0
我对ruby非常陌生,我只是花时间研究github中现有的ruby项目的模式。现在,我降落在twitter's ruby project,并注意到在其配置这些行:Ruby配置技巧
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
,并呼吁它(同样在Twitter上面的代码怎么做)
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
现在,我的问题是,即使我没有在我的这几行代码(见代码块从叽叽喳喳以上),在我的 “初始化” 的方法,
options.each do |key, value|
instance_variable_set("@#{key}", value)
end
代码 puts "#{sample.hello} #{sample.foo}"
和puts sample.test
仍然正常工作。这是为什么?这个实例变量是如何真正设置的?
啊哈!我知道了。我懂了。所以原因是当我产生(self)'时,它实际上将实例传递给块,这就是我能够手动配置或赋值给他们的方式。我太傻了。无论如何,再次感谢人! – Aldee
您的风格实际上很安全且易于追踪。是。我同意Twitter的实施实际上是松懈的。 – Aldee
在这样的方法中,你会看到'yield(self)if(block_given?)'。这是一种模式,它可以回退正在进行中的对象,您可以在最终确定之前进行修改。当你在一个函数调用中构建一个对象时,这个函数会派上用场,你只需要调整它:'func(Thing.new {| t | t.name ='test'})''例如。 – tadman