简体   繁体   中英

Can I edit the gem installed using 'gem install' or from my gemfile?

On my server (or laptop for that matter) whenever I install a gem using:

gem install mygemname

or in my gemfile:

gem 'mygemname'

It will install on the computer to some folder on my computer.

Can I go to that folder and edit the file if I want to say add some logging etc.?

If this is not possible, I remember reading that you can have the gem source code installed in your rails 3 application under the 'vendor' folder. How do I install it locally so I can edit it and add logging to it (to learn how it works etc.)

Can you?

Yes

Should you?

Absolutely Not.

Why?

  • Modifying the gem source makes it very difficult to upgrade to newer versions of the gem
  • It's much harder to debug an issue
  • It will cause HUGE headaches down the line
  • It makes it difficult to work in a collaborative environment (does every developer have the correct hacked gem?)
  • It causes questions like these (ie where should I hack a gem?)

Solutions

There are a few ways to solve this problem:

Submit a Patch

If you feel that this 'change' would benefit the entire community, find the source code (most likely on github ), fork, apply the patch, write tests, and submit a pull-request. If the developer agrees that your patch is viable, it will be merged into the project and released with the next version of the gem.

Advantages
  • You are helping the community
  • You have a local copy of the gem (since you forked it) on your development machine
Disadvantages
  • You have to wait for the developer to accept your patch
  • This can be pretty time-consuming

Re-Gem

If you don't think this is something the entire community would benefit from, but you still want to allow your other developers to use the gem in a systematic way, fork the existing gem, apply your patch, rename the gem, and publish. in this case, it's good practice to prefix your custom gem with the original gem name. For example, if the gem was named foo , you would name your gem foo-my-company . You now can choose to open-source that gem (push to rubygems) or push it to a private development gem server within your organization. You still must source the original gem author in your re-gem!

Advantages
  • Don't have to wait for a developer
  • Central code base
  • Easily shared
Disadvantages
  • Difficult to update from original gem
  • Can be cumbersome to maintain

Local Lib (monkey-patch)

You can create a monkey-patch inside your application and override any methods or properties that don't fit your current environment.

Advantages
  • Quick and Easy
  • Easily Shared (via git - just include the patch file in your repo)
Disadvantages
  • Updating the gem is difficult
  • It's not clear to other developers that you are modifying the Gem's core
  • Harder to debug (is it an error with the gem or your patch?)

Fork and Source

This is my recommended option. Why did I put it last - the other ones are more common. In this method, you fork the gem from its original repository (probably on github), and then source your gem from your git repo. For example, say the gem was named foo , you would fork foo to username/foo on github. Apply you patches, changes, whatevers. Then in your Gemfile:

 gem 'gem_name', :git => 'git://github.com/username/foo' 

This will install and compile the gem from source at your repo every time the bundle command is run. You can also specify a particular tag and branch (recommended to stability).

Advantages
  • You can easily update upstream (you have a fork - pull from the upstream, merge, you have all changes)
  • Version control is easy (use tags and branches for various versions)
  • Everyone has access to the same gem source
  • Easy to manage updates
Disadvantages
  • Your "custom" code is public (although you could use a custom git server instead of github to solve this)

Conclusion

Each method has its own advantages and disadvantages (which I've tried to enumerate as best as possible). In any event, the method you suggested is not an advised method for solving that problem.

If readers have comments about other advantages/disadvantages, please list them, and I'll add them to my answer.

Sure, it's just code.

Should you? Not in general, since it could be re-installed, updated, etc.

Since you can re-open classes IMO it's safer to monkey-patch, embrace and extend, etc. This isn't always as practical as direct modification, of course.

For educational purposes (when it doesn't matter if modifications are lost), it's fine, and makes more sense than duplicating everything. AOP-ish logging is often doable w/o modifying the original source, though. Sometimes cloning a repo and using it, particularly during exploratory phases, is cleaner.

Dave Newton's advice is wisdom and you should take it, but there's nothing wrong with taking a look at it to learn something. Running gem env will show you where your gems are installed; the lib directory is where you tend to find the meat of the code.

We have had this discussion at work, and it is a practice I discourage.

Gems are made to be updated when improvements and bug-fixes are made. That will instantly wipe out the changes you have done, breaking your code.

You can freeze your version by making it read-only, or use bundler or copying the entire Ruby distribution, but in each of those you are going against the flow.

Instead, I recommend:

  1. Write a patch to the method in question in one of your own files. I've copied the method definition into a separate file in my app's lib directory, and made the change there, then required it last, allowing the method to be fixed without subverting Gem's normal use.
  2. Submit your change to the gem maintainer as a patch, along with your reason for needing the change.
  3. Remove the file and the require if/when the change is accepted.

I used to work at a major corporation that decided it was a good idea to make a patch to one of the source files in their mail system. The software was not something they wrote themselves, so, as time went by, they spent more and more time having to roll in their "special" changes to the software as the vendor grew the product. Eventually, it took months to roll in the changes and made the software fragile, which is not a good thing for something that is a core-business service. Ruby's ability to redefine a method would have saved them untold dollars and months of work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM