Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I extend ActiveRecord from app/modules?

I have several different acts_as_... custom class methods I'd like to use in my app. I would like the code for those methods to be in files in the app/modules directory.

I have been unable to get this working.

For instance, I have a file: app/modules/acts_as_lockable

module ActsAsLockable

    def acts_as_lockable
        before_create :set_lock

        include InstanceMethods
    end

    module InstanceMethods
        protected

        def set_lock
            now = Time.now.to_s
            self.lock = Digest::SHA1.hexdigest(now)
        end
    end

end

ActiveRecord::Base.extend ActsAsLockable

And in application.rb

config.autoload_paths += %W(#{config.root}/app/modules)

When I try to load up a model that calls acts_as_lockable I get the following error:

NameError: undefined local variable or method `acts_as_lockable'

My guess is that I shouldn't be autoloading the modules folder because ActiveRecord has already been loaded when I extend it? Is there another way to do this? I would like to be able to alter the file during development without restarting my server but that's more of a want that a need.

like image 557
tanman Avatar asked Jun 09 '11 05:06

tanman


1 Answers

I think you're thinking about this in the wrong way.

You are adding this module to the load path,

but it will only load if you either say;

require 'acts_as_lockable'

or

ActsAsLockable

I'd suggest you never really want to say either of these inside your code.

The correct paradigm you're looking for is an "initializer".

I suggest you create a file called "config/initializers/acts_as_lockable.rb"

In this file you can either include the whole code,

or just include a require 'acts_as_lockable'

Normally I keep things like this inside the libs directory

ensure lib is in the load path

** config/application.rb **

config.autoload_paths += %W(#{config.root}/lib)

** lib/acts_as_lockable.rb **

module ActsAsLockable

  def acts_as_lockable
    before_create :set_lock

    include InstanceMethods
  end

  module InstanceMethods
    protected

    def set_lock
      now = Time.now.to_s
      self.lock = Digest::SHA1.hexdigest(now)
    end
  end

end

then in the initializer

** config/initializers/acts_as_lockable.rb **

require 'acts_as_lockable'
ActiveRecord::Base.extend ActsAsLockable
like image 98
Matthew Rudy Avatar answered Oct 25 '22 09:10

Matthew Rudy