修改ActiveRecord模块以使用任何模型

时间:2011-07-02 16:24:14

标签: ruby-on-rails activemodel

前一段时间我创建了一个小模块作为可选多态关联所需的方法,虽然它原本只用于ActiveRecord,但我现在想用mongo,因为我' m使用mongoid我需要在这个intance中创建的关联的所有方法具有相同的名称,并在此处查看我之前的代码:

# config/initializers/acts_as_votable.rb

module ActsAsVotable

end

module ActiveRecord
  class Base
    class << self
      cattr_accessor :votable

      def acts_as_votable
        has_many :votes, :as => :voteable
      end

      def acts_as_voter
        has_many :votes, :as => :voter
      end

      def votable?
        method_defined? :votes
      end
    end

    def votable?
      self.class.send(:method_defined?, :votes)
    end
  end
end

以下是它的使用方法:

class Recipe < ActiveRecord::Base
  acts_as_votable
  # more stuff...
end

所以你会注意到这里有两个问题,首先,我正在扩展ActiveRecord::Base,我怎样才能让这个工作适用于任何模型,而不仅仅是那些继承自ActiveRecord的模型?实际上需要一个像ActsAsVotable那样的空模块吗?我在这里做错了什么?

如果我只将所有代码放入模块ActsAsVotable,我是否应该只能从我的模型中调用includes ActsAsVotable

1 个答案:

答案 0 :(得分:3)

首先,将它放在初始值设定项或/lib中,但要确保路径已加载到应用程序中。

module ActsAsVotable

  extend ActiveSupport::Concern

  module InstanceMethods
    def votable?
      self.class.send(:method_defined?, :votes)
    end
  end

  module ClassMethods
    cattr_accessor :votable

    def acts_as_votable
      has_many :votes, :as => :voteable
    end

    def acts_as_voter
      has_many :votes, :as => :voter
    end

    def votable?
      method_defined? :votes
    end

  end
end

然后在任何模型中:

class User < ActiveRecord::Base

  include ActsAsVotable

end

最后:

User.methods.include?("acts_as_votable") # => true