Pro Yearly is on sale from $80 to $50! »

How Does Bundler Work, Anyway? (RubyConf 2015)

4c3ed917e59156a36212d48155831482?s=47 André Arko
November 17, 2015

How Does Bundler Work, Anyway? (RubyConf 2015)

We all use Bundler at some point, and most of us use it every day. But what does it do, exactly? Why do we have to use bundle exec? What's the point of checking in the Gemfile.lock? Why can't we just gem install the gems we need? Join me for a walk through the reasons that Bundler exists, and a guide to what actually happens when you use it. Finally, we'll cover some Bundler "pro tips" that can improve your workflow when developing on multiple applications at once.

4c3ed917e59156a36212d48155831482?s=128

André Arko

November 17, 2015
Tweet

Transcript

  1. how does bundler work, anyway?

  2. how does bundler work, anyway?

  3. a brief (?) history of dependency management

  4. André Arko @indirect

  5. None
  6. therubyway.io

  7. None
  8. None
  9. let’s share ruby code

  10. Gemfile gem “foo”

  11. Terminal $ bundle install

  12. Terminal $ bundle exec foo

  13. done! pretty cool, right?

  14. but… what just happened?

  15. iiiiit’s History ⚔ Time

  16. 1994 2000 2003 2009 dependency timeline require setup.rb RubyGems Bundler

  17. require it loads the codes

  18. def require(filename) eval File.read(filename) end

  19. i’m sure it’s fine run code twice?

  20. $LOADED_FEATURES = [] def require(filename) if $LOADED_FEATURES.include?(filename) return true end

    eval File.read(filename) $LOADED_FEATURES << filename end
  21. probably fine too only absolute paths?

  22. $LOAD_PATH = [] def require(filename) full_path = $LOAD_PATH.first do |path|

    File.exist?(File.join(path, filename)) end eval File.read(full_path) end
  23. load paths are ⛄ pretty ❄ cool

  24. but now we need… setup.rb

  25. how do setup.rb? ruby setup.rb setup ruby setup.rb config ruby

    setup.rb install
  26. use ruby libraries 1. Find a cool library 2. Download

    the library 3. Untar the library 4. Run `ruby setup.rb all`
  27. no versions no uninstall but it’s fine, I’m sure

  28. maybe a little bit incredibly tedious

  29. what if you could… gem install gem uninstall gem list

    rails
  30. bonus round! gem install rails -v 4.1 gem install rails

    -v 4.2 gem install rails -v 5.0
  31. gem "rack", "1.0" require "rack"

  32. $ rackup _1.2.2_ -p 3000

  33. so many gems! 100,000 gems 1,000,000 versions

  34. but gem apps don’t play well with others

  35. welcome to the team here’s your machine we expect setting

    up to take a week
  36. # config/application.rb […] config.gem “rack” config.gem “rails” config.gem “what?” […]

  37. “why is this broken in production?” “dunno, it works on

    every developer machine” 3 days of debugging later… “oh, look, one production server has frobnitz 1.1.3, but the others have 1.1.4” “welp. that explains those exceptions ”
  38. version conflicts gem install rails rails s cd ../other-project rails

    s
  39. activation errors how common can they be, really?

  40. $ rails s Gem::LoadError: can't activate rack (~> 1.0.0., runtime)

    for ["actionpack-2.3.5"], already activated rack-1.1.0 for ["thin-1.2.7"] activation errors
  41. the moral runtime resolution install-time resolution

  42. wait… how do we resolve at install-time?

  43. None
  44. addressable (2.3.7) arel (6.0.0) bcrypt (3.1.10) binding_of_caller (0.7.2) debug_inspector (>=

    0.0.1) builder (3.2.2) byebug (3.5.1) columnize (~> 0.8) debugger-linecache (~> 1.2) slop (~> 3.6) celluloid (0.16.0) Gemfile.lock
  45. bundle install my old friend 1. Read the Gemfile (and

    lock, if it's there) 2. Ask RubyGems.org for a list of every gem we need 2. Find gems allowed by the Gemfile that work together 3. Write down those versions in the lock for future installs 4. Install gems until every locked gem is installed
  46. bundle exec everyone’s nemesis 1. Read the Gemfile (and lock,

    if it's there) 2a. Use locked gems if possible OR 2b. Find versions that work to put in the lock 3. Remove any existing gems the $LOAD_PATH 4. Add each gem in the lock to the $LOAD_PATH
  47. pro tip no more bundle exec! $ bundle binstubs rspec-core

    $ bin/rspec repeat as needed for other gems
  48. was that the end? in a word, no.

  49. I want YOU to contribute 3 @bundlerio team@bundler.io

  50. or if you’re too busy, fund this work. http://rubytogether.org/join