edge
Daugiau informacijos rubyonrails.org: Daugiau apie Ruby on Rails

Aktyvusis palaikymas - pagrindiniai plėtiniai

Aktyvusis palaikymas yra Ruby on Rails komponentas, atsakingas už Ruby kalbos plėtinius ir įrankius.

Jis siūlo geresnį kalbos lygmenį, skirtą tiek Rails aplikacijų kūrimui, tiek paties Ruby on Rails kūrimui.

Po šio vadovo perskaitymo, jūs žinosite:

Chapters

  1. Kaip įkelti pagrindinius plėtinius
  2. Plėtiniai visiems objektams
  3. Plėtiniai Module
  4. Plėtiniai Class
  5. Plėtiniai String
  6. Plėtiniai Symbol tipo objektams
  7. Plėtiniai Numeric tipo objektams
  8. Plėtiniai Integer tipui
  9. Plėtiniai BigDecimal tipui
  10. Plėtiniai Enumerable tipui
  11. Plėtiniai Array
  12. Plėtiniai Hash tipo objektui
  13. Plėtiniai Regexp
  14. Plėtiniai Range
  15. Plėtiniai Date
  16. Plėtiniai DateTime
  17. Time plėtinių
  18. File plėtiniai
  19. NameError plėtiniai
  20. Plėtiniai LoadError
  21. Plėtiniai Pathname

1 Kaip įkelti pagrindinius plėtinius

1.1 Stand-alone Aktyvusis palaikymas

Norint turėti kuo mažesnį numatytąjį atminties našumą, Aktyvusis palaikymas numatytai įkelia minimalias priklausomybes. Jis yra padalintas į mažas dalis, todėl galima įkelti tik norimus plėtinius. Taip pat yra patogūs įėjimo taškai, skirti įkelti susijusius plėtinius vienu metu, netgi viską.

Taigi, po paprasto require:

require "active_support"

bus įkelti tik Aktyvusiojo palaikymo pagrindiniai plėtiniai.

1.1.1 Pasirinktinio apibrėžimo pasirinkimas

Šis pavyzdys parodo, kaip įkelti Hash#with_indifferent_access. Šis plėtinys leidžia konvertuoti Hash į ActiveSupport::HashWithIndifferentAccess, kuris leidžia prieigą prie raktų kaip prie simbolių arba kaip prie eilučių.

{ a: 1 }.with_indifferent_access["a"] # => 1

Kiekvienam vienam kaip pagrindinio plėtinio apibrėžtam metodui šiame vadove yra pastaba, kur nurodoma, kur toks metodas yra apibrėžtas. with_indifferent_access atveju pastaba skaitoma taip:

PASTABA: Apibrėžta active_support/core_ext/hash/indifferent_access.rb.

Tai reiškia, kad jūs galite tai įkelti taip:

require "active_support"
require "active_support/core_ext/hash/indifferent_access"

Aktyvusis palaikymas buvo kruopščiai peržiūrėtas, todėl pasirinkus failą, įkeliamos tik griežtai reikalingos priklausomybės, jei tokių yra.

1.1.2 Grupuotų pagrindinių plėtinių įkėlimas

Kitas lygis yra tiesiog įkelti visus Hash plėtinius. Taisyklės pagalba, SomeClass plėtiniai yra pasiekiami vienu metu, įkeliant active_support/core_ext/some_class.

Taigi, norint įkelti visus Hash plėtinius (įskaitant with_indifferent_access):

require "active_support"
require "active_support/core_ext/hash"

1.1.3 Visų pagrindinių plėtinių įkėlimas

Galbūt norėsite tiesiog įkelti visus pagrindinius plėtinius, tam yra failas:

require "active_support"
require "active_support/core_ext"

1.1.4 Viso Aktyvaus palaikymo įkėlimas

Ir galiausiai, jei norite turėti visą Aktyvųjį palaikymą, tiesiog naudokite:

require "active_support/all"

Tai net neįkelia viso Aktyvaus palaikymo į atmintį iš karto, iš tikrųjų, kai kurie dalykai yra sukonfigūruoti per autoload, todėl jie įkeliami tik naudojant.

1.2 Aktyvusis palaikymas Ruby on Rails aplikacijoje

Ruby on Rails aplikacija įkelia visą Aktyvųjį palaikymą, nebent config.active_support.bare yra true. Tokiu atveju aplikacija įkelia tik tai, ką pati sistema pasirenka savo poreikiams, ir vis tiek gali pasirinkti pati, kaip paaiškinta ankstesniame skyriuje.

2 Plėtiniai visiems objektams

2.1 blank? ir present?

Rails aplikacijoje šie reikšmės laikomos tuščiomis:

  • nil ir false,

  • eilutės, sudarytos tik iš tarpų (žr. pastabą žemiau),

  • tuščios masyvai ir žodynai, ir

  • bet koks kitas objektas, kuris atsako į empty? ir yra tuščias.

INFORMACIJA: Eilučių predikatas naudoja Unikodo sąmoningą simbolių klasę [:space:], todėl pavyzdžiui U+2029 (pastraipos skirtukas) laikomas tarpais. ĮSPĖJIMAS: Atkreipkite dėmesį, kad čia nėra paminėti skaičiai. Ypač, 0 ir 0.0 nėra tušti.

Pavyzdžiui, ši ActionController::HttpAuthentication::Token::ControllerMethods klasės metodas naudoja blank? tikrinimui, ar yra pateiktas ženklas:

def authenticate(controller, &login_procedure)
  token, options = token_and_options(controller.request)
  unless token.blank?
    login_procedure.call(token, options)
  end
end

Metodas present? yra ekvivalentus !blank?. Šis pavyzdys paimtas iš ActionDispatch::Http::Cache::Response klasės:

def set_conditional_cache_control!
  return if self["Cache-Control"].present?
  # ...
end

PASTABA: Apibrėžta active_support/core_ext/object/blank.rb faile.

2.2 presence

presence metodas grąžina savo gavėją, jei present?, ir nil kitu atveju. Tai naudinga idiomoms, panašioms į šią:

host = config[:host].presence || 'localhost'

PASTABA: Apibrėžta active_support/core_ext/object/blank.rb faile.

2.3 duplicable?

Nuo Ruby 2.5 dauguma objektų gali būti kopijuojami naudojant dup arba clone:

"foo".dup           # => "foo"
"".dup              # => ""
Rational(1).dup     # => (1/1)
Complex(0).dup      # => (0+0i)
1.method(:+).dup    # => TypeError (allocator undefined for Method)

Active Support teikia duplicable? metodą, skirtą užklausti objektą apie tai:

"foo".duplicable?           # => true
"".duplicable?              # => true
Rational(1).duplicable?     # => true
Complex(1).duplicable?      # => true
1.method(:+).duplicable?    # => false

ĮSPĖJIMAS: Bet kuri klasė gali neleisti kopijavimo pašalinant dup ir clone arba iškeliant iš jų išimtis. Todėl tik rescue gali pasakyti, ar duotas objektas yra kopijuojamas. duplicable? priklauso nuo aukščiau pateiktos sąrašo, bet jis yra daug greitesnis nei rescue. Jį naudokite tik jei žinote, kad aukščiau pateiktas sąrašas pakanka jūsų naudojimo atveju.

PASTABA: Apibrėžta active_support/core_ext/object/duplicable.rb faile.

2.4 deep_dup

deep_dup metodas grąžina gilų norimo objekto kopiją. Paprastai, kai kopijuojate objektą, kuris turi kitus objektus, Ruby jų nekopijuoja, todėl sukuria paviršinę objekto kopiją. Jei turite masyvą su eilute, pavyzdžiui, tai atrodytų taip:

array     = ['string']
duplicate = array.dup

duplicate.push 'another-string'

# objektas buvo nukopijuotas, todėl elementas buvo pridėtas tik prie kopijos
array     # => ['string']
duplicate # => ['string', 'another-string']

duplicate.first.gsub!('string', 'foo')

# pirmas elementas nebuvo nukopijuotas, jis bus pakeistas abiejuose masyvuose
array     # => ['foo']
duplicate # => ['foo', 'another-string']

Kaip matote, nukopijuojant Array objektą, gavome kitą objektą, todėl galime jį modifikuoti ir originalus objektas liks nepakeistas. Tačiau tai netaikoma masyvo elementams. Kadangi dup nekopijuoja giliai, eilutė masyve vis dar yra tas pats objektas.

Jei jums reikia gilos objekto kopijos, turėtumėte naudoti deep_dup. Štai pavyzdys:

array     = ['string']
duplicate = array.deep_dup

duplicate.first.gsub!('string', 'foo')

array     # => ['string']
duplicate # => ['foo']

Jei objektas negali būti kopijuojamas, deep_dup tiesiog jį grąžins:

number = 1
duplicate = number.deep_dup
number.object_id == duplicate.object_id   # => true

PASTABA: Apibrėžta active_support/core_ext/object/deep_dup.rb faile.

2.5 try

Kai norite iškviesti metodą objekte tik tuo atveju, jei jis nėra nil, paprasčiausias būdas tai pasiekti yra naudojant sąlyginės instrukcijas, kurios prideda nereikalingą šlamšą. Alternatyva yra naudoti try. try yra panašus į Object#public_send, tik grąžina nil, jei yra išsiųstas į nil. Štai pavyzdys:

# be try
unless @number.nil?
  @number.next
end

# su try
@number.try(:next)

Kitas pavyzdys yra šis kodas iš ActiveRecord::ConnectionAdapters::AbstractAdapter, kur @logger gali būti nil. Matote, kad kodas naudoja try ir vengia nereikalingo patikrinimo.

def log_info(sql, name, ms)
  if @logger.try(:debug?)
    name = '%s (%.1fms)' % [name || 'SQL', ms]
    @logger.debug(format_log_entry(name, sql.squeeze(' ')))
  end
end

try taip pat gali būti iškviestas be argumentų, bet su bloku, kuris bus vykdomas tik tada, jei objektas nėra nil:

@person.try { |p| "#{p.first_name} #{p.last_name}" }

Atkreipkite dėmesį, kad try praryja nėra-metodo klaidas ir grąžina nil vietoj to. Jei norite apsisaugoti nuo klaidų rašyme, naudokite try!:

@number.try(:nest)  # => nil
@number.try!(:nest) # NoMethodError: undefined method `nest' for 1:Integer

Pastaba: Apibrėžta active_support/core_ext/object/try.rb.

2.6 class_eval(*args, &block)

Galite įvertinti kodą bet kurio objekto vienintelės klasės kontekste naudodami class_eval:

class Proc
  def bind(object)
    block, time = self, Time.current
    object.class_eval do
      method_name = "__bind_#{time.to_i}_#{time.usec}"
      define_method(method_name, &block)
      method = instance_method(method_name)
      remove_method(method_name)
      method
    end.bind(object)
  end
end

Pastaba: Apibrėžta active_support/core_ext/kernel/singleton_class.rb.

2.7 acts_like?(duck)

Metodas acts_like? suteikia galimybę patikrinti, ar tam tikra klasė elgiasi kaip kita klasė pagal paprastą konvenciją: klasė, kuri teikia tą pačią sąsają kaip String, apibrėžia

def acts_like_string?
end

tai tik žymeklis, jos kūnas ar grąžinimo reikšmė nėra svarbūs. Tada kliento kodas gali užklausti, ar tam tikra klasė yra tinkama šiam tipui:

some_klass.acts_like?(:string)

Rails turi klases, kurios elgiasi kaip Date ar Time ir laikosi šio kontrakto.

Pastaba: Apibrėžta active_support/core_ext/object/acts_like.rb.

2.8 to_param

Visi objektai Rails atsako į metodą to_param, kuris turėtų grąžinti kažką, kas juos atstovauja kaip reikšmes užklausos eilutėje arba URL fragmentuose.

Pagal numatytuosius nustatymus to_param tiesiog iškviečia to_s:

7.to_param # => "7"

to_param grąžinimo reikšmė neturėtų būti pabėgta:

"Tom & Jerry".to_param # => "Tom & Jerry"

Kelių klasės Rails perrašo šį metodą.

Pavyzdžiui, nil, true ir false grąžina save. Array#to_param iškviečia to_param ant elementų ir sujungia rezultatą su "/":

[0, true, String].to_param # => "0/true/String"

Ypatingai, Rails maršrutizavimo sistema iškviečia to_param ant modelių, kad gautų reikšmę :id vietos rezervuotajam žymekliui. ActiveRecord::Base#to_param grąžina modelio id, bet galite pervardyti šį metodą savo modeliuose. Pavyzdžiui, turint

class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end

gauname:

user_path(@user) # => "/users/357-john-smith"

ĮSPĖJIMAS. Valdikliai turi žinoti apie bet kokį to_param pervardijimą, nes kai toks užklaustas užklausas, "357-john-smith" yra params[:id] reikšmė.

Pastaba: Apibrėžta active_support/core_ext/object/to_param.rb.

2.9 to_query

Metodas to_query sukuria užklausos eilutę, kuri susieja tam tikrą key su to_param grąžinimo reikšme. Pavyzdžiui, turint šią to_param apibrėžtį:

class User
  def to_param
    "#{id}-#{name.parameterize}"
  end
end

gauname:

current_user.to_query('user') # => "user=357-john-smith"

Šis metodas pabėga viską, kas reikalinga, tiek raktui, tiek reikšmei:

account.to_query('company[name]')
# => "company%5Bname%5D=Johnson+%26+Johnson"

todėl jo išvestis yra paruošta naudoti užklausos eilutėje. Masyvai grąžina rezultatą, taikant to_query kiekvienam elementui su key[] kaip raktu, ir sujungia rezultatą su "&":

[3.4, -45.6].to_query('sample')
# => "sample%5B%5D=3.4&sample%5B%5D=-45.6"

Taip pat, hash'ai taip pat gali būti panaudojami su to_query, bet su kitokia sintakse. Jei nėra perduodamo argumento, kvietimas generuoja surūšiuotą raktų/vertės priskyrimų seriją, kviečiant to_query(key) jo reikšmes. Tada rezultatas sujungiamas su "&":

{ c: 3, b: 2, a: 1 }.to_query # => "a=1&b=2&c=3"

Metodas Hash#to_query priima pasirinktiną vardų erdvę raktams:

{ id: 89, name: "John Smith" }.to_query('user')
# => "user%5Bid%5D=89&user%5Bname%5D=John+Smith"

PASTABA: Apibrėžta active_support/core_ext/object/to_query.rb.

2.10 with_options

Metodas with_options suteikia būdą išskirti bendrus parametrus iš eilės metodų kvietimų.

Turint numatytąjį parametrų hash'ą, with_options perduoda proxy objektą į bloką. Bloke, metodai, iškviesti per proxy, perduodami gavėjui su sujungtais parametrais. Pavyzdžiui, galite atsikratyti dublikavimo:

class Account < ApplicationRecord
  has_many :customers, dependent: :destroy
  has_many :products,  dependent: :destroy
  has_many :invoices,  dependent: :destroy
  has_many :expenses,  dependent: :destroy
end

šitaip:

class Account < ApplicationRecord
  with_options dependent: :destroy do |assoc|
    assoc.has_many :customers
    assoc.has_many :products
    assoc.has_many :invoices
    assoc.has_many :expenses
  end
end

Toks idiomas taip pat gali perduoti grupavimą skaitytojui. Pavyzdžiui, sakykite, norite išsiųsti naujienlaiškį, kurio kalba priklauso nuo vartotojo. Kažkur pašto siuntėjime galėtumėte grupuoti lokalės priklausančius dalykus šitaip:

I18n.with_options locale: user.locale, scope: "newsletter" do |i18n|
  subject i18n.t :subject
  body    i18n.t :body, user_name: user.name
end

PATARIMAS: Kadangi with_options perduoda kvietimus gavėjui, jie gali būti įdėti vienas į kitą. Kiekvienas įdėjimo lygis sujungs paveldėtus numatytuosius parametrus, be savųjų.

PASTABA: Apibrėžta active_support/core_ext/object/with_options.rb.

2.11 JSON palaikymas

Active Support teikia geresnį to_json įgyvendinimą nei įprastai json gembė Ruby objektams. Tai yra todėl, kad kai kurie klasės, pvz., Hash ir Process::Status, reikalauja specialaus tvarkymo, kad būtų gautas tinkamas JSON atvaizdavimas.

PASTABA: Apibrėžta active_support/core_ext/object/json.rb.

2.12 Egzemplioriaus kintamieji

Active Support teikia keletą metodų, palengvinančių prieigą prie egzemplioriaus kintamųjų.

2.12.1 instance_values

Metodas instance_values grąžina hash'ą, kuris susieja egzemplioriaus kintamųjų pavadinimus be "@" su atitinkamomis reikšmėmis. Raktai yra eilutės:

class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}

PASTABA: Apibrėžta active_support/core_ext/object/instance_variables.rb.

2.12.2 instance_variable_names

Metodas instance_variable_names grąžina masyvą. Kiekvienas pavadinimas įtraukia "@" ženklą.

class C
  def initialize(x, y)
    @x, @y = x, y
  end
end

C.new(0, 1).instance_variable_names # => ["@x", "@y"]

PASTABA: Apibrėžta active_support/core_ext/object/instance_variables.rb.

2.13 Klaidų ir išimčių slopinimas

Metodai silence_warnings ir enable_warnings pakeičia $VERBOSE reikšmę atitinkamai per jų bloką ir po to ją atstatydina:

silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }

Klaidų slopinimas taip pat yra įmanomas naudojant suppress. Šis metodas priima bet kokį išimčių klasės skaičių. Jei išimtis iškyla vykdant bloką ir yra kind_of? bet kurio iš argumentų, suppress ją sugauna ir grąžina tyliai. Kitu atveju išimtis nėra sugaunama: ```ruby

Jei naudotojas yra užrakintas, padidinimas yra prarandamas, tai nėra didelė problema.

suppress(ActiveRecord::StaleObjectError) do current_user.increment! :visits end ```

PASTABA: Apibrėžta active_support/core_ext/kernel/reporting.rb.

2.14 in?

Predikatas in? patikrina, ar objektas yra įtrauktas į kitą objektą. Jei perduotas argumentas neatitinka include? metodo, bus iškelta ArgumentError išimtis.

in? pavyzdžiai:

1.in?([1, 2])        # => true
"lo".in?("hello")   # => true
25.in?(30..50)      # => false
1.in?(1)            # => ArgumentError

PASTABA: Apibrėžta active_support/core_ext/object/inclusion.rb.

3 Plėtiniai Module

3.1 Atributai

3.1.1 alias_attribute

Modelio atributai turi skaitytuvo, rašytojo ir predikato metodus. Galite sukurti modelio atributą, kuriam visi trys metodai yra apibrėžti naudojant alias_attribute metodą. Kaip ir kituose sinonimų kūrimo metodų atveju, naujas pavadinimas yra pirmas argumentas, o senas pavadinimas yra antras (vienas mnemoninis būdas yra tai, kad jie eina tokiu pačiu tvarka, kaip ir priskyrimo atveju):

class User < ApplicationRecord
  # Galite kreiptis į el. pašto stulpelį kaip "login".
  # Tai gali būti prasminga autentifikacijos kodo atveju.
  alias_attribute :login, :email
end

PASTABA: Apibrėžta active_support/core_ext/module/aliasing.rb.

3.1.2 Vidiniai atributai

Kai apibrėžiate atributą klasėje, kuri skirta paveldėti, pavadinimo susidūrimai yra rizika. Tai yra ypatingai svarbu bibliotekoms.

Active Support apibrėžia makrokomandas attr_internal_reader, attr_internal_writer ir attr_internal_accessor. Jos elgiasi kaip jų įmontuoti Ruby attr_* atitikmenys, išskyrus tai, kad jos pavadina pagrindinį egzemplioriaus kintamąjį taip, kad susidūrimai būtų mažiau tikėtini.

Makrokomanda attr_internal yra sinonimas attr_internal_accessor:

# biblioteka
class ThirdPartyLibrary::Crawler
  attr_internal :log_level
end

# kliento kodas
class MyCrawler < ThirdPartyLibrary::Crawler
  attr_accessor :log_level
end

Ankstesniame pavyzdyje gali būti atvejis, kai :log_level nepriklauso bibliotekos viešajai sąsajai ir jis naudojamas tik vystymui. Kliento kodas, nežinodamas apie galimą konfliktą, paveldi ir apibrėžia savo :log_level. Dėka attr_internal nėra susidūrimo.

Pagal numatytuosius nustatymus vidinio egzemplioriaus kintamasis vadinamas su priešakyje esančiu pabraukimu, pvz., @_log_level aukščiau pateiktame pavyzdyje. Tai galima konfigūruoti naudojant Module.attr_internal_naming_format, galite perduoti bet kokį sprintf tipo formatavimo eilutę su priešakyje esančiu @ ir kur nors esančiu %s, kur bus įdėtas pavadinimas. Numatytasis yra "@_%s".

Rails naudoja vidinius atributus keliuose vietose, pavyzdžiui, rodiniams:

module ActionView
  class Base
    attr_internal :captures
    attr_internal :request, :layout
    attr_internal :controller, :template
  end
end

PASTABA: Apibrėžta active_support/core_ext/module/attr_internal.rb.

3.1.3 Modulio atributai

Makrokomandos mattr_reader, mattr_writer ir mattr_accessor yra tokios pačios kaip ir klasės cattr_* makrokomandos. Iš tikrųjų, cattr_* makrokomandos yra tik sinonimai mattr_* makrokomandoms. Žr. Klasės atributai.

Pavyzdžiui, Active Storage žurnalo API yra generuojama naudojant mattr_accessor:

module ActiveStorage
  mattr_accessor :logger
end

PASTABA: Apibrėžta active_support/core_ext/module/attribute_accessors.rb.

3.2 Tėvai

3.2.1 module_parent

Įdėtame vardiniame modulyje esančio module_parent metodas grąžina modulį, kuriame yra atitinkantis konstanta:

module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.module_parent # => X::Y
M.module_parent       # => X::Y

Jei modulis yra anoniminis arba priklauso viršutinei lygybei, module_parent grąžina Object. ĮSPĖJIMAS: Atkreipkite dėmesį, kad šiuo atveju module_parent_name grąžina nil.

PASTABA: Apibrėžta active_support/core_ext/module/introspection.rb faile.

3.2.2 module_parent_name

Metodas module_parent_name sujungtoje vardų modulyje grąžina visiškai kvalifikuotą modulio pavadinimą, kuris yra jo atitinkamo kintamojo viduje:

module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.module_parent_name # => "X::Y"
M.module_parent_name       # => "X::Y"

Viršutiniu lygiu arba anoniminiuose moduliuose module_parent_name grąžina nil.

ĮSPĖJIMAS: Atkreipkite dėmesį, kad šiuo atveju module_parent grąžina Object.

PASTABA: Apibrėžta active_support/core_ext/module/introspection.rb faile.

3.2.3 module_parents

Metodas module_parents iškviečia module_parent gavėją ir juda aukštyn, kol pasiekiamas Object. Šis grandinė grąžinama masyve, nuo apačios iki viršaus:

module X
  module Y
    module Z
    end
  end
end
M = X::Y::Z

X::Y::Z.module_parents # => [X::Y, X, Object]
M.module_parents       # => [X::Y, X, Object]

PASTABA: Apibrėžta active_support/core_ext/module/introspection.rb faile.

3.3 Anoniminiai

Modulis gali turėti arba neturėti pavadinimo:

module M
end
M.name # => "M"

N = Module.new
N.name # => "N"

Module.new.name # => nil

Galite patikrinti, ar modulis turi pavadinimą naudodami predikatą anonymous?:

module M
end
M.anonymous? # => false

Module.new.anonymous? # => true

Atkreipkite dėmesį, kad būti nepasiekiamam nereiškia būti anonimiškam:

module M
end

m = Object.send(:remove_const, :M)

m.anonymous? # => false

tačiau anoniminis modulis apibrėžiamas pagal apibrėžimą yra nepasiekiamas.

PASTABA: Apibrėžta active_support/core_ext/module/anonymous.rb faile.

3.4 Metodų Delegavimas

3.4.1 delegate

Makro delegate siūlo paprastą būdą persiųsti metodus.

Pavyzdžiui, įsivaizduokite, kad vartotojai tam tikroje aplikacijoje turi prisijungimo informaciją User modelyje, o vardą ir kitus duomenis atskirame Profile modelyje:

class User < ApplicationRecord
  has_one :profile
end

Su tokia konfigūracija vartotojo vardą galite gauti per jų profilį, user.profile.name, tačiau būtų patogu vis tiek galėti tiesiogiai pasiekti tokius atributus:

class User < ApplicationRecord
  has_one :profile

  def name
    profile.name
  end
end

Tai daro delegate už jus:

class User < ApplicationRecord
  has_one :profile

  delegate :name, to: :profile
end

Tai yra trumpesnis ir aiškesnis.

Metodas turi būti viešas tikslui.

delegate makras priima kelis metodus:

delegate :name, :age, :address, :twitter, to: :profile

Kai įterpiamas į eilutę, :to parinktis turėtų tapti išraiška, kuri įvertina metodui persiųstą objektą. Paprastai tai yra eilutė arba simbolis. Tokia išraiška įvertinama gavėjo kontekste:

# persiunčia į Rails konstantą
delegate :logger, to: :Rails

# persiunčia į gavėjo klasę
delegate :table_name, to: :class

ĮSPĖJIMAS: Jei :prefix parinktis yra true, tai yra mažiau universalu, žr. žemiau.

Pagal numatytuosius nustatymus, jei delegavimas sukelia NoMethodError ir tikslas yra nil, išimtis yra perduodama. Galite paprašyti, kad vietoj to būtų grąžinamas nil naudojant :allow_nil parinktį:

delegate :name, to: :profile, allow_nil: true

Su :allow_nil kvietimas user.name grąžina nil, jei vartotojas neturi profilio.

prefix parinktis prideda priešdėlį prie sugeneruoto metodo pavadinimo. Tai gali būti patogu, pavyzdžiui, gauti geresnį pavadinimą: ruby delegate :gatvė, to: :adresas, prefix: true

Ankstesnis pavyzdys generuoja adresas_gatvė vietoje gatvė.

ĮSPĖJIMAS: Kadangi šiuo atveju sugeneruoto metodo pavadinimas sudarytas iš tikslinio objekto ir tikslinio metodo pavadinimų, :to parinktis turi būti metodo pavadinimas.

Taip pat galima konfigūruoti pasirinktinį priešdėlį:

delegate :dydis, to: :priedas, prefix: :avataras

Ankstesniame pavyzdyje makro generuoja avataras_dydis vietoje dydis.

Parinktis :private keičia metodų matomumo sritį:

delegate :gimimo_data, to: :profilis, private: true

Perduodami metodai pagal numatytuosius nustatymus yra vieši. Norėdami tai pakeisti, perduokite private: true.

PASTABA: Apibrėžta active_support/core_ext/module/delegation.rb

3.4.2 delegate_missing_to

Įsivaizduokite, kad norite perduoti viską, kas trūksta iš Vartotojo objekto, į Profilio objektą. delegate_missing_to makras leidžia jums tai įgyvendinti lengvai:

class Vartotojas < ApplicationRecord
  has_one :profilis

  delegate_missing_to :profilis
end

Tikslas gali būti bet kas, kas gali būti iškviesta objekte, pvz., objekto kintamieji, metodai, konstantos ir kt. Tik vieši tikslinio objekto metodai yra perduodami.

PASTABA: Apibrėžta active_support/core_ext/module/delegation.rb.

3.5 Metodų persikūrimas

Yra atvejų, kai jums reikia apibrėžti metodą su define_method, bet nežinote, ar toks metodas jau egzistuoja. Jei taip, išspausdinamas įspėjimas, jei jie yra įjungti. Tai nėra didelė problema, bet ir nešvaru.

Metodas redefine_method užkerta kelią galimam įspėjimui, pašalindamas esamą metodą, jei reikia.

Taip pat galite naudoti silence_redefinition_of_method, jei norite apibrėžti pakeitimo metodą patys (pavyzdžiui, naudojant delegate).

PASTABA: Apibrėžta active_support/core_ext/module/redefine_method.rb.

4 Plėtiniai Class

4.1 Klasės atributai

4.1.1 class_attribute

Metodas class_attribute deklaruoja vieną ar daugiau paveldimų klasės atributų, kurie gali būti perrašomi bet kurioje hierarchijos lygyje.

class A
  class_attribute :x
end

class B < A; end

class C < B; end

A.x = :a
B.x # => :a
C.x # => :a

B.x = :b
A.x # => :a
C.x # => :b

C.x = :c
A.x # => :a
B.x # => :b

Pavyzdžiui, ActionMailer::Base apibrėžia:

class_attribute :default_params
self.default_params = {
  mime_version: "1.0",
  charset: "UTF-8",
  content_type: "text/plain",
  parts_order: [ "text/plain", "text/enriched", "text/html" ]
}.freeze

Jie taip pat gali būti pasiekiami ir perrašomi objekto lygyje.

A.x = 1

a1 = A.new
a2 = A.new
a2.x = 2

a1.x # => 1, ateina iš A
a2.x # => 2, perrašyta a2

Rašytojo objekto metodo generavimą galima išvengti nustatant parinktį :instance_writer į false.

module ActiveRecord
  class Base
    class_attribute :table_name_prefix, instance_writer: false, default: "my"
  end
end

Modeliui gali būti naudinga ši parinktis kaip būdas užkirsti kelią masiniam priskyrimui nustatant atributą.

Skaitytojo objekto metodo generavimą galima išvengti nustatant parinktį :instance_reader į false.

class A
  class_attribute :x, instance_reader: false
end

A.new.x = 1
A.new.x # NoMethodError

Patogumui class_attribute taip pat apibrėžia objekto predikatą, kuris yra dvigubas neigimas to, ką grąžina objekto skaitytuvas. Pavyzdžiuose jis būtų pavadintas x?. Kai :instance_reader yra false, egzemplioriaus predikatas grąžina NoMethodError, kaip ir skaitymo metodas.

Jei nenorite egzemplioriaus predikato, perduokite instance_predicate: false, ir jis nebus apibrėžtas.

PASTABA: Apibrėžta active_support/core_ext/class/attribute.rb.

4.1.2 cattr_reader, cattr_writer ir cattr_accessor

Makro cattr_reader, cattr_writer ir cattr_accessor yra analogiški savo attr_* atitikmenims, bet skirti klasėms. Jie inicializuoja klasės kintamąjį į nil, jei jis dar neegzistuoja, ir generuoja atitinkamus klasės metodus, skirtus jį pasiekti:

class MysqlAdapter < AbstractAdapter
  # Generuoja klasės metodus, skirtus pasiekti @@emulate_booleans.
  cattr_accessor :emulate_booleans
end

Taip pat, galite perduoti bloką cattr_*, kad nustatytumėte atributą su numatyta reikšme:

class MysqlAdapter < AbstractAdapter
  # Generuoja klasės metodus, skirtus pasiekti @@emulate_booleans su numatyta reikšme true.
  cattr_accessor :emulate_booleans, default: true
end

Taip pat yra sukuriami egzemplioriaus metodai patogumui, jie yra tiesiog peržiūros į klasės atributą. Taigi, egzemplioriai gali keisti klasės atributą, bet negali jį perrašyti, kaip tai atsitinka su class_attribute (žr. aukščiau). Pavyzdžiui, turint

module ActionView
  class Base
    cattr_accessor :field_error_proc, default: Proc.new { ... }
  end
end

mes galime pasiekti field_error_proc per peržiūras.

Skaitymo egzemplioriaus metodo generavimą galima išvengti nustatant :instance_reader į false, o rašymo egzemplioriaus metodo generavimą galima išvengti nustatant :instance_writer į false. Abu metodai gali būti išvengti nustatant :instance_accessor į false. Visais atvejais reikšmė turi būti tiksliai false, o ne bet kokia klaidinga reikšmė.

module A
  class B
    # Nebus sugeneruotas first_name egzemplioriaus skaitytuvas.
    cattr_accessor :first_name, instance_reader: false
    # Nebus sugeneruotas last_name= egzemplioriaus rašytojas.
    cattr_accessor :last_name, instance_writer: false
    # Nebus sugeneruotas surname egzemplioriaus skaitytuvas arba surname= rašytojas.
    cattr_accessor :surname, instance_accessor: false
  end
end

Modeliui gali būti naudinga nustatyti :instance_accessor į false kaip būdą užkirsti kelią masiniam priskyrimui nustatyti atributą.

PASTABA: Apibrėžta active_support/core_ext/module/attribute_accessors.rb.

4.2 Subklasės ir palikuonys

4.2.1 subclasses

Metodas subclasses grąžina gavėjo subklases:

class C; end
C.subclasses # => []

class B < C; end
C.subclasses # => [B]

class A < B; end
C.subclasses # => [B]

class D < C; end
C.subclasses # => [B, D]

Nenurodoma, kokia tvarka šios klasės yra grąžinamos.

PASTABA: Apibrėžta active_support/core_ext/class/subclasses.rb.

4.2.2 descendants

Metodas descendants grąžina visas klases, kurios yra < nei gavėjas:

class C; end
C.descendants # => []

class B < C; end
C.descendants # => [B]

class A < B; end
C.descendants # => [B, A]

class D < C; end
C.descendants # => [B, A, D]

Nenurodoma, kokia tvarka šios klasės yra grąžinamos.

PASTABA: Apibrėžta active_support/core_ext/class/subclasses.rb.

5 Plėtiniai String

5.1 Išvesties saugumas

5.1.1 Motyvacija

Duomenų įterpimas į HTML šablonus reikalauja papildomos priežiūros. Pavyzdžiui, negalite tiesiog įterpti @review.title į HTML puslapį. Vienas dalykas, jei apžvalgos pavadinimas yra "Flanagan & Matz rules!", išvestis nebus gerai suformuota, nes ampersandas turi būti pakeisti į "&amp;". Be to, priklausomai nuo programos, tai gali būti didelė saugumo spraga, nes vartotojai gali įterpti kenksmingą HTML, nustatydami rankų darbo apžvalgos pavadinimą. Daugiau informacijos apie rizikas dėl tarp svetainių skriptų galite rasti Saugumo vadove.

5.1.2 Saugūs eilutės

Active Support turi sąvoką (html) saugios eilutės. Saugi eilutė yra žymima kaip įterpiama į HTML be jokio pakeitimo. Ji yra patikima, nepriklausomai nuo to, ar ji buvo išvengta ar ne.

Pagal nutylėjimą eilutės laikomos nesaugiomis:

"".html_safe? # => false

Galite gauti saugią eilutę iš esamos naudodami html_safe metodą:

s = "".html_safe
s.html_safe? # => true

Svarbu suprasti, kad html_safe nevykdo jokio išvengimo, tai tik patvirtinimas:

s = "<script>...</script>".html_safe
s.html_safe? # => true
s            # => "<script>...</script>"

Jūsų atsakomybė užtikrinti, kad html_safe būtų tinkamai naudojamas tam tikroje eilutėje.

Jei pridedate prie saugios eilutės, arba vietiniu būdu naudojant concat/<<, arba su +, rezultatas yra saugi eilutė. Nesaugūs argumentai yra išvengiami:

"".html_safe + "<" # => "&lt;"

Saugūs argumentai yra tiesiog pridedami:

"".html_safe + "<".html_safe # => "<"

Šių metodų neturėtumėte naudoti įprastose peržiūrose. Nesaugios reikšmės automatiškai yra išvengiamos:

<%= @review.title %> <%# gerai, išvengiama, jei reikia %>

Norėdami įterpti kažką tiesiogiai, naudokite raw pagalbininką, o ne kviesdami html_safe:

<%= raw @cms.current_template %> <%# įterpia @cms.current_template kaip yra %>

arba, ekvivalentiškai, naudokite <%==:

<%== @cms.current_template %> <%# įterpia @cms.current_template kaip yra %>

raw pagalbininkas jums kviečia html_safe:

def raw(stringish)
  stringish.to_s.html_safe
end

PASTABA: Apibrėžta active_support/core_ext/string/output_safety.rb.

5.1.3 Transformacija

Taisyklės pagalba, išskyrus galbūt sujungimą, kaip paaiškinta aukščiau, bet koks metodas, kuris gali pakeisti eilutę, suteikia jums nesaugią eilutę. Tai yra downcase, gsub, strip, chomp, underscore, ir kt.

Atveju, kai vietinio pakeitimo, pvz., gsub!, gavėjas pats tampa nesaugus.

INFORMACIJA: Saugumo bitas visada yra prarandamas, nepriklausomai nuo to, ar pakeitimas iš tikrųjų kažką pakeitė.

5.1.4 Konversija ir koercija

Kviečiant to_s ant saugios eilutės grąžinama saugi eilutė, bet koercija su to_str grąžina nesaugią eilutę.

5.1.5 Kopijavimas

Kviečiant dup arba clone ant saugių eilučių gaunamos saugios eilutės.

5.2 remove

Metodas remove pašalins visus šablonus:

"Hello World".remove(/Hello /) # => "World"

Taip pat yra destruktyvi versija String#remove!.

PASTABA: Apibrėžta active_support/core_ext/string/filters.rb.

5.3 squish

Metodas squish pašalina pradines ir galines tarpus, ir pakeičia tarpus su vienu tarpeliu:

" \n  foo\n\r \t bar \n".squish # => "foo bar"

Taip pat yra destruktyvi versija String#squish!.

Atkreipkite dėmesį, kad jis tvarko tiek ASCII, tiek Unikodo tarpus.

PASTABA: Apibrėžta active_support/core_ext/string/filters.rb.

5.4 truncate

Metodas truncate grąžina kopiją, kurios ilgis yra sumažintas iki nurodyto length:

"Oh dear! Oh dear! I shall be late!".truncate(20)
# => "Oh dear! Oh dear!..."

Elipsė gali būti pritaikyta su :omission parinktimi:

"Oh dear! Oh dear! I shall be late!".truncate(20, omission: '&hellip;')
# => "Oh dear! Oh &hellip;"

Ypač svarbu pastebėti, kad sutrumpinimas atsižvelgia į išvengimo eilutės ilgį.

Prašykite :separator, kad sutrumpintumėte eilutę natūraliame pertraukime: ```ruby "Oh dear! Oh dear! Aš pavėluosiu!".truncate(18)

=> "Oh dear! Oh dea..."

"Oh dear! Oh dear! Aš pavėluosiu!".truncate(18, separator: ' ')

=> "Oh dear! Oh..."


Parametras `:separator` gali būti reguliariosios išraiškos objektas:

```ruby
"Oh dear! Oh dear! Aš pavėluosiu!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."

Pirmuose pavyzdžiuose "dear" yra pjaunama pirmiausia, bet tada :separator tai neleidžia.

PASTABA: Apibrėžta active_support/core_ext/string/filters.rb.

5.5 truncate_bytes

Metodas truncate_bytes grąžina kopiją savo gavėjo, sumažintą iki daugiausiai bytesize baitų:

"👍👍👍👍".truncate_bytes(15)
# => "👍👍👍…"

Elipsė gali būti pritaikyta su :omission parametru:

"👍👍👍👍".truncate_bytes(15, omission: "🖖")
# => "👍👍🖖"

PASTABA: Apibrėžta active_support/core_ext/string/filters.rb.

5.6 truncate_words

Metodas truncate_words grąžina kopiją savo gavėjo, sumažintą po tam tikro žodžių skaičiaus:

"Oh dear! Oh dear! Aš pavėluosiu!".truncate_words(4)
# => "Oh dear! Oh dear!..."

Elipsė gali būti pritaikyta su :omission parametru:

"Oh dear! Oh dear! Aš pavėluosiu!".truncate_words(4, omission: '&hellip;')
# => "Oh dear! Oh dear!&hellip;"

Prašome perduoti :separator, kad sutrumpintumėte eilutę natūraliame pertraukime:

"Oh dear! Oh dear! Aš pavėluosiu!".truncate_words(3, separator: '!')
# => "Oh dear! Oh dear! Aš pavėluosiu..."

Parametras :separator gali būti reguliariosios išraiškos objektas:

"Oh dear! Oh dear! Aš pavėluosiu!".truncate_words(4, separator: /\s/)
# => "Oh dear! Oh dear!..."

PASTABA: Apibrėžta active_support/core_ext/string/filters.rb.

5.7 inquiry

Metodas inquiry konvertuoja eilutę į StringInquirer objektą, padarant lygybės tikrinimą gražesnį.

"production".inquiry.production? # => true
"active".inquiry.inactive?       # => false

PASTABA: Apibrėžta active_support/core_ext/string/inquiry.rb.

5.8 starts_with? ir ends_with?

Active Support apibrėžia 3-as asmenies sinonimus String#start_with? ir String#end_with?:

"foo".starts_with?("f") # => true
"foo".ends_with?("o")   # => true

PASTABA: Apibrėžta active_support/core_ext/string/starts_ends_with.rb.

5.9 strip_heredoc

Metodas strip_heredoc pašalina įdėtą tekstą.

Pavyzdžiui:

if options[:usage]
  puts <<-USAGE.strip_heredoc
    This command does such and such.

    Supported options are:
      -h         This message
      ...
  USAGE
end

vartotojas matytų naudojimo pranešimą, išlygintą su kairiuoju kraštu.

Techniškai, jis ieško mažiausiai įdėtoje eilutėje visoje eilutėje ir pašalina tokio kiekio pradinius tuščius tarpus.

PASTABA: Apibrėžta active_support/core_ext/string/strip.rb.

5.10 indent

Metodas indent įtraukia eilutes gavėjui:

<<EOS.indent(2)
def some_method
  some_code
end
EOS
# =>
  def some_method
    some_code
  end

Antrasis argumentas, indent_string, nurodo, kokį įtraukimo simbolį naudoti. Numatytoji reikšmė yra nil, kuri nurodo metodui padaryti išsilavinimą, žiūrint į pirmą įdėtąją eilutę, ir jei jos nėra, naudoti tarpą.

"  foo".indent(2)        # => "    foo"
"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
"foo".indent(2, "\t")    # => "\t\tfoo"

Nors indent_string paprastai yra vienas tarpas ar tabuliacija, jis gali būti bet koks simbolis.

Trečiasis argumentas, indent_empty_lines, yra žymeklis, kuris nurodo, ar tuščios eilutės turėtų būti įtrauktos. Numatytoji reikšmė yra false.

"foo\n\nbar".indent(2)            # => "  foo\n\n  bar"
"foo\n\nbar".indent(2, nil, true) # => "  foo\n  \n  bar"

Metodas indent! atlieka įtraukimą vietoje.

PASTABA: Apibrėžta active_support/core_ext/string/indent.rb.

5.11 Prieiga

5.11.1 at(position)

at metodas grąžina eilutės simbolį, esantį pozicijoje position:

"hello".at(0)  # => "h"
"hello".at(4)  # => "o"
"hello".at(-1) # => "o"
"hello".at(10) # => nil

PASTABA: Apibrėžta active_support/core_ext/string/access.rb faile.

5.11.2 from(position)

from metodas grąžina eilutės dalį, pradedant nuo pozicijos position:

"hello".from(0)  # => "hello"
"hello".from(2)  # => "llo"
"hello".from(-2) # => "lo"
"hello".from(10) # => nil

PASTABA: Apibrėžta active_support/core_ext/string/access.rb faile.

5.11.3 to(position)

to metodas grąžina eilutės dalį iki pozicijos position:

"hello".to(0)  # => "h"
"hello".to(2)  # => "hel"
"hello".to(-2) # => "hell"
"hello".to(10) # => "hello"

PASTABA: Apibrėžta active_support/core_ext/string/access.rb faile.

5.11.4 first(limit = 1)

first metodas grąžina eilutės dalį, kuri sudaryta iš pirmųjų limit simbolių.

Kviečiant str.first(n) metodą, jei n > 0, tai yra ekvivalentu str.to(n-1), o jei n == 0, grąžinama tuščia eilutė.

PASTABA: Apibrėžta active_support/core_ext/string/access.rb faile.

5.11.5 last(limit = 1)

last metodas grąžina eilutės dalį, kuri sudaryta iš paskutinių limit simbolių.

Kviečiant str.last(n) metodą, jei n > 0, tai yra ekvivalentu str.from(-n), o jei n == 0, grąžinama tuščia eilutė.

PASTABA: Apibrėžta active_support/core_ext/string/access.rb faile.

5.12 Linksniai

5.12.1 pluralize

pluralize metodas grąžina savo argumento daugiskaitą:

"table".pluralize     # => "tables"
"ruby".pluralize      # => "rubies"
"equipment".pluralize # => "equipment"

Kaip rodo ankstesnis pavyzdys, Active Support žino keletą nereguliarių daugiskaitos formų ir neskaitomų daiktavardžių. Įdiegtos taisyklės gali būti išplėstos config/initializers/inflections.rb faile. Šis failas pagal numatytuosius nustatymus yra generuojamas rails new komandos ir turi instrukcijas komentarų pavidalu.

pluralize metodas taip pat gali priimti pasirinktinį count parametrą. Jei count == 1, grąžinama vienaskaita forma. Kitais count reikšmės atvejais grąžinama daugiskaita forma:

"dude".pluralize(0) # => "dudes"
"dude".pluralize(1) # => "dude"
"dude".pluralize(2) # => "dudes"

Active Record naudoja šį metodą, kad apskaičiuotų numatytąją lentelės pavadinimą, kuris atitinka modelį:

# active_record/model_schema.rb
def undecorated_table_name(model_name)
  table_name = model_name.to_s.demodulize.underscore
  pluralize_table_names ? table_name.pluralize : table_name
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb faile.

5.12.2 singularize

singularize metodas yra pluralize metodo atvirkštinė funkcija:

"tables".singularize    # => "table"
"rubies".singularize    # => "ruby"
"equipment".singularize # => "equipment"

Asociacijos naudoja šį metodą, kad apskaičiuotų atitinkamo numatomo susijusio klasės pavadinimą:

# active_record/reflection.rb
def derive_class_name
  class_name = name.to_s.camelize
  class_name = class_name.singularize if collection?
  class_name
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb faile.

5.12.3 camelize

camelize metodas grąžina savo argumentą camel case formato eilute:

"product".camelize    # => "Product"
"admin_user".camelize # => "AdminUser"

Taisyklės pagalba galima manyti, kad šis metodas transformuoja kelius į Ruby klasės ar modulio pavadinimus, kur slash'ai atskiria vardų erdves:

"backoffice/session".camelize # => "Backoffice::Session"

Pavyzdžiui, Action Pack naudoja šį metodą, kad įkeltų klasę, kuri teikia tam tikrą sesijos saugyklą:

# action_controller/metal/session_management.rb
def session_store=(store)
  @@session_store = store.is_a?(Symbol) ?
    ActionDispatch::Session.const_get(store.to_s.camelize) :
    store
end

camelize metodas priima pasirinktinį argumentą, kuris gali būti :upper (numatytasis) arba :lower. Su paskutiniuoju mažinamas pirmasis raidė:

"visual_effect".camelize(:lower) # => "visualEffect"

Tai gali būti naudinga skaičiuoti metodų pavadinimus kalboje, kuri laikosi šios konvencijos, pavyzdžiui, JavaScript.

Taisyklės pagalba galite manyti, kad camelize yra underscore atvirkštinė funkcija, nors yra atvejų, kai tai netaikoma: "SSLError".underscore.camelize grąžina "SslError". Norint palaikyti tokias situacijas, Active Support leidžia nurodyti akronimus config/initializers/inflections.rb:

ActiveSupport::Inflector.inflections do |inflect|
  inflect.acronym 'SSL'
end

"SSLError".underscore.camelize # => "SSLError"

camelize yra sinonimas camelcase.

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.4 underscore

Metodas underscore veikia atvirkščiai, iš camel case pavadinimų gaunant kelius:

"Product".underscore   # => "product"
"AdminUser".underscore # => "admin_user"

Taip pat pakeičia "::" į "/":

"Backoffice::Session".underscore # => "backoffice/session"

ir supranta mažąsias raides pradžioje:

"visualEffect".underscore # => "visual_effect"

underscore nepriima jokių argumentų.

Rails naudoja underscore gauti mažąsias raides kontrolerio klasėms:

# actionpack/lib/abstract_controller/base.rb
def controller_path
  @controller_path ||= name.delete_suffix("Controller").underscore
end

Pavyzdžiui, ši reikšmė yra ta, kurią gaunate params[:controller].

Taisyklės pagalba galite manyti, kad underscore yra camelize atvirkštinė funkcija, nors yra atvejų, kai tai netaikoma. Pavyzdžiui, "SSLError".underscore.camelize grąžina "SslError".

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.5 titleize

Metodas titleize didina raides gavėjo žodyje:

"alice in wonderland".titleize # => "Alice In Wonderland"
"fermat's enigma".titleize     # => "Fermat's Enigma"

titleize yra sinonimas titlecase.

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.6 dasherize

Metodas dasherize pakeičia pabraukimus gavėjo brūkšneliais:

"name".dasherize         # => "name"
"contact_data".dasherize # => "contact-data"

Modelių XML serijizatorius naudoja šį metodą, kad pakeistų mazgų pavadinimus brūkšneliais:

# active_model/serializers/xml.rb
def reformat_name(name)
  name = name.camelize if camelize?
  dasherize? ? name.dasherize : name
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.7 demodulize

Duodamas eilutės su kvalifikuotu konstantos pavadinimu, demodulize grąžina tikrą konstantos pavadinimą, t. y. dešinįjį jos dalį:

"Product".demodulize                        # => "Product"
"Backoffice::UsersController".demodulize    # => "UsersController"
"Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
"::Inflections".demodulize                  # => "Inflections"
"".demodulize                               # => ""

Pavyzdžiui, Active Record naudoja šį metodą, kad apskaičiuotų counter cache stulpelio pavadinimą:

# active_record/reflection.rb
def counter_cache_column
  if options[:counter_cache] == true
    "#{active_record.name.demodulize.underscore.pluralize}_count"
  elsif options[:counter_cache]
    options[:counter_cache]
  end
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.8 deconstantize

Duodamas eilutės su kvalifikuota konstantos nuoroda, deconstantize pašalina dešinę dalį, paliekant konstantos konteinerio pavadinimą:

"Product".deconstantize                        # => ""
"Backoffice::UsersController".deconstantize    # => "Backoffice"
"Admin::Hotel::ReservationUtils".deconstantize # => "Admin::Hotel"

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.9 parameterize

Metodas parameterize normalizuoja gavėją taip, kad jį būtų galima naudoti gražiuose URL.

"John Smith".parameterize # => "john-smith"
"Kurt Gödel".parameterize # => "kurt-godel"

Norint išlaikyti eilutės raidžių dydį, nustatykite preserve_case argumentą į true. Pagal nutylėjimą, preserve_case yra nustatytas į false.

"John Smith".parameterize(preserve_case: true) # => "John-Smith"
"Kurt Gödel".parameterize(preserve_case: true) # => "Kurt-Godel"

Norint naudoti pasirinktinį skyriklį, pakeiskite separator argumentą.

"John Smith".parameterize(separator: "_") # => "john_smith"
"Kurt Gödel".parameterize(separator: "_") # => "kurt_godel"

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.10 tableize

Metodas tableize yra underscore sekantis pluralize.

"Person".tableize      # => "people"
"Invoice".tableize     # => "invoices"
"InvoiceLine".tableize # => "invoice_lines"

Taisyklės pagalba, tableize grąžina lentelės pavadinimą, kuris atitinka duotą modelį paprastais atvejais. Tikra implementacija Active Record nėra tiesiog tableize, nes ji taip pat demodulizuoja klasės pavadinimą ir patikrina kelias parinktis, kurios gali paveikti grąžinamą eilutę.

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.11 classify

Metodas classify yra tableize atvirkštinis metodas. Jis grąžina klasės pavadinimą, kuris atitinka lentelės pavadinimą:

"people".classify        # => "Person"
"invoices".classify      # => "Invoice"
"invoice_lines".classify # => "InvoiceLine"

Metodas supranta kvalifikuotus lentelės pavadinimus:

"highrise_production.companies".classify # => "Company"

Atkreipkite dėmesį, kad classify grąžina klasės pavadinimą kaip eilutę. Galite gauti faktinį klasės objektą, iškviesdami constantize ant jo, kaip paaiškinta toliau.

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.12 constantize

Metodas constantize išsprendžia konstantos nuorodos išraišką savo gavėjui:

"Integer".constantize # => Integer

module M
  X = 1
end
"M::X".constantize # => 1

Jeigu eilutė neišsiskiria į jokią žinomą konstantą ar jos turinys neteisingas konstantos pavadinimas, constantize iškelia NameError.

Konstantos pavadinimo išsprendimas pagal constantize visada prasideda nuo viršutinio lygio Object, net jei nėra pirminio "::".

X = :in_Object
module M
  X = :in_M

  X                 # => :in_M
  "::X".constantize # => :in_Object
  "X".constantize   # => :in_Object (!)
end

Taigi, tai apskritai nėra ekvivalentu tam, ką Ruby darytų tame pačiame taške, jei būtų įvertinta tikra konstanta.

Pašto testavimo atvejai gauna testuojamą paštą iš testo klasės pavadinimo naudodami constantize:

# action_mailer/test_case.rb
def determine_default_mailer(name)
  name.delete_suffix("Test").constantize
rescue NameError => e
  raise NonInferrableMailerError.new(name)
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.13 humanize

Metodas humanize keičia atributo pavadinimą, kad jis būtų tinkamas rodyti galutiniam vartotojui.

Konkrečiai, jis atlieka šiuos keitimus:

  • Taiko žmogiškus linksniavimo taisykles argumentui.
  • Pašalina pradinius pabraukimus, jei tokie yra.
  • Pašalina "_id" priesagą, jei tokia yra.
  • Pakeičia pabraukimus tarp žodžių tarpu, jei tokie yra.
  • Mažina visus žodžius, išskyrus akronimus.
  • Didina pirmąjį žodį.

Pirmojo žodžio didinimas gali būti išjungtas nustatant :capitalize parinktį į false (pagal nutylėjimą true).

"name".humanize                         # => "Name"
"author_id".humanize                    # => "Author"
"author_id".humanize(capitalize: false) # => "author"
"comments_count".humanize               # => "Comments count"
"_id".humanize                          # => "Id"

Jei "SSL" būtų apibrėžtas kaip akronimas:

'ssl_error'.humanize # => "SSL error"

Pagalbinis metodas full_messages naudoja humanize kaip atsarginę galimybę įtraukti atributo pavadinimus:

def full_messages
  map { |attribute, message| full_message(attribute, message) }
end

def full_message
  # ...
  attr_name = attribute.to_s.tr('.', '_').humanize
  attr_name = @base.class.human_attribute_name(attribute, default: attr_name)
  # ...
end

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.14 foreign_key

Metodas foreign_key iš klasės pavadinimo suteikia svetimos rakto stulpelio pavadinimą. Tam jis demodulizuoja, pabraukia ir prideda "_id":

"User".foreign_key           # => "user_id"
"InvoiceLine".foreign_key    # => "invoice_line_id"
"Admin::Session".foreign_key # => "session_id"

Pereikškite klaidingą argumentą, jei nenorite pabraukti "_id":

"User".foreign_key(false) # => "userid"

Asociacijos naudoja šią metodą, kad nustatytų užsienio raktus, pavyzdžiui, has_one ir has_many tai daro:

# active_record/associations.rb
foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.15 upcase_first

Metodas upcase_first didina pirmąjį simbolį:

"employee salary".upcase_first # => "Employee salary"
"".upcase_first                # => ""

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.12.16 downcase_first

Metodas downcase_first paverčia pirmąjį simbolį mažosiomis raidėmis:

"If I had read Alice in Wonderland".downcase_first # => "if I had read Alice in Wonderland"
"".downcase_first                                  # => ""

PASTABA: Apibrėžta active_support/core_ext/string/inflections.rb.

5.13 Konversijos

5.13.1 to_date, to_time, to_datetime

Metodai to_date, to_time ir to_datetime yra praktiški apvalkalai aplink Date._parse:

"2010-07-27".to_date              # => Tue, 27 Jul 2010
"2010-07-27 23:37:00".to_time     # => 2010-07-27 23:37:00 +0200
"2010-07-27 23:37:00".to_datetime # => Tue, 27 Jul 2010 23:37:00 +0000

to_time priima pasirenkamą argumentą :utc arba :local, nurodantį, kurią laiko juostą norite gauti:

"2010-07-27 23:42:00".to_time(:utc)   # => 2010-07-27 23:42:00 UTC
"2010-07-27 23:42:00".to_time(:local) # => 2010-07-27 23:42:00 +0200

Numatytasis yra :local.

Norėdami gauti daugiau informacijos, kreipkitės į Date._parse dokumentaciją.

Visi trys grąžina nil tuščiems gavėjams.

PASTABA: Apibrėžta active_support/core_ext/string/conversions.rb.

6 Plėtiniai Symbol tipo objektams

6.1 starts_with? ir ends_with?

Active Support apibrėžia 3-as asmenies sinonimus Symbol#start_with? ir Symbol#end_with?:

:foo.starts_with?("f") # => true
:foo.ends_with?("o")   # => true

PASTABA: Apibrėžta active_support/core_ext/symbol/starts_ends_with.rb.

7 Plėtiniai Numeric tipo objektams

7.1 Baitai

Visi skaičiai atsako į šiuos metodus:

Jie grąžina atitinkamą baitų kiekį, naudodami konversijos faktorių 1024:

2.kilobytes   # => 2048
3.megabytes   # => 3145728
3.5.gigabytes # => 3758096384.0
-4.exabytes   # => -4611686018427387904

Vienaskaitos formos yra sinonimai, todėl galite sakyti:

1.megabyte # => 1048576

PASTABA: Apibrėžta active_support/core_ext/numeric/bytes.rb.

7.2 Laikas

Šie metodai:

leidžia deklaruoti ir skaičiuoti laiką, pvz., 45.minutes + 2.hours + 4.weeks. Jų grąžinamos reikšmės taip pat gali būti pridėtos arba atimtos nuo laiko objektų.

Šiuos metodus galima derinti su from_now, ago ir kt., norint gauti tikslų datų skaičiavimą. Pavyzdžiui:

# ekvivalentu Time.current.advance(days: 1)
1.day.from_now

# ekvivalentu Time.current.advance(weeks: 2)
2.weeks.from_now

# ekvivalentu Time.current.advance(days: 4, weeks: 5)
(4.days + 5.weeks).from_now

ĮSPĖJIMAS. Kitoms trukmėms, prašome kreiptis į Integer laiko plėtinius.

PASTABA: Apibrėžta active_support/core_ext/numeric/time.rb.

7.3 Formatavimas

Leidžia formatuoti skaičius įvairiais būdais.

Gauti skaičiaus simbolių eilutės atitikmenį kaip telefono numerį:

5551234.to_fs(:phone)
# => 555-1234
1235551234.to_fs(:phone)
# => 123-555-1234
1235551234.to_fs(:phone, area_code: true)
# => (123) 555-1234
1235551234.to_fs(:phone, delimiter: " ")
# => 123 555 1234
1235551234.to_fs(:phone, area_code: true, extension: 555)
# => (123) 555-1234 x 555
1235551234.to_fs(:phone, country_code: 1)
# => +1-123-555-1234

Gauti skaičiaus simbolių eilutės atitikmenį kaip valiutą:

1234567890.50.to_fs(:currency)                 # => $1,234,567,890.50
1234567890.506.to_fs(:currency)                # => $1,234,567,890.51
1234567890.506.to_fs(:currency, precision: 3)  # => $1,234,567,890.506

Sukurkite skaičiaus eilutinį atvaizdavimą kaip procentą:

100.to_fs(:percentage)
# => 100.000%
100.to_fs(:percentage, precision: 0)
# => 100%
1000.to_fs(:percentage, delimiter: '.', separator: ',')
# => 1.000,000%
302.24398923423.to_fs(:percentage, precision: 5)
# => 302.24399%

Sukurkite skaičiaus eilutinį atvaizdavimą su skirtukais:

12345678.to_fs(:delimited)                     # => 12,345,678
12345678.05.to_fs(:delimited)                  # => 12,345,678.05
12345678.to_fs(:delimited, delimiter: ".")     # => 12.345.678
12345678.to_fs(:delimited, delimiter: ",")     # => 12,345,678
12345678.05.to_fs(:delimited, separator: " ")  # => 12,345,678 05

Sukurkite skaičiaus eilutinį atvaizdavimą su apvalinimu:

111.2345.to_fs(:rounded)                     # => 111.235
111.2345.to_fs(:rounded, precision: 2)       # => 111.23
13.to_fs(:rounded, precision: 5)             # => 13.00000
389.32314.to_fs(:rounded, precision: 0)      # => 389
111.2345.to_fs(:rounded, significant: true)  # => 111

Sukurkite skaičiaus eilutinį atvaizdavimą kaip skaitytino baitų skaičiaus:

123.to_fs(:human_size)                  # => 123 Baitai
1234.to_fs(:human_size)                 # => 1.21 KB
12345.to_fs(:human_size)                # => 12.1 KB
1234567.to_fs(:human_size)              # => 1.18 MB
1234567890.to_fs(:human_size)           # => 1.15 GB
1234567890123.to_fs(:human_size)        # => 1.12 TB
1234567890123456.to_fs(:human_size)     # => 1.1 PB
1234567890123456789.to_fs(:human_size)  # => 1.07 EB

Sukurkite skaičiaus eilutinį atvaizdavimą kaip skaitytino žodžiais:

123.to_fs(:human)               # => "123"
1234.to_fs(:human)              # => "1.23 Tūkstantis"
12345.to_fs(:human)             # => "12.3 Tūkstantis"
1234567.to_fs(:human)           # => "1.23 Milijonas"
1234567890.to_fs(:human)        # => "1.23 Milijardas"
1234567890123.to_fs(:human)     # => "1.23 Trilijonas"
1234567890123456.to_fs(:human)  # => "1.23 Kvadrilijonas"

Pastaba: Apibrėžta active_support/core_ext/numeric/conversions.rb.

8 Plėtiniai Integer tipui

8.1 multiple_of?

Metodas multiple_of? patikrina, ar sveikasis skaičius yra argumento daugiklis:

2.multiple_of?(1) # => true
1.multiple_of?(2) # => false

Pastaba: Apibrėžta active_support/core_ext/integer/multiple.rb.

8.2 ordinal

Metodas ordinal grąžina eilutę su skaitmeniu ir atitinkančiu priesaga:

1.ordinal    # => "st"
2.ordinal    # => "nd"
53.ordinal   # => "rd"
2009.ordinal # => "th"
-21.ordinal  # => "st"
-134.ordinal # => "th"

Pastaba: Apibrėžta active_support/core_ext/integer/inflections.rb.

8.3 ordinalize

Metodas ordinalize grąžina eilutę su skaitmeniu ir atitinkančiu priesaga. Palyginimui, ordinal metodas grąžina tik priesagos eilutę.

1.ordinalize    # => "1st"
2.ordinalize    # => "2nd"
53.ordinalize   # => "53rd"
2009.ordinalize # => "2009th"
-21.ordinalize  # => "-21st"
-134.ordinalize # => "-134th"

Pastaba: Apibrėžta active_support/core_ext/integer/inflections.rb.

8.4 Laikas

Šie metodai:

leidžia deklaruoti ir skaičiuoti laiką, pvz., 4.months + 5.years. Jų grąžinamos reikšmės taip pat gali būti pridėtos arba atimtos nuo laiko objektų.

Šiuos metodus galima derinti su from_now, ago ir pan., siekiant tikslaus datos skaičiavimo. Pavyzdžiui:

# ekvivalentu Time.current.advance(months: 1)
1.month.from_now

# ekvivalentu Time.current.advance(years: 2)
2.years.from_now

# ekvivalentu Time.current.advance(months: 4, years: 5)
(4.months + 5.years).from_now

ĮSPĖJIMAS. Kitoms trukmėms kreipkitės į Numeric laiko plėtinius.

Pastaba: Apibrėžta active_support/core_ext/integer/time.rb.

9 Plėtiniai BigDecimal tipui

9.1 to_s

Metodas to_s numatytuoju parametru naudoja "F" formatą. Tai reiškia, kad paprastas to_s iškvietimas grąžins slankiojo kablelio atvaizdavimą, o ne inžinerinį įrašą:

BigDecimal(5.00, 6).to_s       # => "5.0"

Vis dar galima naudoti inžinerinį įrašą:

BigDecimal(5.00, 6).to_s("e")  # => "0.5E1"

10 Plėtiniai Enumerable tipui

10.1 sum

Metodas sum sudeda elementus iš eilės: ruby [1, 2, 3].sum # => 6 (1..100).sum # => 5050

Sudėtis priima tik elementus, kurie gali atlikti veiksmą +:

[[1, 2], [2, 3], [3, 4]].sum    # => [1, 2, 2, 3, 3, 4]
%w(foo bar baz).sum             # => "foobarbaz"
{ a: 1, b: 2, c: 3 }.sum          # => [:a, 1, :b, 2, :c, 3]

Tuščios kolekcijos suma pagal nutylėjimą yra nulis, tačiau tai galima keisti:

[].sum    # => 0
[].sum(1) # => 1

Jeigu yra pateiktas blokas, sum tampa iteratoriumi, kuris grąžina kolekcijos elementus ir sudeda grąžintas reikšmes:

(1..5).sum { |n| n * 2 } # => 30
[2, 4, 6, 8, 10].sum    # => 30

Tuščios gavėjo sumos taip pat galima keisti šioje formoje:

[].sum(1) { |n| n**3 } # => 1

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.2 index_by

Metodas index_by sugeneruoja raktų ir reikšmių poras, kur raktai yra kažkokio raktinio žodžio pagal indeksą.

Jis peržiūri kolekciją ir perduoda kiekvieną elementą blokui. Elementas bus raktas, grąžintas bloko:

invoices.index_by(&:number)
# => {'2009-032' => <Invoice ...>, '2009-008' => <Invoice ...>, ...}

ĮSPĖJIMAS. Raktai paprastai turėtų būti unikalūs. Jei blokas grąžina tą pačią reikšmę skirtingiems elementams, tokiu atveju nebus sukurtas joks rinkinys šiam raktui. Laimi paskutinis elementas.

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.3 index_with

Metodas index_with sugeneruoja raktų ir reikšmių poras, kur raktai yra kolekcijos elementai. Reikšmė yra arba perduotas numatytasis arba grąžinamas bloke.

post = Post.new(title: "hey there", body: "what's up?")

%i( title body ).index_with { |attr_name| post.public_send(attr_name) }
# => { title: "hey there", body: "what's up?" }

WEEKDAYS.index_with(Interval.all_day)
# => { monday: [ 0, 1440 ], … }

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.4 many?

Metodas many? yra trumpinys collection.size > 1:

<% if pages.many? %>
  <%= pagination_links %>
<% end %>

Jeigu yra pateiktas pasirinktinis blokas, many? atsižvelgia tik į tuos elementus, kurie grąžina true:

@see_more = videos.many? { |video| video.category == params[:category] }

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.5 exclude?

Predikatas exclude? patikrina, ar duotas objektas ne priklauso kolekcijai. Tai yra įprasto include? neigimas:

to_visit << node if visited.exclude?(node)

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.6 including

Metodas including grąžina naują kolekciją, kuri įtraukia perduotus elementus:

[ 1, 2, 3 ].including(4, 5)                    # => [ 1, 2, 3, 4, 5 ]
["David", "Rafael"].including %w[ Aaron Todd ] # => ["David", "Rafael", "Aaron", "Todd"]

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.7 excluding

Metodas excluding grąžina kopiją kolekcijos su pašalintais nurodytais elementais:

["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]

excluding yra sinonimas without.

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.8 pluck

Metodas pluck išskiria nurodytą raktą iš kiekvieno elemento:

[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name) # => ["David", "Rafael", "Aaron"]
[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name) # => [[1, "David"], [2, "Rafael"]]

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

10.9 pick

Metodas pick ištraukia nurodytą raktą iš pirmojo elemento:

[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name) # => "David"
[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name) # => [1, "David"]

PASTABA: Apibrėžta active_support/core_ext/enumerable.rb.

11 Plėtiniai Array

11.1 Prieiga

Active Support papildo masyvų API, kad būtų lengviau pasiekti tam tikrus jų elementus. Pavyzdžiui, to grąžina submasyvą, kuris apima elementus iki nurodyto indekso:

%w(a b c d).to(2) # => ["a", "b", "c"]
[].to(7)          # => []

Panašiai, from grąžina užpakalį nuo nurodyto indekso iki galo. Jei indeksas yra didesnis nei masyvo ilgis, grąžinamas tuščias masyvas.

%w(a b c d).from(2)  # => ["c", "d"]
%w(a b c d).from(10) # => []
[].from(0)           # => []

Metodas including grąžina naują masyvą, kuriame yra nurodyti elementai:

[ 1, 2, 3 ].including(4, 5)          # => [ 1, 2, 3, 4, 5 ]
[ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]

Metodas excluding grąžina kopiją masyvo, išskyrus nurodytus elementus. Tai yra Enumerable#excluding optimizacija, kuri naudoja Array#- vietoje Array#reject dėl našumo priežasčių.

["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
[ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ])                  # => [ [ 0, 1 ] ]

Metodai second, third, fourth ir fifth grąžina atitinkamą elementą, taip pat second_to_last ir third_to_last (first ir last yra įdiegti). Dėka socialinio išmintingumo ir teigiamo konstruktyvumo visur, forty_two taip pat yra prieinamas.

%w(a b c d).third # => "c"
%w(a b c d).fifth # => nil

PASTABA: Apibrėžta active_support/core_ext/array/access.rb.

11.2 Ištraukimas

Metodas extract! pašalina ir grąžina elementus, kuriems blokas grąžina teisingą reikšmę. Jei nėra nurodytas blokas, grąžinamas vietoj to yra Enumeratorius.

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
numbers # => [0, 2, 4, 6, 8]

PASTABA: Apibrėžta active_support/core_ext/array/extract.rb.

11.3 Parinkčių ištraukimas

Kai paskutinis argumentas metodo iškvietime yra hash'as, išskyrus galbūt &block argumentą, Ruby leidžia jums praleisti skliaustus:

User.exists?(email: params[:email])

Toks sintaksinis cukrus dažnai naudojamas Rails'e, kad būtų išvengta pozicinių argumentų, kai jų būtų per daug, o vietoj to siūlomi sąsajos, kurios imituoja vardinius parametrus. Ypač idiomatiška yra naudoti užbaigtinį hash'ą parinktims.

Jei metodas tikisi kintamo skaičiaus argumentų ir jo deklaracijoje naudoja *, tokiame parinkčių hash'as tampa argumentų masyvo elementu, kur jis praranda savo vaidmenį.

Tokiu atveju galite suteikti parinkčių hash'ui išskirtinį apdorojimą naudodami extract_options!. Šis metodas patikrina masyvo paskutinio elemento tipą. Jei tai yra hash'as, jis išimamas ir grąžinamas, kitu atveju grąžinamas tuščias hash'as. Pavyzdžiui, pažvelkime į caches_action valdiklio makro apibrėžimą:

def caches_action(*actions)
  return unless cache_configured?
  options = actions.extract_options!
  # ...
end

Šis metodas priima bet kokį veiksmo pavadinimų skaičių ir pasirinktiną raktų hash'ą kaip paskutinį argumentą. Iškvietus extract_options! gaunate raktų hash'ą ir pašalinamas iš actions paprastu ir aiškiu būdu.

PASTABA: Apibrėžta active_support/core_ext/array/extract_options.rb.

11.4 Konvertavimai

11.4.1 to_sentence

Metodas to_sentence paverčia masyvą į eilutę, kurioje išvardijami jo elementai:

%w().to_sentence                # => ""
%w(Earth).to_sentence           # => "Earth"
%w(Earth Wind).to_sentence      # => "Earth and Wind"
%w(Earth Wind Fire).to_sentence # => "Earth, Wind, and Fire"

Šis metodas priima tris pasirinktinius parametrus:

  • :two_words_connector: Naudojama masyvams, turintiems 2 elementus. Numatytasis yra " and ".
  • :words_connector: Naudojama sujungti masyvo elementus, turinčius 3 ar daugiau elementų, išskyrus paskutinius du. Numatytasis yra ", ".
  • :last_word_connector: Naudojama sujungti paskutinius masyvo elementus, turinčius 3 ar daugiau elementų. Numatytasis yra ", and ".

Šių parametrų numatytieji nustatymai gali būti lokalizuoti, jų raktai yra:

Parametras I18n raktas
:two_words_connector support.array.two_words_connector
:words_connector support.array.words_connector
:last_word_connector support.array.last_word_connector

PASTABA: Apibrėžta active_support/core_ext/array/conversions.rb.

11.4.2 to_fs

Metodas to_fs pagal numatytuosius nustatymus veikia kaip to_s.

Tačiau, jei masyvas turi elementus, kurie gali atsakyti į id, simbolis :db gali būti perduotas kaip argumentas. Tai dažnai naudojama su Active Record objektų kolekcijomis. Grąžinamos eilutės yra:

[].to_fs(:db)            # => "null"
[user].to_fs(:db)        # => "8456"
invoice.lines.to_fs(:db) # => "23,567,556,12"

Pavyzdžio aukščiau esantys sveikieji skaičiai turėtų būti gauti iš atitinkamų id iškvietimų.

PASTABA: Apibrėžta active_support/core_ext/array/conversions.rb.

11.4.3 to_xml

Metodas to_xml grąžina eilutę, kuri yra jo gavėjo XML atvaizdavimas:

Contributor.limit(2).order(:rank).to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors type="array">
#   <contributor>
#     <id type="integer">4356</id>
#     <name>Jeremy Kemper</name>
#     <rank type="integer">1</rank>
#     <url-id>jeremy-kemper</url-id>
#   </contributor>
#   <contributor>
#     <id type="integer">4404</id>
#     <name>David Heinemeier Hansson</name>
#     <rank type="integer">2</rank>
#     <url-id>david-heinemeier-hansson</url-id>
#   </contributor>
# </contributors>

Tam jis išsiunčia to_xml kiekvienam elementui iš eilės ir surinkia rezultatus po šakniniu mazgu. Visi elementai turi atsakyti į to_xml, kitu atveju iškeliama išimtis.

Numatytasis šakninio elemento pavadinimas yra pirmojo elemento klasės pavadinimo su pabraukimu ir brūkšneliu daugiskaita, jei likusieji elementai priklauso tam pačiam tipui (patikrinama su is_a?) ir jie nėra hash'ai. Pavyzdyje aukščiau tai yra "contributors".

Jei yra bent vienas elementas, kuris nepriklauso pirmojo elemento tipui, šakninis mazgas tampa "objects":

[Contributor.first, Commit.first].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
#   <object>
#     <id type="integer">4583</id>
#     <name>Aaron Batalion</name>
#     <rank type="integer">53</rank>
#     <url-id>aaron-batalion</url-id>
#   </object>
#   <object>
#     <author>Joshua Peek</author>
#     <authored-timestamp type="datetime">2009-09-02T16:44:36Z</authored-timestamp>
#     <branch>origin/master</branch>
#     <committed-timestamp type="datetime">2009-09-02T16:44:36Z</committed-timestamp>
#     <committer>Joshua Peek</committer>
#     <git-show nil="true"></git-show>
#     <id type="integer">190316</id>
#     <imported-from-svn type="boolean">false</imported-from-svn>
#     <message>Kill AMo observing wrap_with_notifications since ARes was only using it</message>
#     <sha1>723a47bfb3708f968821bc969a9a3fc873a3ed58</sha1>
#   </object>
# </objects>

Jei gavėjas yra maišų masyvas, pagrindinis elementas pagal numatytuosius nustatymus taip pat yra "objects":

[{ a: 1, b: 2 }, { c: 3 }].to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
#   <object>
#     <b type="integer">2</b>
#     <a type="integer">1</a>
#   </object>
#   <object>
#     <c type="integer">3</c>
#   </object>
# </objects>

ĮSPĖJIMAS. Jei kolekcija yra tuščia, pagal numatytuosius nustatymus pagrindinis elementas yra "nil-classes". Tai yra gudrybė, pavyzdžiui, aukščiau pateikto kontributorių sąrašo pagrindinis elementas nebūtų "contributors", jei kolekcija būtų tuščia, bet "nil-classes". Galite naudoti :root parinktį, kad būtų užtikrintas nuoseklus pagrindinis elementas.

Vaikų mazgų pavadinimas pagal numatytuosius nustatymus yra pagrindinio mazgo pavadinimas vienaskaita. Aukščiau pateiktuose pavyzdžiuose matėme "contributor" ir "object". :children parinktis leidžia nustatyti šiuos mazgų pavadinimus.

Numatytasis XML kūrėjas yra naujas Builder::XmlMarkup egzempliorius. Galite konfigūruoti savo kūrėją per :builder parinktį. Metodas taip pat priima parinktis, pvz., :dasherize ir kt., kurios perduodamos kūrėjui:

Contributor.limit(2).order(:rank).to_xml(skip_types: true)
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <contributors>
#   <contributor>
#     <id>4356</id>
#     <name>Jeremy Kemper</name>
#     <rank>1</rank>
#     <url-id>jeremy-kemper</url-id>
#   </contributor>
#   <contributor>
#     <id>4404</id>
#     <name>David Heinemeier Hansson</name>
#     <rank>2</rank>
#     <url-id>david-heinemeier-hansson</url-id>
#   </contributor>
# </contributors>

PASTABA: Apibrėžta active_support/core_ext/array/conversions.rb.

11.5 Apvyniojimas

Metodas Array.wrap apvynioja savo argumentą į masyvą, nebent jis jau yra masyvas (arba panašus į masyvą).

Konkrečiai:

  • Jei argumentas yra nil, grąžinamas tuščias masyvas.
  • Kitu atveju, jei argumentas gali būti iššauktas to_ary, jis iššaukiamas, ir jei to_ary grąžinimo reikšmė nėra nil, ji grąžinama.
  • Kitu atveju, grąžinamas masyvas su argumentu kaip vieninteliu elementu.
Array.wrap(nil)       # => []
Array.wrap([1, 2, 3]) # => [1, 2, 3]
Array.wrap(0)         # => [0]

Šis metodas panašus į Kernel#Array tikslais, tačiau yra kai kurie skirtumai:

  • Jei argumentas gali būti iššauktas to_ary, metodas yra iššaukiamas. Kernel#Array tęsia bandymą iššaukti to_a, jei grąžinta reikšmė yra nil, bet Array.wrap iš karto grąžina masyvą su argumentu kaip vieninteliu elementu.
  • Jei grąžinta reikšmė iš to_ary nėra nei nil, nei Array objektas, Kernel#Array iškelia išimtį, o Array.wrap to nedaro, ji tiesiog grąžina reikšmę.
  • Jei argumentas neatsako į to_ary, ji nekviečia to_a ir grąžina masyvą su argumentu kaip vieninteliu elementu.

Ypač verta palyginti paskutinį punktą kai kuriems išvardijimams:

Array.wrap(foo: :bar) # => [{:foo=>:bar}]
Array(foo: :bar)      # => [[:foo, :bar]]

Taip pat yra susijusi idiomatika, kuri naudoja splat operatorių:

[*object]

PASTABA: Apibrėžta active_support/core_ext/array/wrap.rb.

11.6 Kopijavimas

Metodas Array#deep_dup dubliuoja save ir visus objektus viduje rekursyviai su Active Support metodu Object#deep_dup. Tai veikia kaip Array#map, siunčiant deep_dup metodą kiekvienam objektui viduje.

array = [1, [2, 3]]
dup = array.deep_dup
dup[1][2] = 4
array[1][2] == nil   # => true

PASTABA: Apibrėžta active_support/core_ext/object/deep_dup.rb.

11.7 Grupavimas

11.7.1 in_groups_of(skaičius, užpildyti = nil)

Metodas in_groups_of padalina masyvą į nuoseklius grupes, kurių dydis yra nurodytas. Jis grąžina masyvą su grupėmis:

[1, 2, 3].in_groups_of(2) # => [[1, 2], [3, nil]]

arba perduoda jas vieną po kito, jei perduodamas blokas:

<% sample.in_groups_of(3) do |a, b, c| %>
  <tr>
    <td><%= a %></td>
    <td><%= b %></td>
    <td><%= c %></td>
  </tr>
<% end %>

Pirmas pavyzdys parodo, kaip in_groups_of užpildo paskutinę grupę tiek nil elementais, kiek reikia, kad būtų pasiektas pageidaujamas dydis. Galite pakeisti šį užpildymo reikšmę naudodami antrąjį pasirinktinį argumentą:

[1, 2, 3].in_groups_of(2, 0) # => [[1, 2], [3, 0]]

Ir galite pasakyti metodui, kad paskutinė grupė neturi būti užpildyta, perduodant false:

[1, 2, 3].in_groups_of(2, false) # => [[1, 2], [3]]

Dėl to false negali būti naudojama kaip užpildymo reikšmė.

PASTABA: Apibrėžta active_support/core_ext/array/grouping.rb.

11.7.2 in_groups(skaičius, užpildyti = nil)

Metodas in_groups padalina masyvą į tam tikrą grupių skaičių. Metodas grąžina masyvą su grupėmis:

%w(1 2 3 4 5 6 7).in_groups(3)
# => [["1", "2", "3"], ["4", "5", nil], ["6", "7", nil]]

arba perduoda jas vieną po kito, jei perduodamas blokas:

%w(1 2 3 4 5 6 7).in_groups(3) { |group| p group }
["1", "2", "3"]
["4", "5", nil]
["6", "7", nil]

Aukščiau pateikti pavyzdžiai rodo, kad in_groups užpildo kai kurias grupes papildomu nil elementu, jei reikia. Grupė gali gauti ne daugiau kaip vieną šio papildomo elemento, jei toks yra. Ir grupės, kuriose jie yra, visada yra paskutinės.

Galite pakeisti šią užpildymo reikšmę naudodami antrąjį pasirinktinį argumentą:

%w(1 2 3 4 5 6 7).in_groups(3, "0")
# => [["1", "2", "3"], ["4", "5", "0"], ["6", "7", "0"]]

Ir galite pasakyti metodui, kad mažesnės grupės neturi būti užpildytos, perduodant false:

%w(1 2 3 4 5 6 7).in_groups(3, false)
# => [["1", "2", "3"], ["4", "5"], ["6", "7"]]

Dėl to false negali būti naudojama kaip užpildymo reikšmė.

PASTABA: Apibrėžta active_support/core_ext/array/grouping.rb.

11.7.3 split(reikšmė = nil)

Metodas split padalina masyvą pagal skyriklį ir grąžina rezultatą.

Jei perduodamas blokas, skyrikliai yra tie masyvo elementai, kuriems blokas grąžina true:

(-5..5).to_a.split { |i| i.multiple_of?(4) }
# => [[-5], [-3, -2, -1], [1, 2, 3], [5]]

Kitu atveju, argumentas, kuris pagal nutylėjimą yra nil, yra skyriklis:

[0, 1, -5, 1, 1, "foo", "bar"].split(1)
# => [[0], [-5], [], ["foo", "bar"]]

PATARIMAS: Pastebėkite ankstesniame pavyzdyje, kad iš eilės esantys skyrikliai rezultuoja tuščius masyvus.

PASTABA: Apibrėžta active_support/core_ext/array/grouping.rb.

12 Plėtiniai Hash tipo objektui

12.1 Konversijos

12.1.1 to_xml

Metodas to_xml grąžina eilutę, kurią sudaro jo gavėjo XML reprezentacija:

{ foo: 1, bar: 2 }.to_xml
# =>
# <?xml version="1.0" encoding="UTF-8"?>
# <hash>
#   <foo type="integer">1</foo>
#   <bar type="integer">2</bar>
# </hash>

Tam, kad tai padarytumėte, metodas kartojasi per poras ir sukuria priklausomas nuo reikšmių mazgas. Turint porą key, value:

  • Jei value yra hash, vykdomas rekursinis kvietimas su key kaip :root.

  • Jei value yra masyvas, vykdomas rekursinis kvietimas su key kaip :root, ir key vienaskaitinė forma kaip :children.

  • Jei value yra kviečiamas objektas, jis turi tikėtis vieno ar dviejų argumentų. Priklausomai nuo argumentų skaičiaus, kviečiamas objektas yra iškviečiamas su options hash kaip pirmu argumentu su key kaip :root, ir key vienaskaitinė forma kaip antru argumentu. Jo grąžinimo reikšmė tampa nauju mazgu.

  • Jei value atsako į to_xml, kviečiamas metodas su key kaip :root.

  • Kitu atveju, sukuriamas mazgas su key kaip žyma ir value teksto mazgu kaip jo teksto reprezentacija. Jei value yra nil, pridedamas atributas "nil" su reikšme "true". Jei neegzistuoja :skip_types parinktis ir ji yra true, taip pat pridedamas atributas "type" pagal šią sąrašą:

XML_TYPE_NAMES = {
  "Symbol"     => "symbol",
  "Integer"    => "integer",
  "BigDecimal" => "decimal",
  "Float"      => "float",
  "TrueClass"  => "boolean",
  "FalseClass" => "boolean",
  "Date"       => "date",
  "DateTime"   => "datetime",
  "Time"       => "datetime"
}

Pagal numatytuosius nustatymus šakninis mazgas yra "hash", bet tai galima konfigūruoti naudojant :root parinktį.

Numatytasis XML kūrėjas yra naujas Builder::XmlMarkup objekto egzempliorius. Galite konfigūruoti savo kūrėją naudojant :builder parinktį. Metodas taip pat priima parinktis, pvz., :dasherize ir kt., kurios perduodamos kūrėjui.

PASTABA: Apibrėžta active_support/core_ext/hash/conversions.rb faile.

12.2 Sujungimas

Ruby turi įmontuotą Hash#merge metodą, kuris sujungia du hash'us:

{ a: 1, b: 1 }.merge(a: 0, c: 2)
# => {:a=>0, :b=>1, :c=>2}

Active Support apibrėžia keletą papildomų būdų, kaip sujungti hash'us, kas gali būti patogu.

12.2.1 reverse_merge ir reverse_merge!

Atveju, kai įvyksta susidūrimas, merge metode laimi argumento hash'o raktas. Galite palaikyti parinkčių hash'us su numatytosiomis reikšmėmis kompaktiškai naudodami šią idiomą:

options = { length: 30, omission: "..." }.merge(options)

Active Support apibrėžia reverse_merge atveju, jei pageidaujate šios alternatyvios sintaksės:

options = options.reverse_merge(length: 30, omission: "...")

Taip pat yra bang versija reverse_merge!, kuri atlieka sujungimą vietoje:

options.reverse_merge!(length: 30, omission: "...")

ĮSPĖJIMAS. Atkreipkite dėmesį, kad reverse_merge! gali pakeisti hash'ą iškvietėjoje, kas gali būti gera arba ne.

PASTABA: Apibrėžta active_support/core_ext/hash/reverse_merge.rb faile.

12.2.2 reverse_update

Metodas reverse_update yra sinonimas reverse_merge!, kuris buvo paaiškintas aukščiau.

ĮSPĖJIMAS. Atkreipkite dėmesį, kad reverse_update neturi bang simbolio.

PASTABA: Apibrėžta active_support/core_ext/hash/reverse_merge.rb faile.

12.2.3 deep_merge ir deep_merge!

Kaip matote ankstesniame pavyzdyje, jei raktas yra rastas abiejuose hash'uose, reikšmė iš argumento hash'o laimi.

Active Support apibrėžia Hash#deep_merge. Gilyn sujungiant, jei raktas yra rastas abiejuose hash'uose ir jų reikšmės yra vėl hash'ai, tada jų sujungimas tampa rezultuojančio hash'o reikšme:

{ a: { b: 1 } }.deep_merge(a: { c: 2 })
# => {:a=>{:b=>1, :c=>2}}

Metodas deep_merge! atlieka gilų sujungimą vietoje.

PASTABA: Apibrėžta active_support/core_ext/hash/deep_merge.rb.

12.3 Gilus kopijavimas

Metodas Hash#deep_dup dubliuoja save ir visus raktus bei reikšmes rekursyviai naudojant Active Support metodo Object#deep_dup. Jis veikia kaip Enumerator#each_with_object, siunčiant deep_dup metodą kiekvienam porai viduje.

hash = { a: 1, b: { c: 2, d: [3, 4] } }

dup = hash.deep_dup
dup[:b][:e] = 5
dup[:b][:d] << 5

hash[:b][:e] == nil      # => true
hash[:b][:d] == [3, 4]   # => true

PASTABA: Apibrėžta active_support/core_ext/object/deep_dup.rb.

12.4 Darbas su raktų

12.4.1 except ir except!

Metodas except grąžina raktus, esančius argumentų sąraše, pašalintus iš hash, jei jie yra:

{ a: 1, b: 2 }.except(:a) # => {:b=>2}

Jei gavėjas atsako į convert_key, metodas yra iškviestas kiekvienam iš argumentų. Tai leidžia except gerai veikti su hash, kuris turi abejotiną prieigą, pavyzdžiui:

{ a: 1 }.with_indifferent_access.except(:a)  # => {}
{ a: 1 }.with_indifferent_access.except("a") # => {}

Taip pat yra bang variantas except!, kuris pašalina raktus vietoje.

PASTABA: Apibrėžta active_support/core_ext/hash/except.rb.

12.4.2 stringify_keys ir stringify_keys!

Metodas stringify_keys grąžina hash, kuriame yra raktų, esančių gavėjui, sustringifikuota versija. Tai daroma siunčiant jiems to_s:

{ nil => nil, 1 => 1, a: :a }.stringify_keys
# => {"" => nil, "1" => 1, "a" => :a}

Atveju, kai yra raktų susidūrimas, reikšmė bus naujausia įterpta į hash:

{ "a" => 1, a: 2 }.stringify_keys
# Rezultatas bus
# => {"a"=>2}

Šis metodas gali būti naudingas, pavyzdžiui, lengvai priimti tiek simbolius, tiek eilutes kaip parinktis. Pavyzdžiui, ActionView::Helpers::FormHelper apibrėžia:

def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0")
  options = options.stringify_keys
  options["type"] = "checkbox"
  # ...
end

Antra eilutė saugiai gali pasiekti "type" raktą ir leisti vartotojui perduoti :type arba "type".

Taip pat yra bang variantas stringify_keys!, kuris vietoje sustringifikuoti raktus.

Be to, galima naudoti deep_stringify_keys ir deep_stringify_keys!, kad sustringifikuotumėte visus raktus duotame hashe ir visuose jame įdėtuose hashuose. Pavyzdys rezultato yra:

{ nil => nil, 1 => 1, nested: { a: 3, 5 => 5 } }.deep_stringify_keys
# => {""=>nil, "1"=>1, "nested"=>{"a"=>3, "5"=>5}}

PASTABA: Apibrėžta active_support/core_ext/hash/keys.rb.

12.4.3 symbolize_keys ir symbolize_keys!

Metodas symbolize_keys grąžina hash, kuriame yra simbolizuota raktų versija gavėjui, kai tai įmanoma. Tai daroma siunčiant jiems to_sym:

{ nil => nil, 1 => 1, "a" => "a" }.symbolize_keys
# => {nil=>nil, 1=>1, :a=>"a"}

ĮSPĖJIMAS. Pastaba, kad ankstesniame pavyzdyje buvo simbolizuotas tik vienas raktas.

Atveju, kai yra raktų susidūrimas, reikšmė bus naujausia įterpta į hash:

{ "a" => 1, a: 2 }.symbolize_keys
# => {:a=>2}

Šis metodas gali būti naudingas, pavyzdžiui, lengvai priimti tiek simbolius, tiek eilutes kaip parinktis. Pavyzdžiui, ActionText::TagHelper apibrėžia ```ruby def rich_text_area_tag(name, value = nil, options = {}) options = options.symbolize_keys

options[:input] ||= "trix_input_#{ActionText::TagHelper.id += 1}" # ... end ```

Trečioji eilutė saugiai gali pasiekti :input raktą ir leisti vartotojui perduoti tiek :input, tiek "input".

Taip pat yra bang variantas symbolize_keys!, kuris simbolizuoja raktus vietoje.

Be to, galima naudoti deep_symbolize_keys ir deep_symbolize_keys!, kad simbolizuotumėte visus raktus duotame haeše ir visuose jame įdėtuose haešuose. Pavyzdys rezultato yra:

{ nil => nil, 1 => 1, "nested" => { "a" => 3, 5 => 5 } }.deep_symbolize_keys
# => {nil=>nil, 1=>1, nested:{a:3, 5=>5}}

PASTABA: Apibrėžta active_support/core_ext/hash/keys.rb.

12.4.4 to_options ir to_options!

Metodai to_options ir to_options! yra symbolize_keys ir symbolize_keys! sinonimai, atitinkamai.

PASTABA: Apibrėžta active_support/core_ext/hash/keys.rb.

12.4.5 assert_valid_keys

Metodas assert_valid_keys priima bet kokį skaičių argumentų ir patikrina, ar gavėjas neturi jokių raktų, kurie nėra išvardyti. Jei taip, išmetamas ArgumentError.

{ a: 1 }.assert_valid_keys(:a)  # praeina
{ a: 1 }.assert_valid_keys("a") # ArgumentError

Active Record nepriima nežinomų parinkčių, kuriant asociacijas, pavyzdžiui. Jis įgyvendina šią kontrolę naudodamas assert_valid_keys.

PASTABA: Apibrėžta active_support/core_ext/hash/keys.rb.

12.5 Darbas su reikšmėmis

12.5.1 deep_transform_values ir deep_transform_values!

Metodas deep_transform_values grąžina naują haešą, kuriame visos reikšmės konvertuojamos naudojant bloko operaciją. Tai apima reikšmes iš pagrindinio haešo ir visų įdėtų haešų ir masyvų.

hash = { person: { name: 'Rob', age: '28' } }

hash.deep_transform_values { |value| value.to_s.upcase }
# => {person: {name: "ROB", age: "28"}}

Taip pat yra bang variantas deep_transform_values!, kuris sunaikina visus reikšmes, naudodamas bloko operaciją.

PASTABA: Apibrėžta active_support/core_ext/hash/deep_transform_values.rb.

12.6 Pjovimas

Metodas slice! pakeičia haešą tik su duotais raktais ir grąžina haešą, kuriame yra pašalinti raktų ir reikšmių poros.

hash = { a: 1, b: 2 }
rest = hash.slice!(:a) # => {:b=>2}
hash                   # => {:a=>1}

PASTABA: Apibrėžta active_support/core_ext/hash/slice.rb.

12.7 Ištraukimas

Metodas extract! pašalina ir grąžina raktų ir reikšmių poras, atitinkančias duotus raktus.

hash = { a: 1, b: 2 }
rest = hash.extract!(:a) # => {:a=>1}
hash                     # => {:b=>2}

Metodas extract! grąžina tą pačią Hash klasės subklasę, kuri yra gavėjas.

hash = { a: 1, b: 2 }.with_indifferent_access
rest = hash.extract!(:a).class
# => ActiveSupport::HashWithIndifferentAccess

PASTABA: Apibrėžta active_support/core_ext/hash/slice.rb.

12.8 Nesvarbus prieiga

Metodas with_indifferent_access grąžina ActiveSupport::HashWithIndifferentAccess iš savo gavėjo:

{ a: 1 }.with_indifferent_access["a"] # => 1

PASTABA: Apibrėžta active_support/core_ext/hash/indifferent_access.rb.

13 Plėtiniai Regexp

13.1 multiline?

Metodas multiline? nurodo, ar reguliariam išraiškai yra nustatytas /m vėliavėlė, tai yra, ar taškas atitinka naujas eilutes.

%r{.}.multiline?  # => false
%r{.}m.multiline? # => true

Regexp.new('.').multiline?                    # => false
Regexp.new('.', Regexp::MULTILINE).multiline? # => true

Rails naudoja šį metodą tik vienoje vietoje, taip pat maršrutizavimo kode. Daugeilinės reguliariosios išraiškos maršrutams yra draudžiamos, ir ši vėliavėlė palengvina šio apribojimo taikymą.

def verify_regexp_requirements(requirements)
  # ...
  if requirement.multiline?
    raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}"
  end
  # ...
end

PASTABA: Apibrėžta active_support/core_ext/regexp.rb.

14 Plėtiniai Range

14.1 to_fs

Active Support apibrėžia Range#to_fs kaip alternatyvą to_s, kuri supranta pasirinktinį formato argumentą. Šiuo metu palaikomas tik neprivalomas formatas :db:

(Date.today..Date.tomorrow).to_fs
# => "2009-10-25..2009-10-26"

(Date.today..Date.tomorrow).to_fs(:db)
# => "BETWEEN '2009-10-25' AND '2009-10-26'"

Kaip pavyzdys iliustruoja, :db formatas generuoja BETWEEN SQL sąlygą. Tai naudojama Active Record, palaikant intervalo reikšmes sąlygose.

PASTABA: Apibrėžta active_support/core_ext/range/conversions.rb.

14.2 === ir include?

Metodai Range#=== ir Range#include? nurodo, ar tam tikra reikšmė patenka tarp duotų intervalo galų:

(2..3).include?(Math::E) # => true

Active Support išplečia šiuos metodus, kad argumentas galėtų būti kitas intervalas. Tokiu atveju tikriname, ar argumento intervalo galai priklauso pačiam intervalui:

(1..10) === (3..7)  # => true
(1..10) === (0..7)  # => false
(1..10) === (3..11) # => false
(1...9) === (3..9)  # => false

(1..10).include?(3..7)  # => true
(1..10).include?(0..7)  # => false
(1..10).include?(3..11) # => false
(1...9).include?(3..9)  # => false

PASTABA: Apibrėžta active_support/core_ext/range/compare_range.rb.

14.3 overlap?

Metodas Range#overlap? nurodo, ar duotiems intervalams yra ne tuščias sankirta:

(1..10).overlap?(7..11)  # => true
(1..10).overlap?(0..7)   # => true
(1..10).overlap?(11..27) # => false

PASTABA: Apibrėžta active_support/core_ext/range/overlap.rb.

15 Plėtiniai Date

15.1 Skaičiavimai

Šie skaičiavimo metodai turi ribines sąlygas 1582 m. spalio mėnesį, nes dienos nuo 5 iki 14 tiesiog neegzistuoja. Šiame vadove jų elgsenos aplink tas dienas nėra aprašyta dėl trumpumo, tačiau pakanka pasakyti, kad jie daro tai, ko tikėtumėte. Tai reiškia, kad Date.new(1582, 10, 4).tomorrow grąžina Date.new(1582, 10, 15) ir taip toliau. Norėdami sužinoti tikėtiną elgseną, patikrinkite test/core_ext/date_ext_test.rb Active Support testų rinkinyje.

15.1.1 Date.current

Active Support apibrėžia Date.current kaip šiandienos datą dabarties laiko juostoje. Tai panašu į Date.today, tačiau jis gerbia vartotojo laiko juostą, jei ji nustatyta. Taip pat apibrėžia Date.yesterday ir Date.tomorrow, taip pat past?, today?, tomorrow?, next_day?, yesterday?, prev_day?, future?, on_weekday? ir on_weekend?, visi jie yra susiję su Date.current.

Lyginant datas naudojant metodus, kurie gerbia vartotojo laiko juostą, įsitikinkite, kad naudojate Date.current, o ne Date.today. Yra atvejų, kai vartotojo laiko juosta gali būti ateityje, palyginti su sistemos laiko juosta, kurią pagal nutylėjimą naudoja Date.today. Tai reiškia, kad Date.today gali būti lygus Date.yesterday.

PASTABA: Apibrėžta active_support/core_ext/date/calculations.rb.

15.1.2 Pavadinimai datoms

15.1.2.1 beginning_of_week, end_of_week

Metodai beginning_of_week ir end_of_week grąžina savaitės pradžios ir pabaigos datą atitinkamai. Savaitės pradžia priklauso nuo pirmadienio, bet tai gali būti pakeista perduodant argumentą, nustatant gijos vietinį Date.beginning_of_week arba config.beginning_of_week.

d = Date.new(2010, 5, 8)     # => Sat, 08 May 2010
d.beginning_of_week          # => Mon, 03 May 2010
d.beginning_of_week(:sunday) # => Sun, 02 May 2010
d.end_of_week                # => Sun, 09 May 2010
d.end_of_week(:sunday)       # => Sat, 08 May 2010

beginning_of_week yra sinonimas at_beginning_of_week ir end_of_week yra sinonimas at_end_of_week.

PASTABA: Apibrėžta active_support/core_ext/date_and_time/calculations.rb.

15.1.2.2 monday, sunday

Metodai monday ir sunday grąžina ankstesnį pirmadienį ir kitą sekmadienį atitinkamai. ruby date = Date.new(2010, 6, 7) date.months_ago(3) # => Thu, 07 Mar 2010 date.months_since(3) # => Mon, 07 Sep 2010

If such a day does not exist, the last day of the corresponding month is returned:

Date.new(2012, 3, 31).months_ago(1)     # => Thu, 29 Feb 2012
Date.new(2012, 1, 31).months_since(1)   # => Wed, 29 Feb 2012

last_month is short-hand for #months_ago(1).

15.1.2.3 weeks_ago, weeks_since

The methods weeks_ago and [weeks_since][DateAndTime::Calculations#weeks_since] work analogously for weeks:

date = Date.new(2010, 6, 7)
date.weeks_ago(2)   # => Mon, 24 May 2010
date.weeks_since(2) # => Mon, 21 Jun 2010

last_week is short-hand for #weeks_ago(1).

15.1.2.4 days_ago, days_since

The methods [days_ago][DateAndTime::Calculations#days_ago] and [days_since][DateAndTime::Calculations#days_since] work analogously for days:

date = Date.new(2010, 6, 7)
date.days_ago(5)   # => Wed, 02 Jun 2010
date.days_since(5) # => Sat, 12 Jun 2010

[yesterday][DateAndTime::Calculations#yesterday] is short-hand for #days_ago(1), and [tomorrow][DateAndTime::Calculations#tomorrow] is short-hand for #days_since(1).

Jei tokios dienos nėra, grąžinamas atitinkamo mėnesio paskutinė diena:

Date.new(2010, 4, 30).months_ago(2)    # => Sek, 28 Vas 2010
Date.new(2009, 12, 31).months_since(2) # => Sek, 28 Vas 2010

last_month yra trumpinys #months_ago(1).

PASTABA: Apibrėžta active_support/core_ext/date_and_time/calculations.rb.

15.1.2.5 weeks_ago

Metodas weeks_ago veikia analogiškai savaitėms:

Date.new(2010, 5, 24).weeks_ago(1)    # => Pirm, 17 Geg 2010
Date.new(2010, 5, 24).weeks_ago(2)    # => Pirm, 10 Geg 2010

PASTABA: Apibrėžta active_support/core_ext/date_and_time/calculations.rb.

15.1.2.6 advance

Bendriausias būdas pereiti prie kitų dienų yra advance. Šis metodas priima maišą su raktiniais žodžiais :years, :months, :weeks, :days, ir grąžina datą, kuri yra tiek pat priekyje, kiek nurodyti raktiniai žodžiai:

date = Date.new(2010, 6, 6)
date.advance(years: 1, weeks: 2)  # => Pirm, 20 Bir 2011
date.advance(months: 2, days: -2) # => Tre, 04 Rgp 2010

Pastaba, kad padidinimai gali būti neigiami.

PASTABA: Apibrėžta active_support/core_ext/date/calculations.rb.

15.1.3 Komponentų keitimas

Metodas change leidžia gauti naują datą, kuri yra tokia pati kaip gavėjas, išskyrus nurodytus metus, mėnesį ar dieną:

Date.new(2010, 12, 23).change(year: 2011, month: 11)
# => Tre, 23 Lap 2011

Šis metodas netoleruoja neegzistuojančių datų, jei keitimas yra netinkamas, išmetamas ArgumentError:

Date.new(2010, 1, 31).change(month: 2)
# => ArgumentError: negaliojanti data

PASTABA: Apibrėžta active_support/core_ext/date/calculations.rb.

15.1.4 Trukmės

Prie datų galima pridėti arba iš jų atimti Duration objektus:

d = Date.current
# => Pirm, 09 Rgp 2010
d + 1.year
# => Antr, 09 Rgp 2011
d - 3.hours
# => Sek, 08 Rgp 2010 21:00:00 UTC +00:00

Jie verčiami į kvietimus since arba advance. Pavyzdžiui, čia gauname teisingą peršokimą kalendoriaus reformoje:

Date.new(1582, 10, 4) + 1.day
# => Pen, 15 Spa 1582

15.1.5 Laiko žymos

Jei įmanoma, šie metodai grąžina Time objektą, kitu atveju - DateTime. Jei nustatyta, jie gerbia vartotojo laiko juostą.

15.1.5.1 beginning_of_day, end_of_day

Metodas beginning_of_day grąžina laiko žymą dienos pradžioje (00:00:00):

date = Date.new(2010, 6, 7)
date.beginning_of_day # => Pirm Jun 07 00:00:00 +0200 2010

Metodas end_of_day grąžina laiko žymą dienos pabaigoje (23:59:59):

date = Date.new(2010, 6, 7)
date.end_of_day # => Pirm Jun 07 23:59:59 +0200 2010

beginning_of_day yra sinonimas at_beginning_of_day, midnight, at_midnight.

PASTABA: Apibrėžta active_support/core_ext/date/calculations.rb.

15.1.5.2 beginning_of_hour, end_of_hour

Metodas beginning_of_hour grąžina laiko žymą valandos pradžioje (hh:00:00):

date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.beginning_of_hour # => Pirm Jun 07 19:00:00 +0200 2010

Metodas end_of_hour grąžina laiko žymą valandos pabaigoje (hh:59:59):

date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.end_of_hour # => Pirm Jun 07 19:59:59 +0200 2010

beginning_of_hour yra sinonimas at_beginning_of_hour.

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

15.1.5.3 beginning_of_minute, end_of_minute

Metodas beginning_of_minute grąžina laiko žymą minutės pradžioje (hh:mm:00): ruby date = DateTime.new(2010, 6, 7, 19, 55, 25) date.beginning_of_minute # => Pirmadienis, birželio 07 19:55:00 +0200 2010

Metodas end_of_minute grąžina laiko žymą minutės pabaigoje (hh:mm:59):

date = DateTime.new(2010, 6, 7, 19, 55, 25)
date.end_of_minute # => Pirmadienis, birželio 07 19:55:59 +0200 2010

beginning_of_minute yra sinonimas at_beginning_of_minute.

beginning_of_hour, end_of_hour, beginning_of_minute ir end_of_minute yra įgyvendinti Time ir DateTime, bet ne Date, nes neturi prasmės prašyti valandos ar minutės pradžios ar pabaigos Date egzemplioriuje.

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

15.1.5.4 ago, since

Metodas ago priima sekundžių skaičių kaip argumentą ir grąžina laiko žymą tiek sekundžių atgal nuo vidurnakčio:

date = Date.current # => Penktadienis, birželio 11 2010
date.ago(1)         # => Ketvirtadienis, birželio 10 2010 23:59:59 EDT -04:00

Panašiai, since juda į priekį:

date = Date.current # => Penktadienis, birželio 11 2010
date.since(1)       # => Penktadienis, birželio 11 2010 00:00:01 EDT -04:00

PASTABA: Apibrėžta active_support/core_ext/date/calculations.rb.

16 Plėtiniai DateTime

ĮSPĖJIMAS: DateTime nežino DST taisyklių, todėl kai kurie iš šių metodų turi ribinius atvejus, kai vyksta DST keitimas. Pavyzdžiui, seconds_since_midnight gali negrąžinti tikro kiekio tokiame dieną.

16.1 Skaičiavimai

Klasė DateTime yra Date po-klasė, todėl įkelus active_support/core_ext/date/calculations.rb paveldite šiuos metodus ir jų sinonimus, išskyrus tai, kad jie visada grąžins datetimes.

Šie metodai yra įgyvendinti, todėl nereikia įkelti active_support/core_ext/date/calculations.rb šiems:

Kita vertus, advance ir change taip pat yra apibrėžti ir palaiko daugiau parinkčių, jie yra aprašyti žemiau.

Šie metodai yra įgyvendinti tik active_support/core_ext/date_time/calculations.rb, nes jie turi prasmę tik naudojant DateTime egzempliorių:

16.1.1 Pavadinimai laikui

16.1.1.1 DateTime.current

Active Support apibrėžia DateTime.current būti kaip Time.now.to_datetime, išskyrus tai, kad jis gerbia vartotojo laiko juostą, jei apibrėžta. Egzemplioriaus predikatai past? ir future? yra apibrėžti atsižvelgiant į DateTime.current.

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.2 Kiti plėtiniai

16.1.2.1 seconds_since_midnight

Metodas seconds_since_midnight grąžina sekundžių skaičių nuo vidurnakčio:

now = DateTime.current     # => Pirmadienis, birželio 07 2010 20:26:36 +0000
now.seconds_since_midnight # => 73596

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.2.2 utc

Metodas utc suteikia jums tą patį datetime gavėjo išreikštą UTC laiku.

now = DateTime.current # => Pirmadienis, birželio 07 2010 19:27:52 -0400
now.utc                # => Pirmadienis, birželio 07 2010 23:27:52 +0000

Šis metodas taip pat yra sinonimas getutc.

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.2.3 utc?

Predikatas utc? sako, ar gavėjas turi UTC kaip laiko juostą:

now = DateTime.now # => Pirmadienis, birželio 07 2010 19:30:47 -0400
now.utc?           # => false
now.utc.utc?       # => true

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.2.4 advance

Bendriausias būdas pereiti prie kito datetime yra advance. Šis metodas priima maišą su raktiniais žodžiais :years, :months, :weeks, :days, :hours, :minutes ir :seconds, ir grąžina datetime, pažengusį tiek, kiek dabartiniai raktai nurodo. ```ruby d = DateTime.current

=> Ket, 05 Rugpjūtis 2010 11:33:31 +0000

d.advance(years: 1, months: 1, days: 1, hours: 1, minutes: 1, seconds: 1)

=> An, 06 Rugsėjis 2011 12:34:32 +0000


Ši metodas pirmiausia apskaičiuoja paskirties datą, perduodamas `:years`, `:months`, `:weeks` ir `:days` į `Date#advance`, kuris yra aprašytas aukščiau. Po to, jis sureguliuoja laiką, iškviesdamas [`since`][DateTime#since] su sekundžių skaičiumi, kurį reikia pridėti. Ši tvarka yra svarbi, kita tvarka duotų skirtingas datos ir laiko reikšmes kai kuriuose ribiniuose atvejuose. Pavyzdys `Date#advance` taikomas ir galime jį išplėsti, kad parodytume tvarkos svarbą, susijusią su laiko elementais.

Jei pirmiausia perkeltume datos elementus (kurie taip pat turi santykinę tvarką, kaip jau buvo aprašyta), o po to laiko elementus, gautume, pavyzdžiui, šią skaičiavimą:

```ruby
d = DateTime.new(2010, 2, 28, 23, 59, 59)
# => Sek, 28 Vasaris 2010 23:59:59 +0000
d.advance(months: 1, seconds: 1)
# => Pir, 29 Kovas 2010 00:00:00 +0000

bet jei juos apskaičiuotume kitaip, rezultatas būtų skirtingas:

d.advance(seconds: 1).advance(months: 1)
# => Ket, 01 Balandis 2010 00:00:00 +0000

ĮSPĖJIMAS: Kadangi DateTime nėra DST informacijos turintis, galite patekti į neegzistuojančią laiko tašką be jokio įspėjimo ar klaidos pranešimo.

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.3 Komponentų keitimas

Metodas change leidžia gauti naują datą ir laiką, kuris yra tas pats kaip ir pradinis, išskyrus duotus parametrus, kurie gali apimti :year, :month, :day, :hour, :min, :sec, :offset, :start:

now = DateTime.current
# => An, 08 Birželis 2010 01:56:22 +0000
now.change(year: 2011, offset: Rational(-6, 24))
# => Tre, 08 Birželis 2011 01:56:22 -0600

Jei valandos yra nustatytos į nulį, tai taip pat taikoma minutėms ir sekundėms (jei jos neturi nustatytų reikšmių):

now.change(hour: 0)
# => An, 08 Birželis 2010 00:00:00 +0000

Panašiai, jei minutės yra nustatytos į nulį, tai taip pat taikoma sekundėms (jei jos neturi nustatytos reikšmės):

now.change(min: 0)
# => An, 08 Birželis 2010 01:00:00 +0000

Šis metodas netoleruoja neegzistuojančių datų, jei keitimas yra netinkamas, iškeliama ArgumentError:

DateTime.current.change(month: 2, day: 30)
# => ArgumentError: negaliojanti data

PASTABA: Apibrėžta active_support/core_ext/date_time/calculations.rb.

16.1.4 Trukmės

Duration objektai gali būti pridėti arba atimti iš datų ir laikų:

now = DateTime.current
# => Pir, 09 Rugpjūtis 2010 23:15:17 +0000
now + 1.year
# => An, 09 Rugpjūtis 2011 23:15:17 +0000
now - 1.week
# => Pir, 02 Rugpjūtis 2010 23:15:17 +0000

Jie verčiami į since arba advance iškvietimus. Pavyzdžiui, čia gauname teisingą perėjimą kalendoriaus reformoje:

DateTime.new(1582, 10, 4, 23) + 1.hour
# => Pen, 15 Spalis 1582 00:00:00 +0000

17 Time plėtinių

17.1 Skaičiavimai

Jie yra analogiški. Prašome kreiptis į jų dokumentaciją aukščiau ir atkreipti dėmesį į šias skirtumus:

  • change priima papildomą :usec parametrą.
  • Time supranta DST, todėl gaunate teisingus DST skaičiavimus, kaip šiuo atveju
Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>

# Barselonoje, 2010/03/28 02:00 +0100 tampa 2010/03/28 03:00 +0200 dėl DST.
t = Time.local(2010, 3, 28, 1, 59, 59)
# => Sek Mar 28 01:59:59 +0100 2010
t.advance(seconds: 1)
# => Sek Mar 28 03:00:00 +0200 2010
  • Jei since arba ago nukelia į laiką, kuris negali būti išreikštas su Time, grąžinamas DateTime objektas.

17.1.1 Time.current

Active Support apibrėžia Time.current kaip šiandien esantį laiką dabartinėje laiko juostoje. Tai panašu į Time.now, tačiau tai gerbia vartotojo laiko juostą, jei ji yra apibrėžta. Taip pat apibrėžiami past?, today?, tomorrow?, next_day?, yesterday?, prev_day? ir future? metodai, visi jie susiję su Time.current.

Lyginant laiką naudojant metodus, kurie gerbia vartotojo laiko juostą, įsitikinkite, kad naudojate Time.current vietoje Time.now. Yra atvejų, kai vartotojo laiko juosta gali būti ateityje, palyginti su sistemos laiko juosta, kurią pagal nutylėjimą naudoja Time.now. Tai reiškia, kad Time.now.to_date gali būti lygus Date.yesterday.

PASTABA: Apibrėžta active_support/core_ext/time/calculations.rb faile.

17.1.2 all_day, all_week, all_month, all_quarter ir all_year

Metodas all_day grąžina intervalą, kuris atitinka visą šios dienos laiką.

now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_day
# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Mon, 09 Aug 2010 23:59:59 UTC +00:00

Analogiškai, all_week, all_month, all_quarter ir all_year visi turi tikslą generuoti laiko intervalus.

now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now.all_week
# => Mon, 09 Aug 2010 00:00:00 UTC +00:00..Sun, 15 Aug 2010 23:59:59 UTC +00:00
now.all_week(:sunday)
# => Sun, 16 Sep 2012 00:00:00 UTC +00:00..Sat, 22 Sep 2012 23:59:59 UTC +00:00
now.all_month
# => Sat, 01 Aug 2010 00:00:00 UTC +00:00..Tue, 31 Aug 2010 23:59:59 UTC +00:00
now.all_quarter
# => Thu, 01 Jul 2010 00:00:00 UTC +00:00..Thu, 30 Sep 2010 23:59:59 UTC +00:00
now.all_year
# => Fri, 01 Jan 2010 00:00:00 UTC +00:00..Fri, 31 Dec 2010 23:59:59 UTC +00:00

PASTABA: Apibrėžta active_support/core_ext/date_and_time/calculations.rb faile.

17.1.3 prev_day, next_day

prev_day ir next_day grąžina laiką prieš tai arba po to esančią dieną:

t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_day               # => 2010-05-07 00:00:00 +0900
t.next_day               # => 2010-05-09 00:00:00 +0900

PASTABA: Apibrėžta active_support/core_ext/time/calculations.rb faile.

17.1.4 prev_month, next_month

prev_month ir next_month grąžina laiką su tuo pačiu dienos numeriu praėjusį arba ateinantį mėnesį:

t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_month             # => 2010-04-08 00:00:00 +0900
t.next_month             # => 2010-06-08 00:00:00 +0900

Jei tokios dienos nėra, grąžinamas atitinkamo mėnesio paskutinė diena:

Time.new(2000, 5, 31).prev_month # => 2000-04-30 00:00:00 +0900
Time.new(2000, 3, 31).prev_month # => 2000-02-29 00:00:00 +0900
Time.new(2000, 5, 31).next_month # => 2000-06-30 00:00:00 +0900
Time.new(2000, 1, 31).next_month # => 2000-02-29 00:00:00 +0900

PASTABA: Apibrėžta active_support/core_ext/time/calculations.rb faile.

17.1.5 prev_year, next_year

prev_year ir next_year grąžina laiką su tuo pačiu dienos/mėnesio numeriu praėjusiais arba ateinančiais metais:

t = Time.new(2010, 5, 8) # => 2010-05-08 00:00:00 +0900
t.prev_year              # => 2009-05-08 00:00:00 +0900
t.next_year              # => 2011-05-08 00:00:00 +0900

Jei data yra vasario 29 diena perkeliamaisiais metais, gaunate vasario 28 dieną:

t = Time.new(2000, 2, 29) # => 2000-02-29 00:00:00 +0900
t.prev_year               # => 1999-02-28 00:00:00 +0900
t.next_year               # => 2001-02-28 00:00:00 +0900

PASTABA: Apibrėžta faile active_support/core_ext/time/calculations.rb.

17.1.6 prev_quarter, next_quarter

prev_quarter ir next_quarter grąžina datą su tuo pačiu dienos numeriu ankstesniame arba kitame ketvirtyje:

t = Time.local(2010, 5, 8) # => 2010-05-08 00:00:00 +0300
t.prev_quarter             # => 2010-02-08 00:00:00 +0200
t.next_quarter             # => 2010-08-08 00:00:00 +0300

Jei tokios dienos nėra, grąžinamas atitinkamo mėnesio paskutinė diena:

Time.local(2000, 7, 31).prev_quarter  # => 2000-04-30 00:00:00 +0300
Time.local(2000, 5, 31).prev_quarter  # => 2000-02-29 00:00:00 +0200
Time.local(2000, 10, 31).prev_quarter # => 2000-07-31 00:00:00 +0300
Time.local(2000, 11, 31).next_quarter # => 2001-03-01 00:00:00 +0200

prev_quarter yra sinonimas last_quarter.

PASTABA: Apibrėžta faile active_support/core_ext/date_and_time/calculations.rb.

17.2 Laiko konstruktorius

Active Support apibrėžia Time.current kaip Time.zone.now, jei yra apibrėžta vartotojo laiko juosta, ir kaip Time.now, jei nėra:

Time.zone_default
# => #<ActiveSupport::TimeZone:0x7f73654d4f38 @utc_offset=nil, @name="Madrid", ...>
Time.current
# => Fri, 06 Aug 2010 17:11:58 CEST +02:00

Analogiškai DateTime, past? ir future? predikatai yra susiję su Time.current.

Jei konstruojamas laikas yra už ribų, kurias palaiko Time vykdymo platforma, mikrosekundės yra atmestos ir grąžinamas DateTime objektas.

17.2.1 Trukmės

Laikui galima pridėti ir iš jo atimti Duration objektus:

now = Time.current
# => Mon, 09 Aug 2010 23:20:05 UTC +00:00
now + 1.year
# => Tue, 09 Aug 2011 23:21:11 UTC +00:00
now - 1.week
# => Mon, 02 Aug 2010 23:21:11 UTC +00:00

Jie verčiami į since arba advance kvietimus. Pavyzdžiui, čia gauname teisingą peršokimą kalendoriaus reformoje:

Time.utc(1582, 10, 3) + 5.days
# => Mon Oct 18 00:00:00 UTC 1582

18 File plėtiniai

18.1 atomic_write

Naudojant klasės metodo File.atomic_write galima įrašyti į failą taip, kad joks skaitytojas nematytų pusiau įrašyto turinio.

Failo pavadinimas perduodamas kaip argumentas, o metodas grąžina failo rankeną, atidarytą rašymui. Baigus vykdyti bloką, atomic_write uždaro failo rankeną ir atlieka savo darbą.

Pavyzdžiui, Action Pack naudoja šį metodą, norėdama įrašyti turtų kašės failus, pvz., all.css:

File.atomic_write(joined_asset_path) do |cache|
  cache.write(join_asset_file_contents(asset_paths))
end

Tam atomic_write sukuria laikiną failą. Tai yra failas, į kurį bloko kode iš tikrųjų rašoma. Baigus darbą, laikinas failas pervadinamas, kas POSIX sistemose yra atomiška operacija. Jei tikslinis failas egzistuoja, atomic_write jį perrašo ir išlaiko savininkus ir teises. Tačiau yra keletas atvejų, kai atomic_write negali pakeisti failo savininko ar teisių, ši klaida yra aptinkama ir praleidžiama, tikintis, kad vartotojas/operacinė sistema užtikrins, kad failas būtų pasiekiamas procesams, kurie jo reikia.

PASTABA. Dėl atomic_write atliekamo chmod veiksmo, jei tiksliniame faile yra nustatytas ACL, šis ACL bus perskaičiuotas/modifikuotas.

ĮSPĖJIMAS. Atkreipkite dėmesį, kad negalima pridėti su atomic_write.

Pagalbiniai failai rašomi į standartinį laikinų failų katalogą, bet galite perduoti jūsų pasirinktą katalogą kaip antrą argumentą.

PASTABA: Apibrėžta faile active_support/core_ext/file/atomic.rb.

19 NameError plėtiniai

Aktyvusis palaikymas prideda missing_name? prie NameError, kuris patikrina, ar išimtis buvo iškelta dėl pateikto vardo.

Vardas gali būti pateiktas kaip simbolis arba eilutė. Simbolis yra tikrinamas su grynuoju konstantos vardu, o eilutė - su visiškai kvalifikuotu konstantos vardu.

PATARIMAS: Simbolis gali reikšti visiškai kvalifikuotą konstantos vardą, pvz., :"ActiveRecord::Base", todėl simboliams apibrėžtas elgesys yra patogumo sumetimais, o ne dėl techninių priežasčių.

Pavyzdžiui, kai veiksmas ArticlesController yra iškviestas, „Rails“ optimistiškai bando naudoti ArticlesHelper. Tai nesvarbu, kad pagalbinės modulio nėra, todėl jei išimtis dėl tos konstantos vardo yra iškelta, ji turėtų būti nutildyta. Tačiau gali būti atvejis, kad articles_helper.rb iškelia NameError dėl faktiškai nežinomos konstantos. Tai turėtų būti pakartotinai iškelta. Metodas missing_name? suteikia galimybę atskirti abu atvejus:

def default_helper_module!
  module_name = name.delete_suffix("Controller")
  module_path = module_name.underscore
  helper module_path
rescue LoadError => e
  raise e unless e.is_missing? "helpers/#{module_path}_helper"
rescue NameError => e
  raise e unless e.missing_name? "#{module_name}Helper"
end

PASTABA: Apibrėžta active_support/core_ext/name_error.rb faile.

20 Plėtiniai LoadError

Aktyvusis palaikymas prideda is_missing? prie LoadError.

Duodamas kelio pavadinimas, is_missing? patikrina, ar išimtis buvo iškelta dėl to konkretaus failo (išskyrus galbūt ".rb" plėtinį).

Pavyzdžiui, kai veiksmas ArticlesController yra iškviestas, „Rails“ bando įkelti articles_helper.rb, bet to failo gali nebūti. Tai gerai, pagalbinis modulis nėra privalomas, todėl „Rails“ nutildyja įkėlimo klaidą. Tačiau gali būti atvejis, kad pagalbinis modulis egzistuoja ir savo ruožtu reikalauja kito trūkstamo bibliotekos. Tokiu atveju „Rails“ turi pakartotinai iškelti išimtį. Metodas is_missing? suteikia galimybę atskirti abu atvejus:

def default_helper_module!
  module_name = name.delete_suffix("Controller")
  module_path = module_name.underscore
  helper module_path
rescue LoadError => e
  raise e unless e.is_missing? "helpers/#{module_path}_helper"
rescue NameError => e
  raise e unless e.missing_name? "#{module_name}Helper"
end

PASTABA: Apibrėžta active_support/core_ext/load_error.rb faile.

21 Plėtiniai Pathname

21.1 existence

existence metodas grąžina gavėją, jei nurodytas failas egzistuoja, kitu atveju grąžina nil. Tai naudinga idiomams, panašiems į šį:

content = Pathname.new("file").existence&.read

PASTABA: Apibrėžta active_support/core_ext/pathname/existence.rb faile.

Atsiliepimai

Jūs esate skatinami padėti pagerinti šio vadovo kokybę.

Prašome prisidėti, jei pastebite rašybos klaidų ar faktinių klaidų. Norėdami pradėti, galite perskaityti mūsų dokumentacijos prisidėjimo skyrių.

Taip pat gali būti nepilnos informacijos arba informacijos, kuri nėra atnaujinta. Prašome pridėti bet kokią trūkstamą dokumentaciją pagrindiniam. Patikrinkite Edge vadovus pirmiausia, ar problemas jau išspręsta arba ne pagrindinėje šakoje. Patikrinkite Ruby on Rails vadovų gaires dėl stiliaus ir konvencijų.

Jei dėl kokios nors priežasties pastebite kažką, ką reikia ištaisyti, bet negalite patys tai pataisyti, prašome pranešti apie problemą.

Ir galiausiai, bet ne mažiau svarbu, bet koks diskusijos dėl Ruby on Rails dokumentacijos yra labai laukiamos oficialiame Ruby on Rails forume.