Ruby配置技术

时间:2015-07-21 16:12:30

标签: ruby twitter

我对ruby很新,我只是花时间研究github中现有ruby项目的模式。现在,我登陆了twitter's ruby project并在配置中发现了这些行:

client = Twitter::REST::Client.new do |config|
  config.consumer_key        = "YOUR_CONSUMER_KEY"
  config.consumer_secret     = "YOUR_CONSUMER_SECRET"
  config.access_token        = "YOUR_ACCESS_TOKEN"
  config.access_token_secret = "YOUR_ACCESS_SECRET"
end

在此方法调用的declaration中,我也注意到了这一点:

module Twitter
  class Client
    include Twitter::Utils
    attr_accessor :access_token, :access_token_secret, :consumer_key, :consumer_secret, :proxy

    def initialize(options = {})
      options.each do |key, value|
        instance_variable_set("@#{key}", value)
      end
      yield(self) if block_given?
    end
...

现在,当我练习时,我复制了相同的逻辑,但观察了"初始化"的内容。方法。

module Main
    class Sample    
        attr_accessor :hello, :foo

        def initialize(options={})            
            yield(self) if block_given?
        end

        def test
            @hello
        end        
    end    
end

并称之为(与上面的推特代码相同)

sample = Main::Sample.new do |config|
    config.hello = "world"
    config.foo = "bar"
end

puts "#{sample.hello} #{sample.foo}" # outputs => world bar
puts sample.test # outputs => world

现在,我的问题是,即使我的代码中没有这些行(请参阅上面的twitter中的代码块),我的"初始化"方法,

options.each do |key, value|
   instance_variable_set("@#{key}", value)
end

代码 puts "#{sample.hello} #{sample.foo}"puts sample.test仍然正常。为什么会这样?实例变量是如何在这里设置的?

1 个答案:

答案 0 :(得分:1)

这是因为您使用config.hello=config.foo=之类的内容手动调用它们。

如果没有这一大块代码,那将无法工作的是:

Main::Sample.new(hello: 'world')

您需要该部分来选择并应用它们。

Twitter版本相当松懈。通常,您希望测试具有该名称的属性,而不是仅仅随机分配实例变量。通常,这是通过某种白名单来完成的:

ATTRIBUTES = %i[ hello world ]

attr_accessor *ATTRIBUTES

def initialize(options = nil)
  options and options.each do |attr, value|
    if (ATTRIBUTES.include?(attr))
      send("#{attr}=", value)
    else
      raise "Unknown attribute #{attr.inspect}"
    end
  end

  yield self if (block_given?)
end

如果使用无效选项调用,则会引发异常。