2013-03-21 88 views
2

我有几个共享问题的模型。每个模型都会传入一个散列,这意味着要处理他们使用这个问题的方式上的细微差别。我通过一个类的方法通过散列像这样:Rails:将变量从类方法传递到实例方法

add_update_to :group, :user 

的关心完整的代码是:

module Updateable 
    extend ActiveSupport::Concern 

    attr_accessor :streams 

    module ClassMethods 
    def add_updates_to(*streams) 
     @streams = streams 
    end 
    end 

    module InstanceMethods 
    def update_streams 
     @streams.collect{|stream| self.public_send(stream)} 
    end 
    end 

    included do 
    has_one :update, :as => :updatable 

    after_create :create_update_and_history 
    end 

    private 
    def create_update_and_history 
     update = self.create_update(:user_id => User.current.id) 
     self.update_streams.each do |stream| 
     stream.histories.create(:update_id => update.id) 
     end 
    end 
end 

大部分代码的工作,但我有从通过哈希麻烦该类到一个实例。目前,我试图通过创建一个虚拟属性来实现这种效果,将散列传递给属性,然后在实例中进行检索。这不仅感觉不舒服,而且不起作用。我假设它不起作用,因为@streams是一个实例变量,所以类方法add_update_to不能实际设置它?

无论如何,有没有更好的方法来解决这个问题?

回答

3

你也许可以在这里使用类变量,但是由于它们的不可预测性,这些在Ruby社区中是非常令人讨厌的。需要记住的是,Ruby中的类实际上也是类的实例,并且可以拥有自己的实例变量,这些变量只能被自己访问,并且不能被其实例访问(如果以任何方式清除的话)。

在这种情况下,要定义行为,而不是数据,所以我觉得既不instance和类变量是合适的。相反,我认为最好的方法是直接在类方法中定义的实例方法,像这样:

module Updateable 
    extend ActiveSupport::Concern 

    module ClassMethods 
    def add_updates_to(*streams) 
     define_method :update_streams do 
     streams.collect {|stream| public_send(stream) } 
     end 
    end 
    end 
end 

BTW,没有这里涉及到散列,所以我不知道你指的是什么。 *streams将您的参数收集到数组中。

+0

优秀的回应。它的工作原理,并感谢您花时间解释您的答案。不过,有一件事我不明白,为什么你不必在'public_send(stream)'上调用'self'。 “自我”暗含了什么? – nullnullnull 2013-03-21 03:04:04

+1

是的,“自我”通常是可选的。在一个实例方法中,任何未明确发送给另一个对象的方法调用会转到“self”。 – 2013-03-21 03:43:33

相关问题