Let's say I have a Rails app that gets most of it's functionality from a gem (for instance, a CMS).
If I now need to add some customisation (for instance, add a property to a user) what is the best practice way of doing this? If I customise the gem, then I will have issues with updating the gem in the future.
What is the best approach to take here?
Extend is also used to importing module code but extends import them as class methods. Ruby will throw an error when we try to access methods of import module with the instance of the class because the module gets import to the superclass just as the instance of the extended module.
If you are going to support multiple languages, such as C and Java extensions, you should put the C-specific ruby files under the ext/ directory as well in a lib/ directory. When the extension is built the files in ext/my_malloc/lib/ will be installed into the lib/ directory for you.
Note that you need an account at RubyGems.org to do this. From the main menu, select Tools | Gem | Push Gem. In the Run tool window, specify your RubyGems credentials. Your gem will be published to RubyGems.org.
Ruby native extensions are libraries written in C using the built-in functions of the RubyVM. Basically, it's C programming with a ton of functions and macros to interact with the virtual machine. Anything that can be achieved by using pure Ruby can also be implemented using the built-in instructions.
This question is quite old, but I feel it could use a bit more fleshing out. It is true that you can monkeypatch rails (and ruby) at run-time. That means it's easy to reopen a class or module and inject new code. However, this is somewhat trickier in rails due to all the dynamic class loading and unloading that goes on development mode.
I won't go into details, but you really want to put your extensions into an initializer, or a gem, since they get reloaded between requests in dev mode. If you put the code into a plugin it won't get reloaded and you'll get very mysterious errors such as "A copy of XXX has been removed from the module tree but is still active!"
The easiest thing to do is throw the code into an initializer (e.g. config/initializers/user_extensions.rb). You can just use class_eval to inject the code.
User.class_eval do
... new code ...
end
One major drawback of ruby's extensibility is tracking down where code is coming from. You might want to add some kind of log message about the extensions being loaded, so people can track it down.
Rails.logger.info "\n~~~ Loading extensions to the User model from #{ __FILE__ }\n"
User.class_eval do
... new code ...
end
Further reading:
http://airbladesoftware.com/notes/monkey-patching-a-gem-in-rails-2-3
Ruby allows you to extend classes in runtime, so you can often hack in to a library without touching the source code. Otherwise I would suggest that you download the gem, create some hooks in the library and submit that back as a patch.
Update:
Note that these customisations are application specific
Yes. What I meant was to modify the generic api in a way, such that it is possible to customise per application. For example, by allowing the user to pass a block to certain methods etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With