1 00:00:00,025 --> 00:00:08,661 [SOUND] So in this workshop we're going to be taking a look at Bundler. 2 00:00:08,661 --> 00:00:14,490 Now, Bundler is going to help you manage different dependencies for 3 00:00:14,490 --> 00:00:16,230 your Ruby project. 4 00:00:16,230 --> 00:00:22,500 Now, these dependencies are going to be your Ruby gems, and Ruby gem versions. 5 00:00:22,500 --> 00:00:25,690 If you want to see a little bit more about why Bundler exists, 6 00:00:25,690 --> 00:00:31,110 you can click on the why Bundler exists button over on the Bundler site. 7 00:00:32,130 --> 00:00:36,770 Now you can see Bundler let's you declare all of your application dependencies 8 00:00:36,770 --> 00:00:41,620 in a file at the root of your application, and this is called the gem file. 9 00:00:41,620 --> 00:00:45,610 You need to specify a source where you'll be getting your gems. 10 00:00:45,610 --> 00:00:49,040 More often than not, this is going to be ruby gems, however, 11 00:00:49,040 --> 00:00:53,580 there are services that allow you to define different sources, and 12 00:00:53,580 --> 00:00:56,490 you can even run your own sources. 13 00:00:56,490 --> 00:00:59,840 After that, you specify the different gems and 14 00:00:59,840 --> 00:01:03,880 versions of your application's dependencies. 15 00:01:03,880 --> 00:01:06,140 Now why do we need to do this? 16 00:01:06,140 --> 00:01:11,410 Well, different gems depend on different versions of other gems and 17 00:01:11,410 --> 00:01:14,580 you might have more than one gem installed. 18 00:01:14,580 --> 00:01:17,180 If I go over to my terminal here and 19 00:01:17,180 --> 00:01:22,180 I do gem list, you can see I have a ton of different gems in here. 20 00:01:23,240 --> 00:01:25,770 The gems are stated on the left side here and 21 00:01:25,770 --> 00:01:29,020 then in parentheses you'll see the different versions. 22 00:01:29,020 --> 00:01:34,090 Now depending on the different version of a gem, and it's dependencies, 23 00:01:34,090 --> 00:01:38,190 it can be quite cumbersome to make sure that you have the right one installed and 24 00:01:38,190 --> 00:01:42,200 it's not going to conflict with another project on your system. 25 00:01:42,200 --> 00:01:46,820 For example, you may have a Rails project that 26 00:01:46,820 --> 00:01:51,980 depends on an old version of a Gem and one that depends on a new one. 27 00:01:51,980 --> 00:01:57,660 And there could be a little bit of trouble if you have both installed. 28 00:01:57,660 --> 00:02:02,000 So what Bundler will do is declare your Gem environment 29 00:02:02,000 --> 00:02:05,960 to be separate from the rest of your Gems and 30 00:02:05,960 --> 00:02:10,830 only load the ones inside and specified in the Gemfile. 31 00:02:12,520 --> 00:02:18,560 Now the Gemfile, you'll notice, has these dependencies specified in a certain way. 32 00:02:18,560 --> 00:02:24,140 So we're using the Rails gem and we're using this particular version of it. 33 00:02:24,140 --> 00:02:27,260 Now, the way that these are specified, 34 00:02:27,260 --> 00:02:31,360 is using something called semantic versioning. 35 00:02:31,360 --> 00:02:37,110 Now, semantic versioning, you can find out, at semver.org. 36 00:02:37,110 --> 00:02:39,340 And it's very, very simple. 37 00:02:39,340 --> 00:02:45,460 Each version of something has a major, minor, and patch version. 38 00:02:45,460 --> 00:02:50,740 The major version where you make incompatible API changes. 39 00:02:50,740 --> 00:02:53,870 So let's say you've coded a gem, and 40 00:02:53,870 --> 00:02:57,670 the gem has a certain method that you call quite a bit. 41 00:02:57,670 --> 00:03:02,900 Well, if you were creating a new major version, you can change the method name. 42 00:03:02,900 --> 00:03:04,620 However, in a minor version, 43 00:03:04,620 --> 00:03:09,750 you can only add functionality in a backwards-compatible manner, and 44 00:03:09,750 --> 00:03:14,260 the patch version allows you to make backwards-compatible bug fixes. 45 00:03:14,260 --> 00:03:16,760 So, if there's an error in your gem, 46 00:03:16,760 --> 00:03:20,980 a new release will be specified with a patch that fixes that particular error. 47 00:03:22,860 --> 00:03:26,560 Now the way these are specified in Bundler is as follows. 48 00:03:27,670 --> 00:03:34,890 If you have a particular gem you can do a comma and then specify an exact version. 49 00:03:34,890 --> 00:03:38,060 If an exact version of a gem is specified, 50 00:03:38,060 --> 00:03:40,690 then that is what will be used in the project. 51 00:03:40,690 --> 00:03:46,320 If no version is specified, the latest version available will be used. 52 00:03:46,320 --> 00:03:50,420 Now, this can be any particular version on the system. 53 00:03:50,420 --> 00:03:54,490 If it's not installed it will be fetched from whatever sources are available. 54 00:03:55,810 --> 00:04:01,250 And then finally, there's this little tilde and greater than sign, 55 00:04:01,250 --> 00:04:07,020 which specifies that it's using the same major and minor version. 56 00:04:07,020 --> 00:04:11,728 So a version of nokogiri that's greater than or equal to the 6.1, 57 00:04:11,728 --> 00:04:15,280 but less than 1.7.0. 58 00:04:15,280 --> 00:04:19,416 That means that only those patches can be used. 59 00:04:21,165 --> 00:04:23,595 Once all of the gems are specified, 60 00:04:23,595 --> 00:04:26,920 then you need to run the command bundle install. 61 00:04:28,000 --> 00:04:32,520 And that will install the different versions of the gems. 62 00:04:32,520 --> 00:04:38,090 When you create a new Ruby on Rails project, bundler is run automatically. 63 00:04:38,090 --> 00:04:39,610 So, let's go ahead and do that right now. 64 00:04:39,610 --> 00:04:43,560 I'm going to clear my screen and write rails new bundler_example. 65 00:04:43,560 --> 00:04:49,300 And this will use the latest version of Ruby on Rails on my system, 66 00:04:49,300 --> 00:04:51,820 generate a new Rails application. 67 00:04:51,820 --> 00:04:56,830 And then while it's doing that, you'll see on the bottom here it runs bundle install. 68 00:04:56,830 --> 00:04:58,070 That will go out and 69 00:04:58,070 --> 00:05:03,630 fetch the different versions that are specified by rails in the default gemfile. 70 00:05:04,850 --> 00:05:08,870 So then if we go in there, we can open this up and 71 00:05:08,870 --> 00:05:11,240 see exactly what has been created. 72 00:05:14,660 --> 00:05:21,500 Now if I open up this gem file, we can see how 73 00:05:21,500 --> 00:05:27,160 Bundler has specified everything in here for the default rails gem file. 74 00:05:27,160 --> 00:05:31,865 We're using a rails gem at this particular version, any version of SQL Lite, 75 00:05:31,865 --> 00:05:40,120 any version of SAS Rails that is at least 5.0 or above and less than 5.1. 76 00:05:40,120 --> 00:05:45,074 Now here's a difference in text we haven't seen yet, 77 00:05:45,074 --> 00:05:48,843 which is using a gem that is greater than or 78 00:05:48,843 --> 00:05:53,923 equal to this specific version, which is 1.3.0. 79 00:05:53,923 --> 00:05:58,740 Now this is going to be different when we're using the Tilt syntax in that if 80 00:05:58,740 --> 00:06:05,340 it's greater than 1.3, it can be 1.4, it can be 2.0.0, it could be anything. 81 00:06:05,340 --> 00:06:09,326 And we'll use that particular gem. 82 00:06:09,326 --> 00:06:13,428 Now here jquery-rails, no particular version is specified, so 83 00:06:13,428 --> 00:06:16,880 we'll use the latest one of that as well as Turbolinks. 84 00:06:18,760 --> 00:06:21,330 Now here's something that we haven't seen just yet. 85 00:06:21,330 --> 00:06:26,247 We've got this particular gem sdoc, which is specified as any 86 00:06:26,247 --> 00:06:31,001 version greater than 0.4.0 and less than 0.5.0. 87 00:06:32,580 --> 00:06:37,250 And this is specified with a group key and the group is doc. 88 00:06:38,580 --> 00:06:41,990 Now, different groups can be used in Bundler. 89 00:06:41,990 --> 00:06:45,530 Frequently in a rails application, you'll see groups for 90 00:06:45,530 --> 00:06:50,870 development, test, production and all groups. 91 00:06:50,870 --> 00:06:53,340 There are two different ways that you can specify a group. 92 00:06:54,470 --> 00:07:01,610 You can use this group key in the jam hash command, or if we scroll down, 93 00:07:01,610 --> 00:07:06,880 you can use the group method name and then the different groups that these belong to. 94 00:07:08,170 --> 00:07:13,210 So, in the development and test groups, we'll have these gems available. 95 00:07:14,300 --> 00:07:19,380 If we're in the production group, these gems will not be available. 96 00:07:20,510 --> 00:07:22,490 Now, let's go ahead and see how this works. 97 00:07:22,490 --> 00:07:24,450 I'm gonna clear my screen here. 98 00:07:24,450 --> 00:07:28,560 And if we want to install the gems we run the bundle install command. 99 00:07:29,560 --> 00:07:32,260 That will go out and fetch the gems, 100 00:07:32,260 --> 00:07:37,970 if we don't have any particular versions of them installed on our machine. 101 00:07:37,970 --> 00:07:41,005 Bundle install is a very interesting command. 102 00:07:43,841 --> 00:07:47,339 We can click learn more and see that it supports. 103 00:07:47,339 --> 00:07:48,920 Different options. 104 00:07:48,920 --> 00:07:54,810 We can give it a bin stubs option which will generate different binaries for 105 00:07:54,810 --> 00:07:57,800 the gems specified in your application. 106 00:07:59,480 --> 00:08:02,840 Now here, let's go ahead and see how that looks. 107 00:08:02,840 --> 00:08:08,211 If I added the different gem, and let's go ahead 108 00:08:08,211 --> 00:08:13,610 to Rubygems.org and search for rspec-rails. 109 00:08:13,610 --> 00:08:20,779 You'll see that that version is 3.3.3. 110 00:08:20,779 --> 00:08:24,122 So if I were to specify that in my gem file, 111 00:08:24,122 --> 00:08:28,615 then return to my command prompt and do bundle install, 112 00:08:28,615 --> 00:08:35,022 we'll see that it's fetching the different gem metadata for Rubygems.org, 113 00:08:35,022 --> 00:08:41,160 and now this bundle install is taking a little bit longer than it was before. 114 00:08:42,880 --> 00:08:47,288 And we'll see that it installed different gems. 115 00:08:47,288 --> 00:08:52,612 We installed rspec-rails which depends on these specific gems, 116 00:08:52,612 --> 00:08:55,370 rspec-support, rspec-core, 117 00:08:55,370 --> 00:09:00,330 rspec-expectations, rspec-mocks, and rspec-rails. 118 00:09:00,330 --> 00:09:06,050 We now have different gems installed in our project with these different versions. 119 00:09:06,050 --> 00:09:09,240 So let's talk for a moment about that bin stubs command. 120 00:09:10,420 --> 00:09:14,620 If we wanted to execute something within the context of the bundle, 121 00:09:14,620 --> 00:09:17,250 we would need to use the command bundle exec. 122 00:09:18,350 --> 00:09:21,500 So, if we typed bundle exec rspec, 123 00:09:21,500 --> 00:09:24,160 this is going to fail because I haven't installed it yet. 124 00:09:25,780 --> 00:09:26,740 No examples found. 125 00:09:28,120 --> 00:09:33,980 In fact, what we need to do is say bundle exec rails generate rspec. 126 00:09:36,190 --> 00:09:36,690 Oh. 127 00:09:38,200 --> 00:09:43,100 Let's say bundle rails generate --help to see what installers we have. 128 00:09:44,540 --> 00:09:47,370 Let's just generate an rspec install. 129 00:09:47,370 --> 00:09:47,870 There it is. 130 00:09:54,947 --> 00:09:56,346 Here we go. 131 00:09:56,346 --> 00:09:59,546 Forgot the rails command here. 132 00:10:03,060 --> 00:10:05,900 Okay, these specific files were created. 133 00:10:08,680 --> 00:10:13,436 You'll notice that I have to type bundle exact to get this to execute within 134 00:10:13,436 --> 00:10:17,070 the context of the gem file and in the context of Bundler. 135 00:10:18,160 --> 00:10:21,280 Bundler supports something called bin stubs, which is going to 136 00:10:21,280 --> 00:10:26,360 generate a binary of this, so that I don't have to type bundle exec all the time. 137 00:10:26,360 --> 00:10:31,860 And that can be done by typing bundle binstubs 138 00:10:33,520 --> 00:10:39,370 and the name of the gem, which in this case is rspec-core. 139 00:10:39,370 --> 00:10:42,610 Now, if I look inside of the bin directory, 140 00:10:43,890 --> 00:10:47,420 I have this rspec command that was generated by Bundler. 141 00:10:49,420 --> 00:10:54,400 So now instead of typing bundle exec rspec, 142 00:10:54,400 --> 00:10:58,220 I can type bin/rspec, 143 00:10:58,220 --> 00:11:02,050 and that will run everything within the context of the gem file. 144 00:11:03,740 --> 00:11:08,490 Something else that's neat that we can do is do a bundle install and 145 00:11:08,490 --> 00:11:10,639 tell Bundler the path to use. 146 00:11:11,870 --> 00:11:14,930 Now, if we were deploying an application with Bundler, 147 00:11:14,930 --> 00:11:19,520 it would install with the default tuned for deployment and CI environments. 148 00:11:19,520 --> 00:11:21,200 Well, what exactly does that mean? 149 00:11:22,280 --> 00:11:25,030 Well, if we're doing a deploy of an application, 150 00:11:25,030 --> 00:11:28,377 we wanna have all of its dependencies in our application. 151 00:11:28,377 --> 00:11:31,405 We don't want it going out to RubyGems to fetch them. 152 00:11:31,405 --> 00:11:34,580 They should be available in our application. 153 00:11:34,580 --> 00:11:39,150 So to do that, we can specify a path, and 154 00:11:39,150 --> 00:11:44,580 if we look at this path, we specify a different path than the system default, 155 00:11:44,580 --> 00:11:48,570 which is either $BUNDLE_PATH or $GEM_HOME. 156 00:11:48,570 --> 00:11:55,410 So if I look in the vendor directory, we have assets. 157 00:11:55,410 --> 00:12:01,910 But, if I do bundle install and give it a path of vendor and 158 00:12:01,910 --> 00:12:06,520 bundle, it will go out and install all of these gems if they're 159 00:12:06,520 --> 00:12:10,970 not installed already, just like the regular install command does. 160 00:12:10,970 --> 00:12:16,956 However, this time, they'll be saved to the path of vendor/bundle. 161 00:12:16,956 --> 00:12:20,940 And we'll see all of the different dependencies in this application will be 162 00:12:20,940 --> 00:12:27,190 installed, and you'll notice that there is now a bundle directory, and 163 00:12:27,190 --> 00:12:33,095 this will mimic the ruby gem directory 164 00:12:33,095 --> 00:12:38,780 layout inside of the vendor bundle directory. 165 00:12:38,780 --> 00:12:44,200 So we can see all these different gems are now kept inside of our application. 166 00:12:46,310 --> 00:12:47,820 And this will take a few minutes, 167 00:12:47,820 --> 00:12:52,270 depending on the size of your application, and its dependencies. 168 00:12:52,270 --> 00:12:55,480 Now, you might be wondering how Bundler keeps track 169 00:12:55,480 --> 00:12:57,960 of all of the different dependencies. 170 00:12:57,960 --> 00:13:05,910 Those are placed inside of this file, gemfile.lock. 171 00:13:05,910 --> 00:13:09,820 Now, if we look inside of this gemfile.lock, 172 00:13:09,820 --> 00:13:13,850 we'll see different versions of gems that are installed. 173 00:13:13,850 --> 00:13:21,770 Right here, actionmailer version 4.2.3 depends on these different gems below it, 174 00:13:21,770 --> 00:13:27,890 actionpack, actionview, activejob, mail, rains-dom-testing. 175 00:13:27,890 --> 00:13:29,470 And, using the syntax, 176 00:13:29,470 --> 00:13:36,120 we also see the different versions that are specified in parentheses afterwards. 177 00:13:36,120 --> 00:13:40,350 Now it's going to go through and create this dependency graph for 178 00:13:40,350 --> 00:13:44,420 every gem in our gem file and their dependent gems as well. 179 00:13:46,130 --> 00:13:49,830 By doing this, Bundler will have an overarching view of 180 00:13:49,830 --> 00:13:53,850 everything that's needed in the application. 181 00:13:53,850 --> 00:13:59,790 So we can see turbolinks depends on coffee-rails, any version. 182 00:13:59,790 --> 00:14:01,970 And it will say the platforms, which is ruby. 183 00:14:01,970 --> 00:14:05,300 Now, there are different versions of ruby install available. 184 00:14:05,300 --> 00:14:08,190 It could say something like jruby or 185 00:14:08,190 --> 00:14:11,070 any of the alternate ruby implementations that there are. 186 00:14:12,670 --> 00:14:18,100 For the most part, you will not need to mess with this gemfile.lock. 187 00:14:18,100 --> 00:14:21,410 In fact, you should leave it alone, never touch it, and 188 00:14:21,410 --> 00:14:23,150 just let Bundler manage it for you. 189 00:14:24,630 --> 00:14:30,330 If you ever get into a situation where you have modified the gemfile.lock, 190 00:14:30,330 --> 00:14:32,770 something is probably wrong. 191 00:14:32,770 --> 00:14:35,710 It may be safer to delete your gemfile.lock and 192 00:14:35,710 --> 00:14:38,140 regenerate it by doing bundle install. 193 00:14:40,710 --> 00:14:44,110 So we can see now that all of these gems are installed, 194 00:14:44,110 --> 00:14:47,090 they are now installed into vendor/bundle. 195 00:14:47,090 --> 00:14:52,440 13 Gemfile dependencies, 59 gems installed. 196 00:14:54,580 --> 00:14:59,420 Now should your gems become out of date, one other thing that you can do is update 197 00:14:59,420 --> 00:15:05,010 your gems, so let's say that one of these gems had an update to it. 198 00:15:05,010 --> 00:15:11,370 We can run the bundle update command, and that will go out 199 00:15:11,370 --> 00:15:16,570 and check to see if any new versions of any of the gems are installed. 200 00:15:16,570 --> 00:15:20,100 And then it will fetch them and update the vendor bundle. 201 00:15:22,160 --> 00:15:26,120 Now, as we're watching this, we'll see it's checking the gem metadata. 202 00:15:26,120 --> 00:15:32,580 If something is updated, it will be shown in green rather than the normal dark text. 203 00:15:35,040 --> 00:15:36,611 And we can see that so 204 00:15:36,611 --> 00:15:41,711 far it doesn't look like any updates were needed in this bundle. 205 00:15:44,491 --> 00:15:46,887 Now, when we do the deployment option, 206 00:15:46,887 --> 00:15:51,260 this will automatically be installed into the vendor bundle directory. 207 00:15:53,430 --> 00:15:55,830 And there's pretty much no need to modify that for 208 00:15:55,830 --> 00:15:58,570 deployment unless it depends on the system that you're using. 209 00:15:59,950 --> 00:16:03,220 Now, without is also an interesting command. 210 00:16:04,510 --> 00:16:08,175 We'll see that we have different groups available in this Gemfile. 211 00:16:09,250 --> 00:16:11,560 Here we have the development and test group. 212 00:16:11,560 --> 00:16:16,640 If we used the without keyword, and we can say without the test environment, 213 00:16:16,640 --> 00:16:22,110 any gems that are specified only in the test environment would be installed. 214 00:16:23,860 --> 00:16:29,948 For the most part, what you'll be doing is using bundle install, 215 00:16:29,948 --> 00:16:33,111 bundle update, and bundle exec. 216 00:16:36,012 --> 00:16:39,226 If you wanted to create your own application using Bundler, 217 00:16:39,226 --> 00:16:42,590 you can do that with the bundler.setup command. 218 00:16:42,590 --> 00:16:44,550 And that's very, very easy to use. 219 00:16:48,871 --> 00:16:52,242 So let's go ahead and say we're creating a project. 220 00:16:52,242 --> 00:16:56,177 my_bundler_project. 221 00:16:58,617 --> 00:16:59,918 Clear my screen here. 222 00:17:03,077 --> 00:17:05,790 Close this. 223 00:17:05,790 --> 00:17:08,830 Now, here is my Bundler project. 224 00:17:10,780 --> 00:17:15,855 I'm gonna create a new file and save it as Gemfile. 225 00:17:18,470 --> 00:17:23,490 Now I've got a Gemfile, what I need to do is specify some kind of gem, 226 00:17:23,490 --> 00:17:29,820 we'll just say I'm gonna specify the money gem, and 227 00:17:29,820 --> 00:17:36,230 in order to require it, we can say require rubygems and require bundler/setup, 228 00:17:36,230 --> 00:17:40,930 so, I'll just do a new file and we'll say example.rb. 229 00:17:40,930 --> 00:17:46,441 And if I were going to use the money gem, 230 00:17:46,441 --> 00:17:51,117 let's go ahead and check it out, 231 00:17:51,117 --> 00:17:56,127 ruby money gem, we can just copy and 232 00:17:56,127 --> 00:17:59,139 paste this, run it. 233 00:18:04,999 --> 00:18:09,460 So if I run example.rb, we get this uninitialized constant money. 234 00:18:09,460 --> 00:18:12,861 Well, I haven't done any bundle installs yet, so let me do that. 235 00:18:15,720 --> 00:18:20,868 Now, if I just type bundle, that will automatically try to do a bundle install. 236 00:18:20,868 --> 00:18:25,620 It says uh-oh, your Gemfile has no gem server sources. 237 00:18:25,620 --> 00:18:27,480 If you need gems that are not already installed, 238 00:18:27,480 --> 00:18:31,710 add a line like this to your Gemfile specifying a gem source. 239 00:18:31,710 --> 00:18:36,670 Okay, let me copy and paste rubygems.org into my gem file. 240 00:18:37,940 --> 00:18:38,510 Save that. 241 00:18:40,690 --> 00:18:41,580 Run bundle again. 242 00:18:44,710 --> 00:18:49,020 Now, this is going to install the gem and its dependencies. 243 00:18:49,020 --> 00:18:54,260 So now let me clear my screen and run the example.rb again and watch it fail. 244 00:18:54,260 --> 00:18:59,345 We still get this uninitialized constant Money error, 245 00:18:59,345 --> 00:19:02,046 and if we go back, we can see, 246 00:19:02,046 --> 00:19:07,793 the reason is we need to require rubygems and bundler/setup. 247 00:19:07,793 --> 00:19:09,610 So let's do that and see what happens. 248 00:19:12,770 --> 00:19:14,230 Let's go ahead and print that to the screen. 249 00:19:15,670 --> 00:19:20,760 Now if we run this again, we still get this uninitialized constant Money, and 250 00:19:20,760 --> 00:19:24,120 let's see why, now we can require money. 251 00:19:24,120 --> 00:19:25,880 If only it was that easy in real life, right? 252 00:19:27,420 --> 00:19:29,310 Uninitialized constant Currency. 253 00:19:31,090 --> 00:19:32,520 Let's see why that is. 254 00:19:35,561 --> 00:19:37,001 We're requiring money. 255 00:19:40,821 --> 00:19:43,960 And let's just get currency out of here for now so we can see how this works. 256 00:19:47,241 --> 00:19:49,870 Probably haven't updated their gem documentation. 257 00:19:51,170 --> 00:19:57,160 Okay, now we have access to the Money constant and the Currency constant. 258 00:19:57,160 --> 00:19:59,760 So if we were to specify any other gems in here, 259 00:19:59,760 --> 00:20:04,160 we would need to put them in the Gemfile and then require them. 260 00:20:05,550 --> 00:20:07,780 Now, those are the basics of using Bundler. 261 00:20:07,780 --> 00:20:12,990 If we had different groups, we could call this bundler.setup method and 262 00:20:12,990 --> 00:20:18,410 that would add groups from not just the default group but any group we specify. 263 00:20:20,870 --> 00:20:25,750 So these are the basics, you can read more about Bundler on the Bundler website. 264 00:20:25,750 --> 00:20:27,840 Definitely go through and check it out, 265 00:20:27,840 --> 00:20:31,400 and you can also find some helpful info in the notes below this video.