How to install and use RVM

RVM is a critical part of your Ruby on Rails development stack. Why? Because it allows you to work in multiple Ruby environments. As soon as you build out more than one project you could find yourself having to deal with one project at a certain version of Ruby and another project at a different version. Without a tool like RVM. This can be a huge headache. Fortunately, installing RVM is pretty easy.

So let’s start on a bare OS X system. You’ll notice you have Ruby installed already by running the following command in the OS X Terminal App (all the commands in this post should be run in Terminal):

ruby -v

Outputs:

ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14]

At the time of this post, the Ruby on my OS X 10.10 Yosemite was 2.0.0 patch level 481.

What you should be comfortable determining is whether or not you are seeing the OS X version of Ruby or the RVM version (the one you want).

So lets see the path to the ruby executable:

which ruby

Outputs:

/usr/bin/ruby

The output /usr/bin/ruby tells you that you are referencing the built in OS X ruby. Let’s fix that.

Here’s how you install RVM:

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

This could take some time to finish. When it does, run the previous command again to check your ruby executable path. It should read:

/Users/your-username/.rvm/rubies/ruby-2.1.3/bin/ruby

See that .rvm in the path? That means RVM is installed and being properly referenced!

The –ruby flag in the previous command installed the latest version of ruby. You can see that it has changed by checking for the version again:

ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-darwin14.0]

Again, based on when you read this post and run these commands, your versions may be different.

Here are some default commands to get you started with RVM:

rvm list

This will show you the ruby executables (also called rubies) installed on your machine.

rvm list known

This will show you the rubies you can install

rvm install [insert ruby version number]

This will install a specific version of ruby to your machine

rvm install 2.0.0

rvm use [insert ruby version number] –default

This will make sure that a specific version of ruby is used every time you open a terminal window

rvm use 2.0.0 --default

rvm gemset list

This will list all the gemsets for your current ruby version

rvm gemset create [insert gemset name]

This will create a gemset in your current ruby version

rvm gemset create my-gemset

rvm use [insert ruby version number @ gemset name] –default

This will make sure a specific version of ruby is loaded every time AND at a specific gemset

rvm use 2.0.0@my-gemset

Now. What do you need to do in order to get started with Rails? Well, to be honest, there is some discussion as to whether or not gemsets are even required with Bundler. Obviously they are more important if you are developing a Ruby project without Bundler. So, for me, I find setting a ruby version is all I need.

Using RVM you have the ability to manage different ruby versions, what gems are included with each one and you’re not cluttering up the built in ruby with all your various project gems.

Using select, reject, collect, inject and detect.

I spend a lot of time convincing my friends to switch to a Mac. Some of my friends are also software developers so naturally, just when they think the evangelism has come to an end, I convince them to get on the Rails. However, learning Rails usually means learning Ruby for the first time as well. In this post I am going to address one of the issues I see for newcomers to Ruby. Looping.

Looping in Ruby seems to be a process of evolution for newcomers to the language. Newcomers will always find their way to the for loop almost immediately and when confronted with iterating an array, the first choice will generally be a for..in:

a = [1,2,3,4]
for n in a
  puts n
end

This works, but its not very… Ruby. The next stage of evolution will be using an iterator for the first time. So the for loop gets dropped all together and each is used. The Rubyist is born at this point:

a.each do |n|
  puts n
end

What I see next is a lot of conditional logic being used inside the each block. The logic is generally introduced to perform the following operations:

  1. Building a list of items from an array.
  2. Total the items in an array.
  3. Find an item in the array.

So if this is you, then stop. Ruby has plenty more iterators where each came from. Which one you should be using depends on what operation you are trying to perform. So let’s take a look at our previous list and see if we can find a more Ruby way to get them done.

Building a list of items from the array using select

For this operation you should be using select. The way select works is simple, it basically iterates through all the elements in your array and performs your logic on each one. If the logic returns TRUE, then it adds the item to a new array which it returns when the iteration is complete. Here’s an example:

a = [1,2,3,4]
a.select {|n| n > 2}

This will return the last two elements in the array: 3 and 4. Why? Because 3 and 4 are both greater than 2, which was the logic we placed in the block. It’s worth noting that select has an evil step sister named reject. This will perform the opposite operation of select. Logic which returns FALSE adds the item to the array that is returned. Here’s the same examples as before except we will swap select, with reject:

a = [1,2,3,4]
a.reject {|n| n > 2}

In this example the return value is [1,2] because these elements return false when the condition is tested.

I also have to mention another close sibling to select and reject; collect, which returns an array of values that are the RESULT of logic in the block. Previously we returned the item based on the result of the CONDITION in the block. So perhaps we need square the values in our array:

a = [1,2,3,4]
a.collect {|n| n*n}

This returns a new array with each item in our array squared.

Finally, note that using select, reject, and collect returns an array. If you want to return something different, because you are concatenating or totaling values, then check out inject.

Total the items in an array using inject

When you think of accumulating, concatenating, or totaling values in an array, then think of inject. The main difference between select and inject is that inject gives you another variable for use in the block. This variable, referred to as the accumulator, is used to store the running total or concatenation of each iteration. The value added to the accumulator is the result of the logic you place in the block. At the end of each iteration, whatever that value is, can be added to the accumulator. For example, let’s sum all the numbers together in our array:

a = [1,2,3,4]
a.inject {|acc,n| acc + n}

This will return 10. The total value of all the elements in our array. The logic in our block is simple: add the current element to the accumulator. Remember, you must do something to the accumulator in each iteration. If we had simply placed n in the block the final value of the accumulator would have been 4. Why? Because its the last value in the array and since we did not add it to the accumulator explicitly the accumulator would be replaced in each iteration.

You can also use a parameter with the inject call to determine what the default value for the accumulator is:

a = [1,2,3,4]
a.inject(10) {|acc,n| acc + n}

In this example the result is 20 because we assigned the accumulator an initial value of 10.

If you need to return a string or an array from inject, then you will need to treat the accumulator variable that way. You can use the default value parameter of inject to do this:

a = [1,2,3,4]
a.inject([]) {|acc,n| acc << n+n}

In this example I add n to itself and then append it to the accumulator variable. I initialized the accumulator as an empty array using the default value parameter.

Find an item in the array using detect

Our last example operation was to find an element in the array. Let’s just put it out there and say that other iterators could be used to select the correct value from the array, but I am going to show you how to use detect to round out our exploration of these iterators.

So let’s find the value 3 in our array using detect:

a = [1,2,3,4]
a.detect {|n| n == 3}

This returns 3. The value we were looking for. If the value had not been found, then the iterator returns nil.

So if your head is spinning at this point as to which iterator to use for when, then remember this:

  1. Use select or reject if you need to select or reject items based on a condition.
  2. Use collect if you need to build an array of the results from logic in the block.
  3. Use inject if you need to accumulate, total, or concatenate array values together.
  4. Use detect if you need to find an item in an array.

By using these iterators you will be one step closer to mastering… Ruby-Fu.

Take it to the next level with the Ruby on Rails console

If you are not using the Rails console while your developing then now is the time to start! I learn best by example, so that’s how I am going to structure this.

Here’s the scenario:

You are writing code against a class and need to determine which attributes you have available to you. In Rails, your attributes are largely driven by the database schema, so you will not see them in the class definition. At this point most developers will take a look at the table in the database and find the column they need, then determine the type of data stored there. There is a better way…

Let’s use the command line.

We start by firing up our Rails application in console mode:
You must be in your Rails application directory to issue this command.

1
script/console

So now what? Well now you have command line access to your entire Rails application! For example, let’s say you have a class named Person (which would map to a people table in the database). You want a new instance of this class? Then issue the following:

1
p = Person.new

Perhaps you want to view a Person from the database:

1
p = Person.find(1)

By default the results are displayed below each command and they are not very friendly, so let’s output them in YAML as it will be much more readable:

1
y p

‘y’ is like calling ‘puts p.to_yaml’ on the resulting value that follows it. There is also a ‘p’ shortcut that is the equivalent of issuing ‘puts’ on the value.

So how does this help with determining attributes? At first glance you may think you have to look at the list of values returned in your YAML command and find what your looking for… no… it gets better. Remember that all Ruby objects inherit certain methods, watch this:

You want to get the methods associated with your object:

1
y p.methods

You can also get the private, public, and protected methods using the following commands:

1
2
3
y p.public_methods
y p.private_methods
y p.protected_methods

So this class could return a huge YAML result which may not seem as efficient as scanning the schema in the database, and you’re right. So let’s get to what we are really looking for using ‘grep':

1
y p.methods.grep /method_name/

This will return any method which contains method_name. You can write pass any regular expression you like into this command and really drill into your class methods, and for help putting those regular expressions together I really like using Rubular a web-based Ruby regular expression editor.

And what about the type of an object?

1
y p.class

This is just a taste of what you can do with the console… I use the console everyday as I develop. I will post some more console tips in future posts!

Running Ruby on Rails with Mongrel Clustering and Apache Proxy

Being a Rails coder is easy, deploying a Rails application can be hard. Through a great deal of effort, we’ll call it blood, sweat and tears, I have put together the following guidance on how to get your Ruby on Rails application up and running behind a Mongrel cluster using Apache Proxy.

Here’s the deal, I am going to install all the necessary applications to get this up and running, so if you have some of these installed on your server already you may just skip ahead, however, if you have any issues with this you may want to read over those sections you skipped and understand why I installed a specific version or what pitfalls I encountered that may be affecting your setup. Also, I am running Ubuntu, so if you are running a different distribution, then the paths to specific configuration files on your system may be different. Let’s get started!

Installing MySQL

Install MySQL using the package manager in Ubuntu:

1
sudo apt-get install mysql-server

After the installation you should be able to run the command mysql or mysqladmin. If you cannot run these then you may have to create symbolic links to these commands or add them to your path.

By default, MySQL only listens on localhost, in order to change that you need to comment out the line which reads: bind-address = 127.0.0.1

Change this by editing the following file on your system:

1
sudo vi /etc/mysql/my.cnf

You can search for text in vi using a forward slash.

You should restart MySQL after making a change to the config file:

1
/etc/init.d/mysql restart

Now verify that MySQL is listening to the network. The output of the following command should show an entry for MySQL:

1
netstat -tap

You need to set a password for the root account of MySQL, otherwise anyone can access it!

1
2
mysqladmin -u root password your_password
mysqladmin -h server_name -u root password your_password

In case it is not clear, your_password should be replaced with a strong password of your choosing.

Installing Ruby

1
apt-get install ruby ri irb

Install Ruby Gems

1
2
3
4
5
cd /tmp
wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
tar -zxvf rubygems-0.9.2.tgz
cd /rubygems-0.9.2.tgz
ruby setup.rb

Update rubygems

1
2
3
gem update --system
gem update
gem cleanup

Why the two calls to gem update? –system will update the RubyGems itself and without that parameter you will only be updating the gems.

Install Rails

Install Rails using Rubygems:

1
gem install rails

Now let’s test the rails installation:

1
2
3
rails /tmp/railstest
cd /tmp/railstest
./script/server

This will start the default WeBrick web server, so open a web browser to http://localhost:3000 If all is well you will see the Ruby on Rails welcome screen. Once you are finished staring at your success, press CTRL + d to kill the web server.

Install Mongrel

Install the build tools:

1
apt-get install build-essential ruby1.8-dev

Install Mongrel:

1
gem install mongrel mongrel_cluster --include-dependencies

Now let’s test the Mongrel installation:

1
2
cd /tmp/railstest
mongrel_rails start

This will start the Mongrel web server (now default), so open a web browser to http://localhost:3000 If all is well you will see the Ruby on Rails welcome screen… again. Now kill the web server.

Configure Mongrel Rails cluster

Add a user for our mongrel cluster:

1
useradd mongrel

Add the group for our mongrel user:

1
groupadd mongrel

Configure the directory security for your application:

1
chown -R mongrel:mongrel /tmp/railstest

Now we need to configure the Rails cluster for the test application. This command will write a YAML file to the config directory in your Rails application so you will only have to enter all these parameters once. After that, simply firing the command mongrel_rails cluster::start will use this configuration:

1
2
3
cd /tmp/railstest
mongrel_rails cluster::configure -e production 
-p 8000 -N 8 --user mongrel --group mongrel

You can reconfigure by running this command and using different parameters, you can also safely delete the YAML file from your config directory to blow these settings away.

Time to start the cluster:

1
2
cd /tmp/railstest
mongrel_rails cluster::start

You should be able to test your application by going to http://localhost:8000. You could also hit any of the 8 ports you have configured.

Install Apache

We have come to the last part of this lengthy installation. Apache. Now, it must be understood that you MUST install Apache 2.2 or higher. The reason for this is the Apache Proxy Balance Module. This module is required to glue all this together and is ONLY available in Apache 2.2 or higher. I am going to build from source on this one because the current version available to me in the apt-get library is not the sufficient version required.

Download Apache, unpack it, and then change to the directory which contains the unpacked files.

1
2
3
wget http://archive.apache.org/dist/httpd/httpd-2.2.3.tar.gz
tar xvfz httpd-2.2.3.tar.gz
cd httpd-2.2.3

Configure the source tree for compiling Apache on your system:

1
2
3
4
5
6
./configure --prefix=/usr/local/apache2 
--enable-mods-shared=all 
--disable-deflate 
--enable-proxy 
--enable-proxy-balancer 
--enable-proxy-http

Build and install using the following commands:

1
2
make
sudo make install

Start Apache and navigate to your server through a browser. You should see the default Apache homepage.

1
sudo /usr/local/apache2/bin/apachectl start

There are several options for configuring and securing Apache that should be considered before taking this setup into production.

In order to configure Apache to serve your Mongrel cluster you will need to add the following to the Apache conf file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<Proxy balancer://mongrel_cluster>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
BalancerMember http://127.0.0.1:8002
BalancerMember http://127.0.0.1:8003
BalancerMember http://127.0.0.1:8004
BalancerMember http://127.0.0.1:8005
BalancerMember http://127.0.0.1:8006
BalancerMember http://127.0.0.1:8007
</Proxy>
 
<VirtualHost yourdomain.com:80>
ServerAdmin yourname@yourdomain.com
ServerName  www.yourdomain.com
ServerAlias yourdomain.com
 
# Indexes + Directory Root.
DirectoryIndex test.html
DocumentRoot /tmp/railstest/public/
 
<Directory "/tmp/railstest/public">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
 
RewriteEngine On
RewriteCond %{HTTP_HOST} ^yourdomain.com$ [NC]
RewriteRule ^(.*)$ http://www. yourdomain.com$1 [R=301,L]
 
# Check for maintenance file and redirect all requests
RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /system/maintenance.html [L]
 
# Rewrite index to check for static
RewriteRule ^/$ /index.html [QSA]
 
# Rewrite to check for Rails cached page
RewriteRule ^([^.]+)$ $1.html [QSA]
 
# Redirect all non-static requests to cluster
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
 
# Logfiles
ErrorLog  /tmp/railstest/log/error.log
CustomLog /tmp/railstest/access.log combined
</VirtualHost>
 
NameVirtualHost yourdomain.com:80

Now, there are 3 pieces to take note of here. First, you need to create a Proxy group for the mongrel cluster we created. Since we created 8 nodes, there are 8 BalancerMembers. Second, you will need a VirtualHost entry for your Rails site (in this case the railstest site we created earlier). And Finally, you have to add the NameVirtualHost entry for your VirtualHost (I can’t tell you how many times I forget that).

That should get you going with a Mongrel Cluster behind Apache Proxy. If you want to setup more than one site, then just create 3 more entries in your Apache conf file. You may want to think about separating the declarations from the main httpd.conf file, but for this example I just wanted to get you going. Have Fun!