跳至内容 跳至搜索
方法
A
B
D
H
I
P
T
W
包含的模块

常量

APP_PATH = File.expand_path("test/dummy/config/application", ENGINE_ROOT)
 

实例公共方法

acts_like?(duck)

提供了一种基于适当命名的标记方法是否存在来检查某个类是否像另一个类。

一个提供与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/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

blank?()

对象是 blank(空白)如果它是 false、empty(空)或空白字符串。例如,nil、”、‘ ‘、[]、{} 和 false 都是 blank。

这简化了

!address || address.empty?

address.blank?

@return [true, false]

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 18
def blank?
  respond_to?(:empty?) ? !!empty? : false
end

deep_dup()

如果对象可复制,则返回对象的深拷贝。如果不可复制,则返回 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/deep_dup.rb, line 15
def deep_dup
  duplicable? ? dup : self
end

duplicable?()

你能安全地复制这个对象吗?

方法对象为 false;否则为 true。

# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 26
def duplicable?
  true
end

html_safe?()

# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 7
def html_safe?
  false
end

in?(another_object)

如果此对象包含在参数中,则返回 true。

当参数是 Range 时,使用 cover? 来正确处理开放范围内的包含检查。否则,参数必须是任何响应 include? 的对象。用法

characters = ["Konata", "Kagami", "Tsukasa"]
"Konata".in?(characters) # => true

对于非 Range 参数,如果参数不响应 include?,这将抛出 ArgumentError

# 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

instance_values()

返回一个具有字符串键的哈希表,该哈希表将不带“@”的实例变量名映射到其对应的值。

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 14
def instance_values
  instance_variables.to_h do |ivar|
    [ivar[1..-1].freeze, instance_variable_get(ivar)]
  end
end

instance_variable_names()

返回包含“@”的实例变量名字符串数组。

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/instance_variables.rb, line 29
def instance_variable_names
  instance_variables.map(&:name)
end

presence()

如果接收者存在,则返回接收者,否则返回 nilobject.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/blank.rb, line 45
def presence
  self if present?
end

presence_in(another_object)

如果接收者包含在参数中,则返回接收者,否则返回 nil。参数必须是任何响应 include? 的对象。用法

params[:bucket_type].presence_in %w( project calendar )

如果参数不响应 include?,这将抛出 ArgumentError

@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

present?()

如果对象不 blank(空白),则对象是 present(存在)。

@return [true, false]

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 25
def present?
  !blank?
end

to_param()

to_s 的别名。

# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 8
def to_param
  to_s
end

to_query(key)

将一个对象转换为适合用作 URL 查询字符串的字符串,使用给定的 key 作为参数名。

# 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

try(*args, &block)

调用名称作为第一个参数的公共方法,就像 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

无论是否响应方法,在 nil 上调用 try 都会返回 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_evaled

@person.try { upcase.truncate(50) }

请注意,try 定义在 Object 上。因此,它不能与没有 Object 作为其祖先的类的实例一起使用,例如 BasicObject 的直接子类。

# File activesupport/lib/active_support/core_ext/object/try.rb, line 39
  

try!(*args, &block)

try 相同,但如果接收者不为 nil 且未实现所尝试的方法,则引发 NoMethodError 异常。

"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/try.rb, line 104

with(**attributes)

在块周围设置和恢复公共属性。

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.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

with_options(options, &block)

一种优雅的方式,用于消除传递给一系列方法调用的选项中的重复。块中调用的每个方法(以块变量作为接收者)都将与其选项与提供的默认 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>
# 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