Модификация модуля ActiveRecord для работы с любой моделью - PullRequest
1 голос
/ 02 июля 2011

Итак, некоторое время назад я создал небольшой модуль для использования в качестве методов, необходимых для голосовой полиморфной ассоциации, и, хотя он изначально предназначался для использования только для ActiveRecord, сейчас я хочу использовать его с mongo, и, поскольку я ' При использовании mongoid все методы для ассоциаций, которые мне нужно создать в этом примере, имеют одинаковые имена, и здесь все рассмотрим мой предыдущий код:

# 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 Ответ

3 голосов
/ 03 июля 2011

Сначала поместите это в инициализатор или в /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
...