Thursday, 9 October 2008

Deploying a Ruby on Rails Application

I am in the process of developing a laboratory sample logging application, and before going to far down the road wanted to check it would work in the production environment. For development I am using WEBrick, MySQL and Ruby (1.8.6) with NetBeans (6.1), but the server has PostgreSQL, with Tomcat (which requires JRuby), so there are plenty of potential problems moving from one to the other. If you do not have Ruby installed, you still need to use "jruby " before rake.

Moving to JRuby and PostgreSQL
NOTE: I had a problem moving to JRuby, as I had Ruby installed as well, and I had not realised that "gem install " will install a gem to Ruby, rather than JRuby, and so I had a rather confusing time with gems installed in the wrong place. To install a gem specifcally on JRuby use "jruby -S gem install ", and to use rake and warble, likewise prefix the command with "jruby -S " The -S swich tells jruby to use its own version of the binary. See more here:
http://wiki.jruby.org/wiki/Getting_Started#How_do_I_run_rake.2C_gem.2C_etc

My first step was to install JRuby 1.1.4 on the server (JRuby already includes Gems), and then Rails (with: "jruby -S gem install rails -y --no-ri"). All very easy. Then I had to create a database server in PostgreSQL, which I did through the command line:
createdb mydb

I created a new project as normal in Rails, and modified the database.yml file to this:

development:
adapter: jdbcpostgresql
encoding: unicode
database: mydb_development
username: postgres
password:
host: localhost
port: 5432

test:
adapter: jdbcpostgresql
encoding: unicode
database: mydb_test
host: localhost
username: postgres
password:

production:
adapter: jdbcpostgresql
encoding: unicode
database: mydb_production
host: localhost
username: postgres
password:


I chose to use JDBC, if you chose not to, just delete "jdbc" from the above.

Then I could use rake to create the databases ("jruby -S rake db:create:all"). Next I copied across the contains of the app and the db/migrate folders from my PC to the server, along with routes.rb (you might want other files from config too) and the stylesheets (I did not copy the tests; there seemed no point). I migrated my databases ("jruby -S rake db:migrate").

Then I installed the gem to handle database connections, either one, depending on whether you want to use JDBC or not:
jruby -S gem install postgres-pr
jruby -S gem install activerecord-jdbcpostgresql-adapter


At this point I could fire up the server, and check everything was okay (with "jruby script/server"), or use the interactive environment (with "jruby script/console").

So I had transferred to a different computer (though it could as well been the same computer, if I had been willing to install PostgreSQL on it) with a different database and a different Ruby; there were several issues that I have glossed over, but once you know what to do, pretty straightforward. No actual deployment yet though.

Moving to the Production Environment
To ensure the production database is used, in config/environment.rb uncomment this line:
ENV['RAILS_ENV'] = 'production'

To create the database tables in the production database:
jruby -S rake environment RAILS_ENV=production db:migrate

Warbler
I used Warbler to create a .war file (Warbler replaces GoldSpike). More information from here:
http://caldersphere.rubyforge.org/warbler/http://wiki.jruby.org/wiki/Warbler

Warbler is installed with:
jruby -S gem install warbler

By default, Warbler will package Rails, but no other gems. To change that (so the database connections are including), first create a config file using warbler ("warble config"). This creates a new file in your application config/warbler.rb. Edit the file to include the gems you require, or insert the following code to include all gems:

# From http://wiki.jruby.org/wiki/Warbler
# Include all gems which are used by the web application
require "#{RAILS_ROOT}/config/boot"
BUILD_GEMS = %w(warbler rake rcov)
for gem in Gem.loaded_specs.values
next if BUILD_GEMS.include?(gem.name)
config.gems[gem.name] = gem.version.version
end

Some other configuration setting can be found in tmp/war/WEB-INF/web.xml

Now create the .war file with:
warble
This should give the following output (if it has an mk command, then it is using Ruby rather than JRuby, I think):
jar cf mydb.war -C tmp/war .

Note that warbler requires access to a Java JDK, so you need that in your path (PATH=C:\Program Files\Java\jdk1.6.0_07\bin;C:\jruby-1.1.4\bin;%path%).

Moving to Tomcat
The .war file can then be dragged to the Tomcat webapps directory. You may need to restart Tomcat, but not necessarily. Tomcat will decompress the .war file and the web application can now be accessed with:
http://<servername>:8080/<app>

8080 is the default port for Tomcat. is the project name, which is the folder name for your application.

To replace an old version in Tomcat, you need to stop Tomcat, delete the directory with your project name (which Tomcat created by decompressing your old .war file), copy across your new .war, and restart Tomcat.

Overall it probably took me two to three times longer to deploy the application than it did to build the first draft of it, however, now I know what to do, it will be much, much quicker next time!

Struggling with Ruby: Contents Page

No comments: