我正在尝试一种我想要反馈的模式:
module Concerns
def AuthenticatedS3Concern(options)
AuthenticatedS3ConcernHelper.go(options)
end
module_function :AuthenticatedS3Concern
module AuthenticatedS3ConcernHelper
def self.go(options = {:attribute => :photo})
@@auth_attr = options[:attribute] # the photo clip reference
@@auth_attr_url = "#{@@auth_attr}_authenticated_url" # set this to do a one time download
Module.new do
def self.included(base)
base.send :include, AuthenticatedS3ConcernHelper::InstanceMethods
end
class_eval %(
def #{@@auth_attr}_authenticated_url(time_limit = 7.days)
authenticated_url_for('#{@@auth_attr}', time_limit)
end
)
end
end
module InstanceMethods
def authenticated_url_for(attached_file, time_limit)
AWS::S3::S3Object.url_for(self.send(attached_file).path('original'), self.send(attached_file).bucket_name, :expires_in => time_limit)
end
end
end
end
可以这样使用:
require 'concerns/authenticated_s3_concern'
require 'concerns/remote_file_concern'
class Attachment
include Concerns.AuthenticatedS3Concern(:attribute => :attachment)
end
我很好奇这是一种好方法还是一种糟糕的方法或者什么。有没有更好的方法来完成这种可变定义的模块内容?
由于
答案 0 :(得分:1)
除了让维护开发人员的大脑受到伤害外,我认为没有任何优势。
据我所知,所有这些代码都是在名为attribute_name_authenticated_url
的包含类中创建一个实例方法 - 它只是authenticated_url_for.
的包装器
您可以使用method_missing
轻松完成相同的操作,或者定义并调用创建实例方法的类方法。 IMO,这种方法更简单易读:
module Concerns
module AuthenticatedS3
def authenticated_url_for(attached_file, time_limit = 7.days)
AWS::S3::S3Object.url_for(self.send(attached_file).path('original'), self.send(attached_file).bucket_name, :expires_in => time_limit)
end
end
end
class Attachment
include Concerns::AuthenticatedS3
end
@attachment = Attachment.new
@attachment.authenticated_url_for(:attribute_name)
元编程技术最好不要妨碍你想要做的事情。
答案 1 :(得分:0)
不确定为什么你需要模块。
如果你需要做的只是动态添加一个动态命名的方法,你可以从:
开始def make_me_a_method meth
define_method(meth){|param=7|
puts param
}
end
class C
make_me_a_method :foo
end
C.new.foo(3)
#=> 3