How to extend ActiveRecord action from application / modules?

I have several different methods of act_as _... custom class that I would like to use in my application. I would like the code for these methods to be in files in the application / module directory.

I was not able to get this work to work.

For example, I have a file: app / modules / actions_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 a model that calls act_as_lockable, I get the following error:

NameError: undefined local variable or `act_as_lockable 'method

I assume that I should not autoload the modules folder because ActiveRecord is already loaded when I produce it? Is there any other way to do this? I would like to be able to modify the file during development without rebooting my server, but this is more necessary for this.

+6
source share
2 answers

I think you think about it wrong.

You add this module to the boot path,

but it will only load if you say:

 require 'acts_as_lockable' 

or

 ActsAsLockable 

I would advise you to never want to talk about this inside your code.

The correct paradigm you are looking for is the "initializer."

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

In this file you can include all the code,

or just enable require 'acts_as_lockable'

I usually keep these things inside the libs directory

ensure lib is in the boot path

** config / application.rb **

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

** lib / actions_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 / actions_as_lockable.rb **

 require 'acts_as_lockable' ActiveRecord::Base.extend ActsAsLockable 
+7
source

The problem is that ruby's autoload mechanism is a lazy process: when a constant like ActsAsLockable is used in your code, it looks for a file called act_as_lockable.rb inside autoload_paths. Since you never use ActsAsLockable, the file never loads. You could do (though not very pretty):

 ActsAsLockable class MyModel < ActiveRecord::Base acts_as_lockable ... end 

I think pattern_as_ * will be used for plugins and gems to easily integrate functionality into your code. Plugins and gems should be in the final state when you integrate them into your project so that you do not need a reboot in development mode.

Hope this helps.

0
source

Source: https://habr.com/ru/post/890114/


All Articles