Gems or svn:externals?
From WhyNotWiki
Gems or svn:externals? / QualitySmith sync edit
This is mostly a discussion about the possibility of unpacking all gems and adding them to svn... But more generally it's about how best to handle gem dependencies.
See also: How do we know that all the gems will be there when I deploy?
Also aliased as Gem dependencies: should we unpack all gems?
Applies to:
- our own code/gemables/plugins
- could also apply to 3rd-party gems
[edit] What to do about locally-developed gems
[edit] Option 1: install gem system-wide, then specify specific version in your require
Possible problems:
- We may forget to update gems when we deploy to production (!). See Deployment#.21.21_How_do_we_make_sure_all_the_gems_we_need_are_installed_on_the_production_servers.3F.
- If you just want to make a little change to a library and then test that it works (in the context of another project you're working on), the most tempting/easiest option is to just sudo edit the system-wide gem version of that .rb file. But that's a bad idea in a shared development environment... Plus, even if you do get it working the way you want it, then you have to manually copy those changes back into a working copy so that you can commit them.
- The other alternative, which I sometimes end up doing, is to just make the changes in my working copy and do a
gem install --force(rake clean gem_install) after every little change, to test it out. - The heart of this problem, though, is Problem: How to develop/modify a plugin in the context of a working app.
- The other alternative, which I sometimes end up doing, is to just make the changes in my working copy and do a
- If you install a new version of a gem that you're working with on a shared development server, it may unintentionally cause problems for other developers.
- If everyone specifies a version number in their "gem" commands, then it shouldn't affect the other developers at all. RubyGems will continue to load the older version for the other developers while you, who are working on the newer version, can specify the newer version number in your gem command...
- It could be a problem if someone tries to re-install overtop of an existing version number (
gem install --force). Which is one reason why you generally shouldn't do that.
Advantages:
- Fewer svn:externals means less file duplication (wasted disk space), faster
svn updates, and less clutteredsvn statusoutput... - Only have to update once and it will update the gem for the entire system (all users and all applications that use the gem).
- RubyGems has a more sophisticated dependency system, allowing you to depend on other gems and even specify a minimum version number, etc.
[edit] Option 2: Use svn:externals pointing to repository containing our gemable
Could point to "edge" or use versioned externals/piston to point to a specific version and upgrade to a newer version manually.
[edit] Template:Feedback Proposal
I propose that we make all of our gemables into gems and depend on them using RubyGems rather than svn:externals.
We may want to continue using svn:externals for Rails plugins, at least for now but even that, I think, may change, as I've heard/seen that it is even possible to distribute plugins as gems ("plugems"?).
--Tyler (2007-04-30 10:48)
[edit] What to do about 3rd-party gems
[edit] Option 1: install gem system-wide, then specify specific version in your require
[edit] Option 2: gem install, unpack, and add to svn
If we do unpack them, we have to explicitly require them in Rails.
The "Gems" plugin looks like it could help to handle the unpacking/freezing ... and adding to $LOAD_PATH [1]
This is a small plugin that helps with Ruby Gem management for your application. It will automatically include all gem/lib paths into the $LOAD_PATH on startup.
To freeze gems:
$ rake gems:freeze GEM=tzinfo ...Be sure to require them in your environment.rb if you want them available.
(Or: This snippet looks like it might be a good way to load everything in vendor.)
Unresolved problem: the gem itself may have gem statements.
[edit] Option 3: gem install --install-dir my/project/vendor/ and add to svn
(Install to a directory within your application)
Unresolved problem: the gem itself may have gem statements.
[edit] Option 4: Use svn:externals pointing to remote repository
Problem: they may not have exposed their SCM, or they may use an SCM other than Subversion.
Problem: if pointing to "edge" version, things could break unexpectedly. Solution: versioned externals or Piston.
[edit] Option 5: Use Piston to handle syncing with remote repository/vendor drops
[edit] Discussion
http://jayfields.blogspot.com/2006/10/rubygems-shared-ruby-code.html
http://weblog.rubyonrails.org/2006/3/31/freeze-is-cool-so-freeze-for-goodness-sake
- "If thou bless thee world with an application of open source, thou must ship it with the version of Rails that thou knowest it to work with in vendor/rails."
- Here’s one counter argument that will not allow you to evade this finger: “But it’ll make my app X% larger to download”. In this day of age, nobody cares. Time is more valuable than disk space and saving hair-pulling aggravation over broken dependencies is infinitely more valuable than disk space.
Bond
- Why don’t we use the version-freezing feature that gems already support? I for one like being able to keep my gems up to date centrally and to do mass upgrades. Having to do this for each and every Rails application will be a nightmare.
Aaron Blohowiak
- personally, I prefer svn:externals to a particular revision, as this keeps all of that crap out of my repository and ensures i have it where i need it.
- I agree with convention over configuration, but there is already a convention—gem depencies. Let’s use that as the default.
DGM
- It violates the DRY principal. Why do you make and use a framework that does everything possible to not repeat things, and yet you effectively reccomend a cut and paste to keep the right version of rails with your app. That’s all freeze edge does… a copy and paste of rails into your own app’s structure. Wasteful!
- Why not include a complete copy of ruby while you’re at it!
- gems have versioning capability. Please use it!
Chad Woolley
- Please don’t force untold numbers of duplicate copies of Rails to be checked into SCM repositories the world over. This would be a Very Bad Idea.
- Take a lesson from Maven, using versioned external dependencies from a central repository is a proven and reliable practice. It can also be extended to encompass your own custom dependencies from a local repository.
- Automatic cloning of the an framework source tree into every app would be a very large step in the wrong direction. All Duplication Is Evil!
- The Gems approach provides everything you need for controlled versioning and dependency management (except perhaps for resolution of dependency chains through enforced project dependency metadata, which is the next big step that Maven2 is tackling, but that’s an advanced topic that’s lightyears ahead of the current ruby/gems/rails status quo). Centralized hosting of dependencies is Good Thing.
Lance: It definitely seems cleaner to use versioned svn:externals. Would that mean we need to keep a copy of everything we use in our repo?
- Yeah, I guess it would ... which I have mixed feelings about...
- If we unpacked all our gems, would we rely only on the unpacked versions? And not even install the gems on the system? Or if we had both available, could we easily tell it to use the unpacked version and not the installed gem? Things to think about...
Ezra: Not all gems work with unpack
Tyler: Show me one that doesn't.
[edit] How to unpack a gem
http://www.hostingrails.com/forums/wiki_thread/2 (Install and freeze your own RubyGems)
http://rubygems.org/read/chapter/10#page39
- The unpack command creates a private copy of the named gem’s contents into a new directory. This enables you to examine the contents without interfering with the gem repository.
- You can only unpack gems that you have installed, and you must specify the gem name exactly.
[edit] See also
Dependency problems edit (Category edit) Category:Dependency problems
