Rails: How to define an association extension in a module that is part of my AR model?

I have a module Blockablethat contains associations and methods that should be included in several other classes ActiveRecord.

Relevant Code:

module Blockable
  def self.included(base)
    base.has_many :blocks
  end
end

I want to add an extension to the association. The usual syntax (i.e. when I do not define an association in a module) looks like this:

# definition in Model < ActiveRecord::Base
has_many :blocks do
  def method_name
    ... code ...
  end
end

# usage
Model.first.blocks.method_name

This syntax does not work when used in a module that is included in the AR model. I get it undefined method 'method_name' for #<ActiveRecord::Relation:0xa16b714>.

Any idea how I should determine the extension of an association in a module to be included in other AR classes?

+5
source share
3 answers

Arg, I suck.

, .

, , Xavier Holt Rails 3.0.3:

self.included(base)
  base.has_many :blocks do 
    def method
      ...
    end
  end
end

# OR

self.included(base)
  base.class_eval do 
    has_many :blocks do
      def method
        ...
      end
    end
  end
end
+2

Rails 3 . The Rails 3 Way, 2nd Edition:

module Commentable
  extend ActiveSupport::Concern
  included do
    has_many :comments, :as => :commentable
  end
end
+7

I have something similar working in my Rails code (2.3.8) at the moment. I used base.class_eval, not base.has_many:

module Blockable
    self.included(base)
        base.class_eval do
            has_many :blocks do
                def method_name
                    # ...stuff...
                end
            end
        end
    end
end

Whew - it was a lot of spaces ...

In any case, it works for me - I hope it works for you too!

+4
source

All Articles