views:

57

answers:

1

Hello, i've the following code and tried the whole day to refactor the class methods to a sperate module to share the functionality with all of my model classes.

Code (http://pastie.org/974847):

class Merchant
  include DataMapper::Resource

  property :id, Serial                                             
  [...]

  class << self
    @allowed_properties = [:id,:vendor_id, :identifier]

    alias_method :old_get, :get 
    def get *args
      [...]
    end         

    def first_or_create_or_update attr_hash  
      [...]
    end     
  end

end     

I'd like to archive something like:

class Merchant
  include DataMapper::Resource
  include MyClassFunctions
  [...]
end

module MyClassFunctions
  def get [...]
  def first_or_create_or_update[...]
end

=> Merchant.allowed_properties = [:id]
=> Merchant.get( :id=> 1 )

But unfortunately, my ruby skills are to bad. I read a lot of stuff (e.g. here) and now i'm even more confused. I stumbled over the following two points:

  1. alias_method will fail, because it will dynamically defined in the DataMapper::Resource module.
  2. How to get a class method allowed_properties due including a module?

What's the ruby way to go?

Many thanks in advance.

A: 

Here is a good discussion on ruby class method module inheritance. Something like this could work:

module MyFunctions
  module ClassMethods
    @allowed_properties = [:id,:vendor_id, :identifier]

    def get *args
      opts = super_cool_awesome_sauce
      super opts
    end

    def first_or_create_or_update[...]
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class Merchant
  include DataMapper::Resource
  include MyFunctions
  [...]
end

Because it is using a form of inheritance you can take advantage of super instead of using alias_method, which many find to be more straight forward.

Using ModuleName::ClassMethods is something you see alot in the Rails codebase and makes it easier to use super.

BaroqueBobcat