Rails extending models without modifying the base file
I've got two Rails 2.3 applications, we'll call them admin and frontend. In admin I have all my models specified in app/models
. In frontend I have those models s开发者_开发知识库ymlinked. I would like to add frontend specific methods to a model that only show up for the frontend application, and not the admin app.
At first I tried just adding config.autoload_paths += "#{RAILS_ROOT}/app/augments/address.rb"
with:
class Address
def hello
"hello world"
end
end
But that just wasn't loaded. Calls to Address.first.hello
would be met with undefined method 'hello'
.
If I require a file that does this:
Address.class_eval do
def hello
"hello world"
end
end
It is loaded once, and for the first hit in development it works, but all subsequent reloads it fails. This is due to config.cache_classes = false
in development.
A semi-working solution is to run that from ApplicationController:
class ApplicationController < ActionController::Base
Address.class_eval do
def hello
"hello world"
end
end
end
Which does reload and works every time in dev andprod, but doesn't work for script/runner or script/console. (If this is the only solution I'm sure we could extract that out into a module and include ModelExtensions
in ApplicationController.)
Is there something I can add to environment.rb or an initializer that will get reloaded every time in development?
To extend your class you should use module and include it in your model. Something like this:
module Address
def hello
"hello world"
end
end
This is an old but always interesing article on that argument: http://weblog.jamisbuck.org/2007/1/17/concerns-in-activerecord
To include the module only in frontend you should check if the module exists with:
Class A
include Address if defined? Address
end
精彩评论