Gems, MVC, Rails, Ruby, RVM

After the Install: Scenario-Based RVM Best Practices

In my previous post, Ruby Version Manager (RVM) Overview for Rails Newbs, I outline RVM’s architecture and fundamental features. That post is also very focused on RVMs role when running rails new.

BeforeAfterToday, I’d like to cover a few more common scenarios Rails developers will encounter after the initial install of RVM. More to the point though, we’ll be focused on how RVM can be used to optimize workflow in these scenarios.

1.  USE A DISTINCT GEMSET FOR EACH PROJECT
In my own development journey, it wasn’t initially clear to me when I should be creating new gemsets. If you too have pondered this question, here’s my suggested answer…create a new gemset for every project you are working on. This approach is not only clean and orderly but more importantly reduces the chance that gem dependency errors sidetrack your work.

As a refresher, here’s the necessary commands to create and use a new gemset:

$ rvm gemset create new_gemset_name

$ rvm gemset use new_gemset_name

Hopefully you’re starting to get some clarity on the use-cases for global, default, and custom gemsets. Basically, global and default are largely used to influence what you get from rails new. Custom gemsets are then used to manage all gems related to a project from that point forward.

RVM_architecture

2.  AUTOMATICALLY CHANGE RUBY VERSION AND RUBY GEMSETS WHEN MOVING BETWEEN PROJECTS
Like all devs, I’ve got lots of active projects in various stages on maturity on my machine.  Before I came across this little nugget of knowledge (just keep reading!), I was frequently running:

$ rvm use ruby_version_here

and then

$ rvm gemset use gemset_name_here

It worked pretty well, but when moving between projects in my command line I often got gem-related errors when trying to run rails s or rails c. The problem was that if I forgot to tell RVM to change gemsets when I moved across projects in my command line, the gems that project expected to be available weren’t there.

Before I get to the solution here, humor me with a quick aside…

In a previous life, I was an Excel junky. I really loved Excel and what it could do. Just like development, it offers an incredible combination of logic and creativity. Also like development, the mouse is not necessarily your friend. Learning to do things without leaving the keyboard can be a HUGE time saver. People who were more mouse-dependent would sometimes look over my shoulder as I worked and say, “dude, you need to teach a class on Excel!”. It was a nice compliment and while I was interested in sharing both my love of Excel as well as its features, I would often respond with,

“if you are ever working in Excel and thinking ‘there has to be a better way to do this’. There is. You just need to figure it out.”

The point is that even though I espoused awareness of this phenomena in the context of Excel, I lamely continued with my error-prone use of RVM for some weeks. It wasn’t until my good friend @megharastogi noticed what I was doing and said, “why don’t you use an .rvmrc file?”.

Eureka! An .rvmrc file sits at the root level of your application and basically tells RVM which Ruby version and gemset to use. RVM is smart and interprets these files as you navigate project folders in the command line.

Below is an actual .rvmrc file in one of my apps. It’s stored at your_project_name/.rvmrc or in the below case social-playlist/.rvmrc.

Screen Shot 2013-08-26 at 8.15.50 AM

Your .rvmrc file should be in the same location as your .gitignore, Gemfile, and README.

Boom! No more gem-related errors. Time saved. Happy dev.

3.  CREATE AND USE A NEW GEMSET WHEN RUNNING GIT CLONE
If you haven’t yet, at some point you’ll clone an existing repo. After doing so, likely your first task is to ensure you can get the app running locally in your development environment. For a Rails app, having the required gems present locally is a critical step in the process.

While you’ve cloned the repo, the repo likely doesn’t contain the actual gems. It merely contains a statement of what gems are necessary, via the Gemfile.

Here’s my recommended order of operations:

1. Review the repo’s README file.

2.  Check the Gemfile of the target repo to see if a Ruby version and or gemset name is explicitly stated. (If it’s a Rails app, a Rails version will surely be stated).

3. Check the target repo for a .rvmrc file at project_directory/.rvmrc. If yes, this often also tell you which version of Ruby as well as the gemset name being used.

NOTE:  As per the Typical RVM Project Workflow, other potential locations where Ruby version and/or gemset dependencies may be stated include files named: .versions.conf, .ruby-version.

4. If a Ruby version is explicitly stated, ensure that Ruby version is installed locally on your machine with $ rvm list

a. If that version is already installed locally on your machine, make it active with $ rvm use ruby_version_here and go to step 5.
b. If that version is not installed locally on your machine, get it with $ rvm install ruby_version_name                                       c. If no version of Ruby is explicity stated, I recommend using the latest stable version.
d. Make the target version of Ruby active with  make it active with $ rvm use ruby_version_here

5. Run $ git clone target_repo_location_here

      • Example:  $ git clone git@github.com:lostincode/social-playlist.git or
      • Example:  $ git clone https://github.com/lostincode/social-playlist.git

Note: Both of the above commands clone the same repo, they just use different security protocols. For the truly adventurous reader, here’s a deep dive on the hows and whys of each protocol.

6. $ cd newly_created_directory_name

7. $ rvm gemset create new_gemset_name

Note: If the repo already contained a .rvmrc file with a gemset name, consider naming your local gemset the same as what’s being used by the other dev(s) pushing to the repo.

8. $ rvm gemset use new_gemset_name

9. $ bundle install

If no .rvmrc file is already present in the app, create one! It’s up to you if you include the .rvmrc in the .gitignore (I strongly suggest you do not! This as an important file for ensuring consistency across collaborators).

While not RVM specific, for good measure I’ll also offer up the other following steps to get the newly cloned app running locally.

10. $ rake db:create

11. $ rake db:migrate

12. $ rake db:seed (optional – only run if seeds.rb contains seed data).

Unless there’s database or server specific requirements, that should suffice to get the app running locally with rails s.

Looping back to the big picture before closing out on this topic. Now we have a distinct gemset just for this project (meeting the objectives of best practice #1) – and automated instructions for RVM to use this gemset whenever this project is active (meeting the objectives of best practice #2) in the command line. And we can be confident we are mirroring the Ruby and Ruby gem configuration of the other devs on the project.

4.  CREATE A “RAILS 4 SCAFFOLD APP” FOR QUICK REFERENCE
In my other post, Reading Rails 4: MVC and Scaffolding for Rails Newbs, I go deep on some of the code generated when running rails generate scaffold.

My original title and concept for the post was not Rails-version specific. I thought it would mostly be about MVC and scaffolding – but be agnostic of Rails version. However, by reviewing the output of rails new and rails scaffold (while having RVM use Rails 4), I quickly and easily learned a lot about Rails 4 versus the Rails 3 versions I was more familiar with.

The point here is that RVM (combined with rails generators), is your assistant in having multiple boilerplate/clean versions of working Rails apps side-by-side on your machine. This makes it easy to access, evaluate, compare, and understand fundamental changes in Rails versions. Personally, I found reviewing the output of a Rails 4 scaffold more educational on mass-assignment in Rails 4 than any online documentation.

If helpful, here’s specifically what I’m suggesting. Say you’ve been hesitating getting onto the Rails 4 bandwagon because you are up and running and proficient in Rails 3. Maybe you feel too busy right now to slow down and learn the “gotchas” in Rails 4. Well, I think 5 minutes spent on the following will probably get you past that hurdle

  1. Create a new gemset called “rails4scaffold” with $ rvm gemset create rails4scaffold
  2. Make the new gemset active with $ rvm gemset use rails4scaffold
  3. Install Rails 4 in that gemset by running $ gem install rails 4
  4. Create a new app by running $ rails new rails4scaffoldapp
  5. Scaffold a basic MVC in that app with rails generate scaffold books title author
  6. Run rake db:migrate
  7. Now go inspect key files like app/controllers/books_controller.rb and run $ rake routes to see how Rails 4 handles basic CRUD.

If you haven’t yet, consider moving Rails 4 into your default gemset!

SUMMARY
As always, I really appreciate you reading my post. I hope it’s been useful for you in getting more value out of RVM. Your comments and feedback are welcomed.

One other quick point is that there are other tools and approaches for doing what RVM does (quite well in my opinion). However my goal is not to promote RVM, but to promote knowledgeable, confident, and satisfying development experiences. As such, I want to share a post titled “Vendor Everything” Still Applies by Ryan McGreary. In it, he makes some interesting and compelling arguments for an alternative approach to gemsets and gem management.

I’m personally still using RVM, but that doesn’t mean I will forever.

Truth fears no questions.
-Napoleon Bonaparte

Reading between the lines of Mr McGreary’s post as well as some of the comments, I think the main point is that consistency in approach to gemset management within a collaborating group is critical to developer happiness and productivity.

Here’s some of my other posts you might like:

Peace.

Rails, Ruby, RVM

Ruby Version Manager (RVM) Overview for Rails Newbs

RVM Overview and Installationbabydev

In someone’s first few hours as a Ruby on Rails developer, they will likely be encouraged to install Ruby Version Manager (commonly known as RVM). RVM is a free, powerful tool for creating and easily moving between Ruby and Ruby Gem combinations.

It’s important for the newb to understand that you want to get RVM configured correctly before running rails new. It’s your RVM settings that will control just what kind of Ruby on Rails app gets generated. Confused? No problem, just keep reading.

As per the RVM installation instructions, by simply entering the below short statement into your command line, you can begin unlocking the power of Ruby and Rails!

$ \curl -L https://get.rvm.io | bash -s stable --rails

Let’s talk about what this is doing. Besides installing the RVM tool itself, this command will also install the newest, stable version of both Ruby and Rails.

That’s great right? The newest, stable version is probably what any new Rails dev wants to be running right? Probably. Let me explain about why I hesitate.

Rails Is a Moving Target

As Rails issues are continuously being found and resolved, the open source code changes over time. The Rails 3.2.13 gem (yes, Rails is just a gem) was released in March 2013 and the Rails 4.0.0 gem released 3 months later in June 2013.

As Rails evolves, syntax that worked in a previous version may no longer work in a newer version. For this reason, the Rails Guide’s own guidance states:

“Before attempting to upgrade an existing application, you should be sure you have a good reason to upgrade.”

The main point for the newb is that pro-actively understanding and choosing which version of Rails they will use to build any app is an important decision.

Note: The syntax retirement described above is specific to Rails (not Ruby).  As such, it’s unlikely a newb will have a reason to run an older version of Ruby. However, it is plausible a newb may have reason to run an older version of Rails (as explained below).

Explain It To Me Like I’m 3 Years Old

In addition to RVM, another common ingredient in a new Rails developer’s kitchen will be one of the great tutorials like Ruby on Rails Tutorial (Hartl) or Rails in Action (Biggs, Katz). These cookbooks have multiple editions as they are generally refreshed when Rails is refreshed. If a newb is using a tutorial predicated on a different (possibly earlier) version of Rails than what RVM has installed by default, headaches will ensue.

One more probable Rails newb scenario is installing a newer version of either Ruby or Rails when one is released after RVM was originally installed.  Both of these scenarios will be addressed below.

This Sounds Like It Could Be Me. How Do I Avoid Headaches?

It really quite easy, and in fact this is what RVM was built to do! But before we dive into more command line stuff, let’s revisit the following statement,

“RVM is a free, powerful tool for creating and easily moving between Ruby and Ruby Gem combinations.”

26FALDIYou can think of RVM as your food pantry for Ruby and Ruby Gems. Maybe you’re feeling old school and want a little Ruby 2.0.0 with a dash of Rails 3.2.13. Or maybe you’re feeling modern and want to run Ruby 2.0.0 with a sprinkle of Rails 4.0.0.   No matter the combination, RVM can have these ingredients ready to grab off the shelf and even mix together with a few simple keystrokes before you run rails new.

Filling Your Pantry with Rubies

Note: It’s unlikely a newb will have a reason to run an older version of Ruby. However, the following instructions are provided for completeness and apply for newbs wanting to install a newer version of Ruby (if one has been released since the original RVM install).

So you’ve got the defaults RVM gave you, but let’s put some other flavors of Ruby into our pantry. Getting additional versions of Ruby is easy enough. Simply drop the below into your terminal.

$ rvm install ruby_version_here

Here’s an example:

$ rvm install 1.9.3

Depending on your needs, feel free to change “1.9.3” for any other (possibly newer) version of Ruby desired. For a list of all available versions, run:

$ rvm list known

Now to see all locally installed versions of Ruby on your machine go ahead and run:

$ rvm list

This returns a nice list of Ruby versions on your machine – as well as indicators of the “default” version and the “current” version.

If you want to change your current version (which you might want to do before running rails new, you can simply enter:

$ rvm use full_ruby_version_name

Here’s an example:

$ rvm use ruby-1.9.3-p392

Note: It’s unlikely a newb will have a reason to run an older version of Ruby. However, a newb may decide to run a newer version of Ruby should one be released after the newb’s original RVM installation.

Navigating and Naming Gemsets in RVM

Okay, so we’ve got multiple Ruby versions that we can quickly move between. But what about Rails? As already stated, Rails is a gem and RVM stores gems in groups – called “gemsets”.

Gemsets in RVM are isolated in that they are only available to a single version of Ruby (this is a common area of confusion for newbs).  When a version of Ruby is installed via RVM, 2 associated (empty) gemsets will be created simultaneously. One is called “global” and one is called “default”.

Global Gemset: Any gems installed into the “global” gemset will be included whenever rails new is run while the associated version of Ruby is active or in use.

Default or User Generated Gemsets: Gems installed into “default” (or a user created gemset), will only be included when rails new is run if that gemset is active or in use.

For example, if you want to be able to run Rails 3.2.13 and Rails 4.0.0 with Ruby 2.0.0, you’ll need 2 separate gemsets and you’ll need to install a different version of Rails into each one.

To bring these points home, possibly a visual will help. Here it is.

RVM_architecture


icon@58Note! I recently released an iPhone app and would appreciate it if you would give it a try. It’s free and called smoov. smoov is a text messaging assistant for gents.

You can download it here or search for it by name in the App Store.


Similar to seeing all locally available Ruby versions, we can see all locally available gemsets (associated with the currently active version of Ruby) via the below command.

$ rvm gemset list

Moving on, to see all gems in the current gemset, just run:

$ gem list

If you want to see what gems are inside of a different gemset, simply move to that gemset with:

$ rvm gemset use gemset_name

For example:

$ rvm gemset use default

or

$ rvm gemset use global

and then,

$ gem list

Great, so we’ve got multiple versions of Ruby, multiple gemsets, and understand the gems inside those gem sets.

A Note About Gemset Naming:

A common area of confusion for newbs with multliple versions of Ruby is that they have multiple gemsets named “global” and “default”.  $ rvm gemset list will return the “global”, “default”, and any other gemsets subordinate to that specific Ruby instance.  If the newb changes their active Ruby version with $ rvm use full_ruby_version_name and then reruns $ rvm gemset list, they will again see “global” and “default” gemsets, but these are not the same gemsets seen just moments earlier.

Due to this approach by RVM, I suggest including the Ruby version number when creating new gemsets.  For example:  rvm gemset create ruby2rails3 or rvm gemset create ruby2rails4.

Filling Your Pantry with Ruby Gems

So we know what we have for existing gemsets and their included gems, what if we want to create a new gemset? No problem, first just make sure you are “using” the version of Ruby that you want the gemset to be associated with. We already learned how to navigate between Ruby versions with:

$ rvm use full_ruby_version_name

Here’s an example:

$ rvm use ruby-2.0.0-p0

Now just tell RVM to create a new gemset and what to name it, using:

$ rvm gemset create my_new_gemset

Here’s two examples:

$ gem gemset create ruby2rails3 or $ gem gemset create ruby2rails4

Next, we need to “use” the newly created gemset by running:

$ rvm gemset use my_new_gemset

or in our example

$ rvm gemset use ruby2rails3

Once we are “using” or inside the target gemset, we can begin installing gems to our hearts content with:

$ gem install gem_name

Here’s an example:

$ gem install rails -v 3.2.13

Finally, to see a complete list of all Rails releases, go to RubyGems.org. Another quick way to get educated on great gems, is to check out Easy Does IT: Top 10 Gems for Rails Newbs.

Changing Default Settings

defaultsAs stated earlier, RVM is going to set your initial Ruby and Gemset defaults to the latest, stable version of Ruby and Rails. If you woud like to change these default settings you can do so with:

$ rvm use ruby_version@gemset_name --default

Here’s an example:

$ rvm use ruby-2.0.0-p0@ruby2rails3 --default

Summary

All if this information is shared so a new Rails developer can consider and have confidence in  knowing what version of Rails they want to be use when running the rails new command.

Conceptually, the newb should now be able to easily:

  • See all locally install versions of Ruby with: $ rvm list
  • Move between locally installed versions of Ruby with: $ rvm use ruby_version_here
  • Install additional versions of Ruby with: $ rvm install ruby_version_here
  • See all locally existing gemsets for a specific version of Ruby with: $ rvm gemset list
  • Move between gemsets with: $ rvm gemset use gemset_name_here
  • Create new gemsets with: $ rvm gemset create my_new_gemset
  • Install new gems in the current gemset with: $ gem install gem_name_here
  • Change their default Ruby and Gemset with: $ rvm use ruby_version@gemset_name --default

newbFull disclosure:  This was the first blog post I’ve written as a Rails dev.  In short, I’m a newb too.

If you’ve found this post useful, consider reading my other newb-centric posts:

I welcome your comments and feedback.