Reputation: 3407
I'm building a gem in which part of its purpose is to extend associations on a target Class. Although I can easily extend all associations by using something like :
ActiveRecord::Relation.send(:include, MyGem::ActiveRecord::RelationMethods)
This is too broad, and for a Rails App that may use this Gem, I don't want to extend associations for all Classes.
For better granularity, I want to provide the equivalent of :
class User < ActiveRecord::Base
has_many :messages, :extend => MyGem::ActiveRecord::RelationMethods
has_many :comments, :extend => MyGem::ActiveRecord::RelationMethods
end
By using
class User < ActiveRecord::Base
acts_as_my_fancy_gem
has_many :messages
has_many :comments
end
The problem I have is trying to conditionally extend associations within the Gem, when acts_as_my_fancy_gem
is added to a class. This is the bare bones of it.
module MyGem
extend ActiveSupport::Concern
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def acts_as_my_fancy_gem
include MyGem::InstanceMethods
end
end
module InstanceMethods
...
end
end
I've looked into reflections, but at this point can find a clear path, and have simply taking stabs in the dark to experiment.
UPDATE:
Currently, I can achieve this with each association by providing a class method like
class User < ActiveRecord::Base
has_many :messages
has_many :comments
fancy_extend :messages
end
module MyGem
extend ActiveSupport::Concern
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def acts_as_my_fancy_gem
include MyGem::InstanceMethods
end
def fancy_extend *associations
class_eval do
associations.each do |association|
reflections[association].options[:extend] = MyGem::ActiveRecord::RelationMethods
end
end
end
end
module InstanceMethods
...
end
end
Adding this approach into the act_as_my_fancy
method (which is where I would like to have it) gives me :
# NoMethodError: undefined method `options' for nil:NilClass
Upvotes: 2
Views: 471
Reputation: 18845
Is this rail4? I did not find the :extend
option documented. It looks like rails 4 uses blocks to do that nowadays.
It could be as simple as this:
module Fancy
def has_many(name, scope = nil, options = {})
super(name, scope, options) do
def doit
"i did"
end
end
end
end
# in your model
extend Fancy
YourModel.your_relation.doit # => 'i did'
Upvotes: 1