Reputation: 4792
I am using Ruby 1.9.2 and Ruby on Rails 3.2.2. I have following statements:
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
In the above code I am trying to override both acts_as_something
and has_many
methods added to the Category
class by the including Commentable
module. Both methods are stated "in the scope of" Category
so the above code does not work as expected: methods are not overrode.
Is it possible to override those methods? If so, how?
Upvotes: 2
Views: 2105
Reputation: 230561
You should include your module in the end of your class definition. As it is now, methods from the module get injected before the class defines its method. This is so because ruby processes and evaluates code in the top-down manner. Therefore, a little bit later it encounters class' own definitions of the methods and overwrites those that came from the module.
So, use this knowledge according to your intention: who should override whom. If methods from the module should take dominance over those in the class, include it in the end.
Given this code
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
Then
class Foo < Base
include Commentable
has_many :comments
end
# class overrides module
Foo.new.many_comments # => "I am having many comments with {}"
And
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\"}"
Upvotes: 4