class Object
def acts_like?(duck)
Stringish.new.acts_like?(:string) # => true
Then client code can query for duck-type-safeness this way:
end
end
def acts_like_string?
class Stringish
This class may define:
==== Example: A class that provides the same interface as String
value are irrelevant.
Note that the marker method is only expected to exist. It isn't called, so its body or return
method to interoperate.
and classes that are able to act like Time can also define an acts_like_time?
x.acts_like?(:time) and x.acts_like?(:date) to test duck-type compatibility,
and extends Time to define acts_like_time?. As a result, developers can call
For example, Active Support extends Date to define an acts_like_date? method,
acts_like?(:some_class).
acts_like_some_class? to signal its compatibility to callers of
A class that provides the same interface as SomeClass may define a marker method named
an appropriately-named marker method.
Provides a way to check whether some class acts like some other class based on the existence of
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
def as_json(options = nil) # :nodoc:
def as_json(options = nil) # :nodoc: if respond_to?(:to_hash) to_hash.as_json(options) else instance_values.as_json(options) end end
def blank?
-
(true, false)
-
def blank? respond_to?(:empty?) ? !!empty? : !self end
def deep_dup
object.instance_variable_defined?(:@a) # => false
dup.instance_variable_set(:@a, 1)
dup = object.deep_dup
object = Object.new
not duplicable, returns +self+.
Returns a deep copy of object if it's duplicable. If it's
def deep_dup duplicable? ? dup : self end
def duplicable?
False for method objects;
Can you safely dup this object?
def duplicable? true end
def html_safe?
def html_safe? false end
def in?(another_object)
This will throw an +ArgumentError+ if the argument doesn't respond
"Konata".in?(characters) # => true
characters = ["Konata", "Kagami", "Tsukasa"]
any object which responds to +#include?+. Usage:
Returns true if this object is included in the argument. Argument must be
def in?(another_object) another_object.include?(self) rescue NoMethodError raise ArgumentError.new("The parameter passed to #in? must respond to #include?") end
def instance_values
end
end
@x, @y = x, y
def initialize(x, y)
class C
corresponding values.
Returns a hash with string keys that maps instance variable names without "@" to their
def instance_values Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }] end
def instance_variable_names
end
end
@x, @y = x, y
def initialize(x, y)
class C
Returns an array of instance variable names as strings including "@".
def instance_variable_names instance_variables.map(&:to_s) end
def presence
-
(Object)
-
def presence self if present? end
def presence_in(another_object)
-
(Object)
-
def presence_in(another_object) in?(another_object) ? self : nil end
def present?
-
(true, false)
-
def present? !blank? end
def to_param
def to_param to_s end
def to_query(key)
Converts an object into a string suitable for use as a URL query string,
def to_query(key) "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}" end
def with_options(options, &block)
# =>
styled.button_tag "I'm red too!"
# => I'm red
styled.link_to "I'm red", "/"
end
end
with_options style: "color: red;"
def styled
module MyStyledHelpers
When the block argument is omitted, the decorated Object instance is returned:
end
end
validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
with_options presence: true do
enum phone_number_type: { home: 0, office: 1, mobile: 2 }
class Phone < ActiveRecord::Base
You can access these methods using the class name instead:
NOTE: You cannot call class methods implicitly inside of +with_options+.
Hence the inherited default for +if+ key is ignored.
validates :content, length: { minimum: 50 }, if: -> { content.present? }
The code is equivalent to:
end
end
validates :content, if: -> { content.present? }
with_options if: :persisted?, length: { minimum: 50 } do
class Post < ActiveRecord::Base
NOTE: Each nesting level will merge inherited defaults in addition to their own.
with_options can also be nested since the call is forwarded to its receiver.
end
end
has_many :expenses
has_many :invoices
has_many :products
has_many :customers
with_options dependent: :destroy do
class Account < ActiveRecord::Base
in merging options context:
When you don't pass an explicit receiver, it executes the whole block
end
body i18n.t :body, user_name: user.name
subject i18n.t :subject
I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
It can also be used with an explicit receiver:
end
end
assoc.has_many :expenses
assoc.has_many :invoices
assoc.has_many :products
assoc.has_many :customers
with_options dependent: :destroy do |assoc|
class Account < ActiveRecord::Base
Using with_options, we can remove the duplication:
end
has_many :expenses, dependent: :destroy
has_many :invoices, dependent: :destroy
has_many :products, dependent: :destroy
has_many :customers, dependent: :destroy
class Account < ActiveRecord::Base
Without with_options, this code contains duplication:
hash as its final argument.
provided. Each method called on the block variable must take an options
the receiver, will have its options merged with the default +options+ hash
method calls. Each method called in the block, with the block variable as
An elegant way to factor duplication out of options passed to a series of
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