Hen*_*nry 6 ruby metaprogramming
我有一个Flickr界面,我刚才写过,其中一部分困扰我,我想让它变得更好.它的工作方式是我使用缺少的方法从flickr对象上调用的方法构造flickr调用的url参数,例如.
@flickr.groups.pools.getPhotos(:user_id => "12656878@N06", :group_id => "99404851@N00")
Run Code Online (Sandbox Code Playgroud)
这些'方法调用'构造一个看起来像这样的api调用
http://api.flickr.com/services/rest/?method=groups.pools.getPhotos&user_id=1848466274& group_id= 99404851@N00
Run Code Online (Sandbox Code Playgroud)
(我已经离开了api键位)它通过记住每个'方法'来做到这一点,直到用参数调用方法,此时它构造url并调用Flickr.
我采用这种方法的原因是ruby代码与Flickr网站上的文档相匹配,你可以复制并粘贴它,它将主要工作,并希望它会使api更改更具弹性,因为我没有硬编码方法.
令人恼火的是,在这个例子中,组ID被传递给getPhotos方法而不是groups方法.我宁愿它看起来像这样.
@flickr.groups(:group_id => "99404851@N00").pools.getPhotos(:user_id => "12656878@N06")
Run Code Online (Sandbox Code Playgroud)
所以我的问题.在Ruby中是否有任何方法可以检测到最后一个方法已被调用,以便我可以触发对Flickr的调用?
由于我想不出任何方法来检测最后一个方法调用,我将建议采用不同的方法.它类似于ActiveRecord的功能; 一个代理类,它构建选项并且在您调用对数据进行操作的方法之前不会获取数据.
class Flickr
def initialize
@result = FlickrResult.new
end
def method_missing(method, *args, &block)
if @result.data.respond_to?(method)
@result.run(method, args, block)
else
@result.append(method, args[0])
return self
end
end
class FlickrResult
attr_reader :data
def initialize
@data = []
@keys = []
@options = {}
end
def append(key, options)
@keys << key
@options.merge!(options) if options
end
def run(method, args, block)
if !@did_run
fetch_data
end
@data.send(method, *args, &block)
end
def fetch_data
puts "Only runs once!"
@url = @keys.join(".") + "?" + @options.map {|k, v| "#{k}=#{v}" }.join("&")
# use @url and fetch data..
@data = ["foo", "bar"]
@did_run = true
end
end
end
@flickr = Flickr.new
@flickr.groups(:group_id => "123").pools.thing.users(:user_id => "456")
@flickr.each {|f| p f }
# => "Only runs once!"
# => "foo"
# => "bar"
p @flickr.map {|f| f.upcase }
# => ["FOO", "BAR"]
Run Code Online (Sandbox Code Playgroud)
它只在你each或map它或任何(任何数组方法)时获取数据.