I am new in rails 3 and need to know how rails manage gem dependencies in rails 3 also i need to know how it is differ from older rails version?
I don't think there have been any changes to the basic workflow. It is enabled by default in Rails 3 whereas you had to set it up manually in 2.3.x.
Basically, bundler takes the requirements set out in your Gemfile (gem name, minimum version, exact version etc), and it works out a set of gems that meet those requirements. It records the exact versions in Gemfile.lock, and takes responsiblity for 'requiring' any gems you need in your application.
It's worth reading the manual, especially with respect to the various deployment options.
See gembundler.com for a summary of how to use it in Rails 3.
Related
I was browsing rubygems.org for themes in Jekyll and they were causing trouble with the current versions of jekyll.
Like here I was trying out linaro-jekyll-theme. and I got this
Fetching gem metadata from https://rubygems.org/.........
Resolving dependencies....
Bundler could not find compatible versions for gem "jekyll":
In Gemfile:
jekyll (~> 4.2.1)
linaro-jekyll-theme was resolved to 1.0, which depends on
jekyll (~> 3.4)
Bundler could not find compatible versions for gem "linaro-jekyll-theme":
In snapshot (Gemfile.lock):
linaro-jekyll-theme (= 1.0)
In Gemfile:
linaro-jekyll-theme
Running bundle update will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
How to change jekyll versions according to the needs. Is there any problem associated with changing versions so many times?
A Jekyll theme (or any gem in general) might depend on a certain version of another gem because
is depends on certain features that were removed or changed in later versions or
the author just pinned the version as a reminder to check compatibility when a new major version is released because major releases might break the gem.
In this example, the author might already have known that their gem works with Jekyll 3.x but not with 4.x anymore or they just wanted to revisit the theme later if it still works with Jekyll 4.x but never did.
Changing versions is not really a problem and because of bundler you can do that easily and as often as you want or need to. But there might be a general issue with downgrading a gem. Newer versions are released mainly for two reasons:
to add new features and
to fix bugs and security vulnerabilities.
When you work with an older version of a gem then you might miss new features that might be okay if you do not need them. But you also might open yourself to security vulnerabilities that have already been fixed in later versions.
My advice is:
Try using the latest version of a gem whenever possible.
If another gem depends on an older version and you, therefore, an update to the latest version, then I would ask myself if it is really worth it to use such an outdated gem. When the gem hasn't been updated to depend on the latest version for a longer period of time then it is likely that it will not be updated anymore which is a risk.
If you still want or need to downgrade then I suggest checking the changelog of the gem what features and bug fixes you will miss. And to check the changelog on a regular basis in the future too.
Useful links in this context: The list of Jekyll versions, as you can see Jekyll 3.4 is about five years old that is a lot of time to build new features, fix bugs and security vulnerabilities. And a lot of time for a theme author to make a theme compatible with newer versions. And the Jekyll Changelog in which you can check what you would be missing when you downgrade to 3.4 instead of using the latest version (currently 4.2.1). And that list is very long.
Why should one care about specifying gem version at all if bundler detects Ruby version and manages to get the latest release to match that version. If I'm not a fond of newer version personally, I would disable incrementing with ~> 1.4.4 and in other cases I'd let bundler manage stuff with putting gem name into Gemfile without any argument
The approach you are suggesting - start with the latest version and pin if problems are experienced - works fine for projects that are 1) actively maintained and 2) tolerant of breakage.
Now imagine you have to deliver this project to a customer who then will run it for a year or longer and you won't be there to support it. In this case simply getting the latest release of all dependencies is not necessarily the best strategy. Maybe you would proactively specify major versions of all of your important dependencies instead. Potentially even lock to minor versions which does give more stability at the cost of missing security updates/bug fixes.
Isn't the Gemfile.lock a hack used to perpetuate bad practices in dependency version control?
I.e. Shouldn't developers set the dependency version ranges strictly in the Gemfile?
For example if my Gemfile says that I depend on gem A version 1.0.1 or versions [1.0-2.0), why would I need the .lock?
No, Gemfile.lock makes a lot of sense and is crucial to the concept of automatically picking gem versions. As a developer, you do not need to bother about exact version numbers. You can say "give me whatever version of gem X fits all other versions of all other gems" (by just saying gem 'xyz' without any further information). Or you can tell it to stay within the bugfixing line of an older version of a gem (gem 'xyz', '~> 2.3.0') or whatever.
By adding the exact version in Gemfile.lock you then make sure that the versions stay consistent for all developers (and environments). You make the act of upgrading to a newer version of a gem a conscious (and well-documented) choice instead of a random part of your build/deploy process.
why would I need the .lock?
to install exactly the same versions as all the other guys in the team. Or install in production the same versions that you use in development.
It might happen that a new version of some gem is released while you were collecting sign-offs for your release. You better be sure you install/load exactly the versions that you developed/tested with.
I maintain a gem with dependencies that are stored in a Gemfile, for example:
gem 'foo', '~> 1.5'
gem 'bar', '~> 2.0.5'
Thanks to pessimistic version constraints, bundler will by default install the latest 1.x version of foo, but can compromise on a lower version if my gem is used in conjunction with another that requires (for example) foo =1.6.2
Question: Is there a simple way to get bundler to install all of the minimum versions of my dependencies (in this case, foo =1.5.0 and bar =2.0.5) so that I can test whether, after I write some new functionality, my gem will still work in combination with other environments that use those lower versions?
Or, is the only way for me to manually reinstall all of the minimum versions and then run my tests?
Because we decided to use Rubygems' Requirement class, there isn't a way to specify the lowest version. I vaguely recall an automated testing tool to help you iterate over dependency versions that you want to test against, but it's extremely hard to automate because there are an exponential number of possible version combinations. I suggest creating a second Gemfile with the oldest versions you want to test against, and using BUNDLE_GEMFILE to run against that Gemfile in an additional CI build.
I saw your question in IRC... from my understanding, there's no way to do it without changing your Gemfile. Sorry. :(
https://github.com/carlhuda/bundler/blob/master/lib/bundler/cli.rb for reference
I have an application with many optional components, all with their own complex dependencies. For example, some deployments might want to use LDAP functionality and will need to load ldap-related gems. But many will not, and those that don't should not have to install ldap-related gems.
How can I use Bundler to load these dependencies depending on which components users (deployers) have enabled?
I don't want to to force deployers to manually edit their Gemfiles. It has to be possible to enabled/disable components via the application's UI.
Just including every possible dependency in the Gemfile is not ideal. Some of the rarely used components require a lot of complicated native compilation. Another solution might be to have the application edit its own Gemfile. But this is kind of awkward and would likely require a restart every time components are changed.
Is there a way in Bundler to dynamically load gems in runtime? If not, are there alternatives that provide something like Bundler's sandboxing but allow for dynamic loading?
You could provide multiple Gemfiles and use bundle install --gemfile to use the specific gemfile and only install the Gems you need for that deployment.
In your application you could then use Bundle.setup with the appropriate groups of the previously installed Gemfile to just load the appropriate Gems
Sure thats not a nice and easy way, but should give you the functionality you want.
See
Bundler Setup
bundle install