Posts Tagged ‘Rails’

Automate Your Rails Deployment

Friday, July 18th, 2008

I’m a big fan of researching and playing with new technologies (hey! I remember rails 0.7) so its no surprise that I’ve been playing a lot with Ruby Enterprise Edition and Phusion Passenger (mod_rails) and researching it as a viable rails deployment solution. For those of you who are staying with the tried and true Nginx + Mongrel, let me offer a brief introduction to Phusion Passenger (mod_rails). But first… let’s take a trip down memory lane:

Rails Deployment History

Phusion Passenger is super easy to install and setup as an Apache mod and immediately simplifies the deployment of rails. It allows you to deploy a rails application without splitting your attention between the web server and app server, such as Nginx and Mongrel. You literally upload a configuration which looks like the following block of code to Apache and it manages your rails application for you.

<VirtualHost *:80>
  ServerName  myrailssite.com
  ServerAlias www.myrailssite.com
 
  DocumentRoot /var/www/rails-project/current/public
</VirtualHost>

Passenger gives rails the same ease of deployment as mod_php and mod_perl. And when you want, it will automatically reload your app if you deploy changes.

But the real gem is using Phusion Passenger with Ruby Enterprise Edition, which is a rewrite of the Ruby MRI with optimization for mod_rails in mind. The initial benchmarks show that using both together results in lower memory usage and increased requests per second. Since then, passenger has had a myriad of early adopters reporting their results. DreamHost praised Phusion for finally solving their rails deployment, after complaining only 4 months earlier of how rails deployment options were a joke. Other websites have boarded the Phusion Passenger train too, reporting easy setup and even easier deployment.

The results look good: Dead easy rails deployment with great performance.

So how do you get started? For dead easy server provisioning, check out Sprinkle, a gem which provisions servers for you. I’ve been hard at work implementing new features and patches to Sprinkle, which you can see in my fork. I have already created the sprinkle scripts to automatically setup this entire stack on a fresh ubuntu server:

  • Rails (and Ruby, Rubygems)
  • sqlite3 or mySQL
  • Apache2
  • Phusion Passenger (mod_rails)
  • Ruby Enterprise Edition

If you’re interested in the automatic setup solution, I recommend checking out the screencast I made detailing the entire process. It requires a custom version of the sprinkle gem (from my fork), which the screencast covers.

If you plan on trying it out and have any questions, leave a comment or feel free to contact me at mitchell.hashimoto [at] citrusbyte [dot] com and I’ll happily provide any assistance you may need.

Keep your site as fresh as your code

Friday, June 27th, 2008

I am actively working on PoolParty, but the website doesn’t necessarily show that the project is in active development.

Luckily, it is hosted at github and they have an API to access their changesets. Now, on PoolParty’s website, I am surfacing the latest changeset’s time, message and author as well as a link to the changeset.

How?

Code (shortened for brevity purposes):

$:.unshift(File.dirname(__FILE__))
require "rubygems"
require "yaml"
require "open-uri"
 
class Grab
  @url = "http://github.com/api/v1/yaml/auser/pool-party/commits/master"
  @refresh_after = 20
 
  def self.latest_commit_object
    o = yaml["commits"][0]
    {
      :message => o["message"].gsub(/\n/, "<br />"),
      :date => Time.parse(o["committed_date"]).timeago,
      :by => o["committer"]["name"],
      :url => o["url"]
    }
  end
end

The github api is slick. As you can see from above, the format for the api url looks like

http://github.com/api/version/format/username/repository/type/object

Where the variables there correspond to:

  • Current version: v1
  • Acceptable formats: json, xml, yaml
  • Acceptable types: commits, commit

Grabbing the latest changesets from the url as YAML format, we can quickly and easily parse the message into a useful hash.

I personally like the “# hours ago” syntax that 2.0 sites are popping up with everywhere, so I just added a timeago method that is very similar to the one included with rails. The source is attached.

Since I don’t want poolpartyrb.com’s load time to be dependent upon how fast it can hit github, I cache the variable so every 20 views it refreshes.

Use in Rails

Save both the files (attached below) to your lib directory.

Add this to your environment.rb

require 'grab'

Then add this helper to your application_helper.rb

  def show_latest_commit
    @latest_commit = Grab.latest_commit_object
 
    <<-EOS
      <div class='note'><strong>Latest commit</strong><br />
      <a href="#{@latest_commit[:url]}">#{@latest_commit[:message]}</a>
      <div class="highlight">by #{@latest_commit[:by]}</div>
      #{@latest_commit[:date]}
    EOS
  end

How to use in sinatra

I use this on poolpartyrb.com, which is a sinatra site. I do basically the same as above, but generally render the code in haml instead

  $:.unshift(File.dirname(__FILE__))
  require "sinatra"
  require 'grab'
 
  get '/' do
    @latest_commit = Grab.latest_commit_object
    haml :home, :layout => :layout
  end

Then in my home.haml

  .note
    %strong
      Latest commit
    %br
    ==<a href="#{@latest_commit[:url]}">
    = @latest_commit[:message]
    </a>
    .highlight
      == by #{@latest_commit[:by]}
    = @latest_commit[:date]

Get the code here

edit: updated location of code

Kill your fixtures and spec happily

Saturday, April 5th, 2008

The trouble w/ fixtures

I don’t use fixtures in my specs. At all. The fundamental issue with fixtures is that they setup a state for your database as a whole (or at least the tables you loaded). So when you use fixtures all your specs are running against essentially the same state. As you build your application and things get more complex your fixtures become more complex and your state grows and grows. The needs of your specs, however, should pretty much stay the same. So when you go back and track down an issue causing some spec to blow up you have to deal with that spec running in a state that’s way beyond it’s needs.

Brittle specs

For example, lets stay I’m writing a spec to ensure that book.authors.living does not return any deceased authors. The state that I need to spec this is very simple: 1 Book with 1 living Author and 1 dead Author. Then I just need to make sure that when I run book.authors.living I don’t get the dead Author back. It might look something like this:

describe Book do
  describe "with authors" do
    fixtures :books, :authors
 
    it "should only find living authors" do
      Book.find_by_title("Foo's Diary").authors.living.should == [Author.find_by_name('Jim')]
    end
  end
end

Assuming I know that Jim is alive this would be a good spec. The problem is as I write specs I’m going to add more and more authors and this spec will quickly blow up. It’s not blowing up because the .living method broke though, it’s just blowing up because it’s no longer running in the state it expected.

Kill your fixtures

Without fixtures I would do something like:

describe Book do
  describe "with authors" do
    before :each do
       @book = Book.create! :title => "Foo's Diary"
       @book.authors << (@jim = Author.new(:name => 'Jim', :dead => false))
       @book.authors << (@jeff = Author.new(:name => 'Jeff', :dead => true))
    end
 
    it "should only find living authors" do
      @book.reload.authors.living.should == [@jim]
    end
  end
end

Now my spec will always run in the state I gave it. So the things I setup for my other specs won’t come back and blow this spec up. Furthermore, the state isn’t buried in multiple fixture files. It’s defined plainly right above the spec(s) which use it.

Simplify your life even more

Once you ditch your fixtures you’ll find a new love for writing specs. There’s a couple handy tools to simplify your life further though:

Factories

Dan Manges blogged about using factories to simplify creation of classes and to provide defaults. Since then there’s been a few plugins developed for quick and easy factories. We’ve been using Scott Taylor’s Fixture Replacement.

add!

add is similar to the << method of has_many associations except it sacrifices chainability in order to return the concatenated object. add! goes a step further and throws an exception if the concatenation failed. This is useful in specs because the exception (probably due to a validation error) will occur in your state setup and you will see the error message in your output when you run your specs. So the reason your spec just blew up is displayed for you.

With Fixture Replacement and add! the example above would look something like:

describe Book do
  describe "with authors" do
    before :each do
       @book = create_book :title => "Foo's Diary"
       @jim = @book.authors.add! new_author(:name => 'Jim')
       @jeff = @book.authors.add! new_author(:name => 'Jeff', :dead => true)
    end
 
    it "should only find living authors" do
      @book.reload.authors.living.should == [@jim]
    end
  end
end

Clean up your code a little with add!

Thursday, April 3rd, 2008

Here’s a little chunk of code I’ve been using recently. It gives you .add
and .add! methods on your has_many relationships that work similar to the << method. The difference is that .add sacrifices chain-ability in order to return the object being added to the collection.

Adding instead of concatenating

Using book.authors << Author.new(:name => ‘Geoff’) returns true or false forcing you to do something like book.authors << (geoff = Author.new(:name => ‘Geoff’)) to maintain a reference to the new object. Using .add you can do geoff = book.authors.add Author.new(:name => 'Geoff')

No really…add!ing

Perhaps even more helpful (especially in specs) is the add! method. add! acts just like add except it raises a RecordInvalid exception on failure. So you can do geoff = book.authors.add! Author.new(:name => 'Geoff') and have your execution (or your transaction) halt if Geoff messed up and wasn’t valid.

Blowing up your specs

This comes in handy a lot in your specs as exceptions will be displayed as the reason for failure. So if you were to add a validation to your Author class that caused all the Author’s you were adding to Book’s all over your specs to be invalid, you would see it (along with your validation’s helpful error message) when you ran your specs.

The goods

Just drop this in a file in your /lib folder and require it in an initializer.

module ActiveRecord
  module Associations
    class AssociationCollection < AssociationProxy #:nodoc:
      # works just like << except returns the added records instead of self, so
      # it's not chainable but allows you to do something like:
      #   @jim = Book.authors.add Author.new(:name => 'jim')
      # (often saving a whole line of code!)
      def add(*records)
        self.<<(*records)
        unarray_if_lonely(records)
      end
 
      # works just like add except raises an exception on error
      def add!(*records)
        raise RecordInvalid.new(*records) unless self.<<(*records)
        unarray_if_lonely(records)
      end
 
      # if the given object is an array of size 1 then it returns the only
      # element itself (w/ no array), otherwise it just gives back object
      def unarray_if_lonely(object)
        (object.is_a?(Array) && object.length == 1) ? object.first : object
      end
    end
  end
end