класс Object
Константы
- HashWithIndifferentAccess
-
Реализует хэш, где ключи
:fooи"foo"считаются одинаковыми.rgb = ActiveSupport::HashWithIndifferentAccess.new rgb[:black] = '#000000' rgb[:black] # => '#000000' rgb['black'] # => '#000000' rgb['white'] = '#FFFFFF' rgb[:white] # => '#FFFFFF' rgb['white'] # => '#FFFFFF'
Внутри символы отображаются в строки при использовании в качестве ключей во всем интерфейсе написания (вызывая
[]=,merge, и т.д.). Это отображение относится к общедоступному интерфейсу. Например, при:hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
Вам гарантируется, что ключ будет возвращен в виде строки:
hash.keys # => ["a"]
Технически принимаются и другие типы ключей:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1) hash[0] = 0 hash # => {"a"=>1, 0=>0}но этот класс предназначен для случаев, когда ожидаемыми ключами являются строки или символы, и удобно понимать их как одинаковые. Например, хэш
paramsв Ruby on Rails.Обратите внимание, что ядро расширений определяет
Hash#with_indifferent_access:rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_accessчто может быть полезно.
- MissingSourceFile
Методы экземпляров Public
# File activesupport/lib/active_support/core_ext/object/acts_like.rb, line 7
def acts_like?(duck)
respond_to? :"acts_like_#{duck}?"
end Вспомогательный метод для работы с типом «утка». Например, Active Support расширяет Date, чтобы определить метод acts_like_date?, и расширяет Time, чтобы определить acts_like_time?. В результате, мы можем выполнять x.acts_like?(:time) и x.acts_like?(:date) для безопасного сравнения типов «утка», так как классам, которые должны вести себя как Time, достаточно определить метод acts_like_time?.
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 15 def blank? respond_to?(:empty?) ? !!empty? : !self end
Объект считается пустым, если он ложный, пустой или строка из пробелов. Например, false, '', ' ', nil, [], и {} являются пустыми.
Это упрощает
!address || address.empty?
до
address.blank?
@return [true, false]
# File railties/lib/rails/test_help.rb, line 28
def create_fixtures(*fixture_set_names, &block)
FixtureSet.create_fixtures(ActiveSupport::TestCase.fixture_path, fixture_set_names, {}, &block)
end # File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 13 def deep_dup duplicable? ? dup : self end
Возвращает глубокую копию объекта, если он дублируемый. Если он не дублируемый, возвращает self.
object = Object.new dup = object.deep_dup dup.instance_variable_set(:@a, 1) object.instance_variable_defined?(:@a) # => false dup.instance_variable_defined?(:@a) # => true
# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 24 def duplicable? true end
Можно ли безопасно дублировать этот объект?
Ложь для nil, false, true, символов, чисел и объектов BigDecimal (в 1.9.x); в противном случае — истина.
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 120 def html_safe? false end
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 10
def in?(another_object)
another_object.include?(self)
rescue NoMethodError
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
end Возвращает true, если этот объект включён в аргумент. Аргумент должен быть любым объектом, который отвечает на #include?. Пример использования:
characters = ["Konata", "Kagami", "Tsukasa"] "Konata".in?(characters) # => true
Это вызовет ArgumentError, если аргумент не отвечает на #include?.
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 12
def instance_values
Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
end Возвращает хэш со строковыми ключами, которые сопоставляют имена переменных экземпляров без «@» с соответствующими значениями.
class C
def initialize(x, y)
@x, @y = x, y
end
end
C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 25
def instance_variable_names
instance_variables.map { |var| var.to_s }
end Возвращает массив имён переменных экземпляров в виде строк, включая «@».
class C
def initialize(x, y)
@x, @y = x, y
end
end
C.new(0, 1).instance_variable_names # => ["@y", "@x"]
# File activesupport/lib/active_support/core_ext/object/itself.rb, line 11 def itself self end
Возвращает сам объект.
Полезно для объединения методов, например, скопов Active Record:
Event.public_send(state.presence_in([ :trashed, :drafted ]) || :itself).order(:created_at)
@return Объект
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 42 def presence self if present? end
Возвращает получатель, если он присутствует, в противном случае возвращает nil. object.presence эквивалентно
object.present? ? object : nil
Например, что-то вроде
state = params[:state] if params[:state].present? country = params[:country] if params[:country].present? region = state || country || 'US'
становится
region = params[:state].presence || params[:country].presence || 'US'
@return [Объект]
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 24 def presence_in(another_object) self.in?(another_object) ? self : nil end
Возвращает получатель, если он включён в аргумент, в противном случае возвращает nil. Аргумент должен быть любым объектом, который отвечает на #include?. Пример использования:
params[:bucket_type].presence_in %w( project calendar )
Это вызовет ArgumentError, если аргумент не отвечает на #include?.
@return [Объект]
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 22 def present? !blank? end
Объект считается существующим, если он не пустой.
@return [true, false]
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 5 def to_param to_s end
Псевдоним to_s.
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 11
def to_query(key)
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
end Преобразует объект в строку, подходящую для использования в строке запроса URL, используя заданное key как имя параметра.
# File activesupport/lib/active_support/core_ext/object/try.rb, line 62 def try(*a, &b) try!(*a, &b) if a.empty? || respond_to?(a.first) end
Вызывает общедоступный метод, имя которого передано в качестве первого аргумента, так же как и public_send, за исключением того, что если получатель не отвечает на него, вызов возвращает nil, а не вызывает исключение.
Этот метод предназначен для записи
@person.try(:name)
вместо
@person.name if @person
try вызовы могут быть объединены:
@person.try(:spouse).try(:name)
вместо
@person.spouse.name if @person && @person.spouse
try также вернёт nil при вызове на
@person.name if @personвне зависимости от того, отвечает ли он на метод:
@person.try(:non_existing_method) #=> nil
вместо
@person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil
try возвращает nil при вызове на nil независимо от того, отвечает ли он на метод:
nil.try(:to_i) # => nil, rather than 0
Аргументы и блоки передаются методу, если вызывается:
@posts.try(:each_slice, 2) do |a, b| ... end
Количество аргументов в сигнатуре должно совпадать. Если объект отвечает на метод, вызов выполняется, и ArgumentError всё ещё возникает в случае несоответствия аргументов.
Если try вызывается без аргументов, он возвращает получателя в заданный блок, если он не nil:
@person.try do |p| ... end
Вы также можете вызвать try с блоком без принятия аргумента, и блок будет выполнен с помощью instance_eval:
@person.try { upcase.truncate(50) }
Обратите также внимание, что try определён в Object. Поэтому он не будет работать с экземплярами классов, у которых Object не среди их предков, например, с прямыми подклассами BasicObject. Например, использование try с SimpleDelegator делегирует try целевому объекту вместо вызова на самом делегаторе.
# File activesupport/lib/active_support/core_ext/object/try.rb, line 69
def try!(*a, &b)
if a.empty? && block_given?
if b.arity == 0
instance_eval(&b)
else
yield self
end
else
public_send(*a, &b)
end
end То же, что и try, но вызовет исключение NoMethodError, если получатель не nil и не реализует вызванный метод.
# File activesupport/lib/active_support/core_ext/uri.rb, line 9
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
# TODO: Are we actually sure that ASCII == UTF-8?
# YK: My initial experiments say yes, but let's be sure please
enc = str.encoding
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
end # File activesupport/lib/active_support/core_ext/object/with_options.rb, line 65 def with_options(options, &block) option_merger = ActiveSupport::OptionMerger.new(self, options) block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger) end
Элегантный способ устранить дублирование в опциях, передаваемых в серию вызовов методов. Каждый метод, вызываемый в блоке с переменной блока в качестве получателя, будет иметь свои опции, объединённые с предопределённым options хэш-объектом. Каждый вызов метода переменной блока должен принимать хэш-объект опций в качестве последнего аргумента.
Без with_options>, этот код содержит дублирование:
class Account < ActiveRecord::Base has_many :customers, dependent: :destroy has_many :products, dependent: :destroy has_many :invoices, dependent: :destroy has_many :expenses, dependent: :destroy end
Используя with_options, мы можем устранить дублирование:
class Account < ActiveRecord::Base
with_options dependent: :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
assoc.has_many :expenses
end
end
Его также можно использовать с явным получателем:
I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n| subject i18n.t :subject body i18n.t :body, user_name: user.name end
Когда вы не передаёте явного получателя, весь блок выполняется в контексте слияния опций:
class Account < ActiveRecord::Base
with_options dependent: :destroy do
has_many :customers
has_many :products
has_many :invoices
has_many :expenses
end
end
with_options также может быть вложенным, так как вызов передаётся его получателю.
ПРИМЕЧАНИЕ: Каждый уровень вложенности объединит унаследованные значения по умолчанию в дополнение к своим собственным.
class Post < ActiveRecord::Base
with_options if: :persisted?, length: { minimum: 50 } do
validates :content, if: -> { content.present? }
end
end
Код эквивалентен:
validates :content, length: { minimum: 50 }, if: -> { content.present? }
Следовательно, унаследованное значение по умолчанию для ключа `if` игнорируется.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.