класс Object
Константы
- APP_PATH
Открытые методы экземпляра
# File activesupport/lib/active_support/core_ext/object/acts_like.rb, line 33
def acts_like?(duck)
case duck
when :time
respond_to? :acts_like_time?
when :date
respond_to? :acts_like_date?
when :string
respond_to? :acts_like_string?
else
respond_to? :"acts_like_#{duck}?"
end
end Позволяет проверить, ведёт ли себя некоторый класс подобно другому классу, исходя из наличия метода-маркера с соответствующим именем.
Класс, предоставляющий тот же интерфейс, что и SomeClass, может определить метод-маркер с именем acts_like_some_class?, чтобы сообщить о своей совместимости вызывающим кодам acts_like?(:some_class).
Например, Active Support расширяет Date, определяя метод acts_like_date?, и расширяет Time, определяя acts_like_time?. В результате разработчики могут вызывать x.acts_like?(:time) и x.acts_like?(:date) для проверки совместимости по утиному типизированию, а классы, способные вести себя подобно Time, также могут определить метод acts_like_time? для взаимодействия с ними.
Обратите внимание: ожидается лишь наличие метода-маркера. Он не вызывается, поэтому его тело и возвращаемое значение не имеют значения.
Пример: класс, предоставляющий тот же интерфейс, что и String
Этот класс может определить:
class Stringish def acts_like_string? end end
Затем клиентский код может проверить совместимость по утиному типизированию следующим образом:
Stringish.new.acts_like?(:string) # => true
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 18 def blank? respond_to?(:empty?) ? !!empty? : false end
Объект считается пустым, если он равен false, пуст или представляет собой строку из пробельных символов. Например, nil, ”, ‘ ’, [], {}, и false — пустые значения.
Это позволяет заменить
!address || address.empty?
на
address.blank?
@return [true, false]
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 15 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 26 def duplicable? true end
Можно ли безопасно создать копию этого объекта?
Для объектов методов возвращает false, для остальных — true.
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 7 def html_safe? false end
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 15
def in?(another_object)
case another_object
when Range
another_object.cover?(self)
else
another_object.include?(self)
end
rescue NoMethodError
raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
end Возвращает true, если этот объект содержится в аргументе.
Если аргумент — Range, для корректной проверки вхождения в открытые диапазоны используется cover?. В противном случае аргументом должен быть любой объект, отвечающий на include?. Пример использования:
characters = ["Konata", "Kagami", "Tsukasa"] "Konata".in?(characters) # => true
Если аргумент не является Range, будет вызвано исключение ArgumentError, если аргумент не отвечает на include?.
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 14
def instance_values
instance_variables.to_h do |ivar|
[ivar[1..-1].freeze, instance_variable_get(ivar)]
end
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 29 def instance_variable_names instance_variables.map(&:name) 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/blank.rb, line 45 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 [Object]
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 34 def presence_in(another_object) in?(another_object) ? self : nil end
Возвращает получатель, если он содержится в аргументе, в противном случае возвращает nil. Аргументом должен быть любой объект, отвечающий на include?. Пример использования:
params[:bucket_type].presence_in %w( project calendar )
Если аргумент не отвечает на include?, будет вызвано исключение ArgumentError.
@return [Object]
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 25 def present? !blank? end
Объект считается присутствующим, если он не пуст.
@return [true, false]
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 8 def to_param to_s end
Псевдоним для to_s.
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 14
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 39
Вызывает открытый метод, имя которого передано первым аргументом, подобно 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.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.
# File activesupport/lib/active_support/core_ext/object/try.rb, line 104
То же, что и try, но вызывает исключение NoMethodError, если получатель не является nil и не реализует вызываемый метод.
"a".try!(:upcase) # => "A" nil.try!(:upcase) # => nil 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
# File activesupport/lib/active_support/core_ext/object/with.rb, line 26
def with(**attributes)
old_values = {}
begin
attributes.each do |key, value|
old_values[key] = public_send(key)
public_send("#{key}=", value)
end
yield self
ensure
old_values.each do |key, old_value|
public_send("#{key}=", old_value)
end
end
end Устанавливает и восстанавливает открытые атрибуты до и после выполнения блока.
client.timeout # => 5 client.with(timeout: 1) do |c| c.timeout # => 1 end client.timeout # => 5
Получатель передаётся предоставленному блоку.
Этот метод — краткая запись распространённой конструкции begin/ensure:
old_value = object.attribute begin object.attribute = new_value # do things ensure object.attribute = old_value end
Его можно использовать с любым объектом, если методы чтения и записи являются открытыми.
# File activesupport/lib/active_support/core_ext/object/with_options.rb, line 92
def with_options(options, &block)
option_merger = ActiveSupport::OptionMerger.new(self, options)
if block
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
else
option_merger
end
end Удобный способ устранить дублирование параметров, передаваемых серии вызовов методов. Для каждого метода, вызванного в блоке, где переменная блока используется как получатель, его параметры будут объединены с предоставленным по умолчанию объектом options типа Hash или Hash. Каждый метод, вызываемый для переменной блока, должен принимать хеш параметров последним аргументом.
Без 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 игнорируется.
ПРИМЕЧАНИЕ: Нельзя неявно вызывать методы класса внутри with_options. Вместо этого к этим методам можно обратиться, указав имя класса:
class Phone < ActiveRecord::Base
enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
with_options presence: true do
validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
end
end
Если аргумент блока опущен, возвращается декорированный экземпляр Object:
module MyStyledHelpers
def styled
with_options style: "color: red;"
end
end
styled.link_to "I'm red", "/"
# => <a href="/" style="color: red;">I'm red</a>
styled.button_tag "I'm red too!"
# => <button style="color: red;">I'm red too!</button>
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.