views:

182

answers:

2

How do I create a module that when included in a model will automatically add some relationships and named_scopes?

Here's what I've got right now:

module Resource

has_many(:permissions)
  named_scope(
     :acl_check,
     lambda do |user_id, method| {
      :include => :permission,
      :conditions => [
       ["permissions.user_id=?", user_id],
       ["permissions.method=?", method],
       ["permissions.classname=?", self.class.name]
  ]
 }
  end)

end

Although I'm getting the following error when I try to start my server:

......config/initializers/Resources.rb:5: undefined method `named_scope' for Resource:Module (NoMethodError)

Thanks to all who respond! :)

+1  A: 

You want to override the included() or extended() method on the module, which is called whenever the Module is (surprisingly enough) included or extended. Something like the following should do what you want:

module Foo
  def self.extended (base)
    base.class_eval do
      has_many :doodads
    end
  end
end

That's simplified a bit for clarity, but you should be able to add all the named scopes, etc, from your original example.

John Hyland
Just put your suggestion together and I'm still getting method not found errors.At least it runs! LOLWhat else could be going on?
Omega
I should be more specific. My named scope isn't working, it appears as though has_many(:permissions) works!
Omega
A: 

Method called in models will be called when Ruby sees the module, not when it is included.

module MyModule
  running_a_class_method
end
# => NameError: undefined local variable or method ‘running_a_class_method’ for MyModule:Module

You have to make sure that the call to this class method runs when the module is included. Ruby has an event handler for inclusion, included. The class/module you include it into is passed as an argument to that method.

module MyModule
  def self.included(base)
    puts base
  end
end

class Thing
  include MyModule
  # => Thing
end

An example that is closer to what you want to achieve:

module Resource
  def self.included(base)
    base.has_many :permissions
    base.named_scope :foos, :conditions => ["..."]
  end
end
August Lilleaas
I can get the regular relationships working, but when I try to do a named scope, it doesn't show up.I get:"undefined method `by_class' for #<Class:0x7f0bea7e25f0>"As you can see, it is attempting to perform the operation on Class??? Not sure what's up with that...
Omega
I don't see any references to `by_class` in the code you pasted, so idk
August Lilleaas