2

Ruby 1.9.2 と Ruby on Rails 3.2.2 を使用しています。私は次の声明を持っています:

class Category < ActiveRecord::Base
  include Commentable

  acts_as_list :scope => 'category_comment_id'

  has_many :comments, :class_name => 'CategoryComment'

  # ...
end

module Commentable
  extend ActiveSupport::Concern

  included do
    acts_as_list :scope => 'comment_id'

    has_many :comments, :class_name => 'Comment'

    # Other useful method statements...
  end

  # Other useful method statements...
end

上記のコードでは、組み込みモジュールによってクラスに追加されたacts_as_somethinghas_manyメソッドの両方をオーバーライドしようとしています。両方のメソッドが「スコープ内」に記載されているため、上記のコードは期待どおりに機能しませ。メソッドはオーバーライドされません。CategoryCommentableCategory

これらのメソッドをオーバーライドすることは可能ですか? もしそうなら、どのように?

4

1 に答える 1

4

クラス定義の最後にモジュールを含める必要があります。現在のように、クラスがそのメソッドを定義する前に、モジュールからのメソッドが注入されます。これは、Ruby がコードをトップダウンで処理および評価するためです。したがって、少し後にクラス独自のメソッドの定義に遭遇し、モジュールから来たものを上書きします。

したがって、この知識を意図に応じて使用してください。誰が誰をオーバーライドする必要があります。モジュールのメソッドがクラスのメソッドよりも優先される場合は、最後に含めます。

編集

このコードを考えると

require 'active_support/core_ext'

class Base
  def self.has_many what, options = {}
    define_method "many_#{what}" do
      "I am having many #{what} with #{options}"
    end
  end
end

module Commentable
  extend ActiveSupport::Concern

  included do
    has_many :comments, class_name: 'Comment'
  end
end

それで

class Foo < Base
  include Commentable
  has_many :comments
end

# class overrides module
Foo.new.many_comments # => "I am having many comments with {}"

class Foo < Base
  has_many :comments
  include Commentable
end

# module overrides class 
Foo.new.many_comments # => "I am having many comments with {:class_name=>\"Comment\"}"
于 2012-10-28T13:54:12.560 に答える