2011-03-03 143 views
0

动态创建的模块,我用一个模式尝试,我想反馈:红宝石

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

不知道为什么你需要的所有模块。

如果你需要做的就是动态添加动态命名的方法,你可以开始:

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 
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) 

元编程技术时最好吃不的你想要做什么的方式获得。