Rails 3 - Extending a model that exists in a gem or plugin
In the RefineryCMS gem there is a Page model that is used to pull in information from the CMS. The model is not defined in your current app and therefore you cannot modify its code (unless you hop into the gem code).
Is there a way to modify the methods within an existing model without having to apply the changes each time a page is loaded? Here is what I have tried:
Model.class_eval
Model.send :i开发者_Python百科nclude, MixinThatHasNewMethods
I've also tried creating a new class with the updated methods and hoping that would update the existing class.
Any ideas?
Ruby allows the developer to "update" any object, at anytime.
That means that after Model
is loaded by RefineryCMS you can just reopen the class and update it:
class Model
def new_method(value)
...
end
def existing_method(*args)
...
super # refer to the ovewriten method
end
end
In your case RafineryCMS is an RoR app, that means while loading the server the ruby code is loaded first for the rails framework, then for the RafineryCMS gem/plugin and after all for your custom libraries (eg: lib folder).
The important point here is the loading order of the code, modification should be loaded after the genuine class code.
That is in your lib or initializers (not really a good place but it works) you should put your custome methods for the Model class.
EDIT: I was reading your question again, and I have to mention, that you are wrong, you actually can change a class from a gem or plugin. ruby load every object in the same scope and all objects are accessible to be overwritten.
In development environment, RoR, reloads all classes (except if cache_classes = false) on every request. It is possible, that after the first request, the gem is reloaded and your changes are lost. Take care to reload your libraries after for every request (only in developement env)
PS: include & class_eval would work too, the important thing is too overwrite a previously loaded class
If I understand your question correctly, you can do something like this.
You may override the model as follows. Say you have the following class:
class User
def name user_name
p "my name is #{user_name}"
end
def age my_age
p "age - #{my_age}"
end
end
then you can call this class by:
user = User.new
user.name "sameera"
user.age 30
and you will get the output:
"my name is sameera"
"age - 30"
then say you want to change only the behavior of the 'name
' method, the you can re-create the user class and add only that method as follows:
class User
def name user_name
p "my modified name #{user_name}"
end
end
and still you can call both the methods as follows:
user = User.new
user.name "sameera"
user.age 30
But this time, your output will be:
"my modified name sameera"
"age - 30"
I think you got my point, hope this helps.
**NOTE: make sure you call the modified 'User
' class before you load the original User
class.
精彩评论