While you are developing on your machine, your application might be running smoothly. Your application relies on multiple libraries/Ruby gems already installed on your machine. While everything might work now, the same gems probably won't be available on the server you will deploy to. If you work with other developers, they might be missing dependencies or have different versions. You might also start a new project and use install a newer version of some libraries which might create some conflicts in your old app.
To avoid all these issues, it is recommended that you bundle/freeze your application dependencies.
To bundle dependencies you need two things:
If you are using an older version of Merb, you might want to remove existing merb.thor files and regenerate a newer version:
$ rm -rf tasks/merb.thor $ merb-gen thor
Make sure you have a dependencies.rb file in your /config folder or create a new one.
Here is an example of a default Merb stack generated dependencies.rb file.
# dependencies are generated using a strict version, don't forget to edit the dependency versions when upgrading. merb_gems_version = "1.0.7.1" dm_gems_version = "0.9.10.1" # For more information about each component, please read http://wiki.merbivore.com/faqs/merb_components dependency "merb-action-args", merb_gems_version dependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_version dependency "merb-auth-more", merb_gems_version dependency "merb-auth-slice-password", merb_gems_version dependency "merb-param-protection", merb_gems_version dependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version dependency "merb_datamapper", merb_gems_version dependency "do_sqlite3" # If using another database, replace this
Usually this file is required by your config/init.rb.
To bundle all the dependencies listed in your dependencies file, run the following command on your development machine.
thor merb:gem:install
Make sure your local ./gems directory and ./gems/cache are added to your SCM (git for instance). You should also ignore ./gems/gems and ./gems/specifications.
Every time, you change the dependencies required, don't forget to rerun the command mentioned above.
The reason for doing that is that native gems need to be recompiled on your deployment platform architecture or you coworker machine.
Next time someone will install the application or you deploy it, just run the following command:
bin/thor merb:gem:redeploy
This command will install gems that are in the cache but not available locally yet.
If you're using a deployment solution like Capistrano or Vlad, you can add this step right after the code has been checked out from your SCM.
Carl Lerche and Yehuda Katz did a screencast of this feature: Merb Dependencies and Bundler: Conquered!
You can find more information on using thor in Using the Thor tasks.
If you have GEM_HOME/GEM_PATH set, their gem locations will trump the bundled gems. For example:
$ ./bin/merb Loading init file from /var/www/ts2/releases/20081119052353/config/init.rb Loading /var/www/ts2/releases/20081119052353/config/environments/development.rb ~ Loaded DEVELOPMENT Environment... ~ ~ FATAL: The file merb-helpers was not found
To fix, just clear GEM_HOME/GEM_PATH:
$ export GEM_HOME= $ export GEM_PATH=
Let's imagine you want to bundle a gem but don't want to load it in your main app. That's often the case when you want bundle gems only used to test your app. The trick is to add them to your dependencies.rb file but not require them:
# bundle but don't load dependency 'david-merb_cucumber', :require_as => nil dependency 'nokogiri', '1.0.5', :require_as => nil