views:

1110

answers:

3

I've done some reading about how to extend ActiveRecord:Base class so my models would have some special methods. What is the easy way to extend it (step by step tutorial). Thx!

+2  A: 

Step 1

module FooExtension
  def foo
    puts "bar :)"
  end
end

Step 2

ActiveRecord::Base.send :include, FooExtension

Step 3

There is no step 3 :)
Vitaly Kushner
I guess step 2 must be placed into config/environment.rb. It's not working for me :(. Can you please write some more help? Thx.
xpepermint
+6  A: 

There are two approaches to this:

Monkey patching

Create a file in the config/initializers directory called active_record_monkey_patch.rb.

class ActiveRecord::Base        
  def bar
   "foo"
  end

  def self.find_values opts
    sql = self.send(:construct_finder_sql, opts)
    self.connection.select_values(sql)
  end
end

Modules

Create a file called app_util.rb in the lib directory.

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

    # add your instance methods here
    def bar
       "foo"
    end

    module ClassMethods
      # add your static(class) methods here
      def find_values opts
        sql = self.send(:construct_finder_sql, opts)
        self.connection.select_values(sql)
      end
   end
 end
 # include the extension 
 ActiveRecord::Base.send(:include, MyActiveRecordExtensions)

Include the file at the end of your config/environment.rb file.

require "app_util"
KandadaBoggu
Hum... for second example when I run ./scripts/console I get an error"`include':TypeError: wrong argument type Class (expected Module)".
xpepermint
@xpepermint Sounds like you started it with `class MyActiveRecordExtensions` instead of `module MyActiveRecordExtensions`.
Jimmy Cuadra
xpepermint
You have to `require` the file at the end of `environment.rb`. I have added this extra step to my answer.
KandadaBoggu
+6  A: 

You can just extend the class and simply use inheritance.

class AbstractModel < ActiveRecord::Base  
  self.abstract_class = true
end

class Foo < AbstractModel
end

class Bar < AbstractModel
end
Toby Hede
I like this idea because is a standard way of doing it but... I get an error Table 'moboolo_development.abstract_models' doesn't exist: SHOW FIELDS FROM `abstract_models`. Where should I put it?
xpepermint
Add `self.abstract_class = true` to your `AbstractModel`. Rails will now recognize the model as an abstract model.
KandadaBoggu
Good catch, cheers
Toby Hede
there must be something that you did not write :). It is not working for me. I created abstract.rb in models, added the code there...
xpepermint
Ha... it works... It was a name who cosed problems. Abstract class must be renamed to X and it works. Thx.
xpepermint