Ruby 理解 Rails 之 Array 的 extract_options! 方法

shawnyu · 2013年06月03日 · 最后由 haobangpig 回复于 2019年09月04日 · 6684 次阅读

注:原帖地址http://www.simonecarletti.com/blog/2009/09/inside-ruby-on-rails-extract_options-from-arrays/

刚刚在讨论《代码的未来》的翻译, 我也来试试,体验下译者的辛苦,请在评论里纠错 我英文很烂 😢

在 Rails 项目里面是不是经常看到下面的方法调用?

my_method :arg1
my_method :arg1, :arg2, :argN
my_method :arg1, :foo => true, :bar => 1

my_method的特别之处在于它可以接受任意数量的参数(:arg1, :arg2...)后跟一个键值对的选项(options)。

ActiveSupport中提供的一个叫做extract_options!的牛逼方法使之成为可能。它的主要作用是提取给出的参数中的选项(options)。如果没有选项(options)它会返回一个空的 Hash。

给你们秀一个列子!

# Use args with the splat operation to allow
# an unlimited number of parameters
def my_method(*args)
  options = args.extract_options!
  puts "Arguments:  #{args.inspect}"
  puts "Options:    #{options.inspect}"
end

my_method(1, 2)
# Arguments:  [1, 2]
# Options:    {}

my_method(1, 2, :a => :b)
# Arguments:  [1, 2]
# Options:    {:a=>:b}

extract_options!被大量用在 Rails 项目中,你肯定已经遇见它无数次了。它驱动(powers)了大多数你每天用到的的 Rails 功能,包括 ActionController filters,ActiveRecord validations 和 finder 方法。

# ActionController filters
class MyController < ApplicationController
  before_filter :my_method, :if => :execute?, :only => %w(new)
end

# ActiveRecord validations and finders
class MyModel < ActiveRecord::Base
  validates_presence_of :field, :allow_blank => true

  ...

  def self.my_find
    find(:all, :order => "id", :limit => 10)
  end

end

extract_options! 可以让你从一个数组的参数中方便的提取出选项列(a list of options),这通常发生在方法调用时。 它不是 Ruby 的标准方法,但是它是 Rails 的核心扩展,并且你需要引用 ActiveSupport才能使用。请注意它是一个 “bang” 方法,因此它会修改调用它的对象。

这个也没啥好理解的吧,说白了就是看看数组最后一项是不是 Hash,如果是的话就提取出来了

但是是?中文一般直接写成但|是。好吧,我在挑刺。。。 不过这文章真心没什么帮助,内容太简单?

你们压根就不懂得什么叫做鼓励,这篇文章针对初学者一定有帮助,而且是英译汉,必须顶!

@iBachue @HalF_taN 哈哈 内容确实比较简单, 不过我竟然昨天才知道这个知识点的, 应该可以帮到一些朋友。 @lgn21st thx

帮助很大,谢谢 lz

@geekontheway 强顶灰飞烟灭

至少我也是第一次学到这个函数,谢谢

原碼如下

def extract_options!
  last.is_a?(::Hash) ? pop : {}
end

剛剛也正在找這個 看原碼理解最快!

最近刚学习到这个,举个例子是

[11] pry(main)> [1,2,{a: "1", b: "s"},{c:"3"}].extract_options!
=> {:c=>"3"}

上面有人提到的是 :

数组最后一项是不是 Hash,如果是的话就提取出来了

源代码的话:

class Array
  # Extracts options from a set of arguments. Removes and returns the last
  # element in the array if it's a hash, otherwise returns a blank hash.
  #
  #   def options(*args)
  #     args.extract_options!
  #   end
  #
  #   options(1, 2)        # => {}
  #   options(1, 2, a: :b) # => {:a=>:b}
  def extract_options!
    if last.is_a?(Hash) && last.extractable_options?
      pop
    else
      {}
    end
  end
end
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册