Read my latest article: RubyURL meets Zombies! (posted Tue, 22 Apr 2008 16:43:00 GMT)

DRY(a): Year After Year 28

Posted by Robby Russell Tue, 25 Mar 2008 03:05:00 GMT

I’m guilty of it. Many of you are likely guilty of it… and I know that several customers of our Rails Code Audit and Review service are guilty of it.

How many times have you realized (after a few months has passed) that your Copyright date/year on your web site was no longer current?

How many of you had the same problem last year? The year before?

Let me share some advice with you all… DRY (a)!

Don’t Repeat Yourself (again)!

This is really a simple problem to fix but when we’re busy tackling bigger problems… little things like this slip by. Don’t worry, you’re not the only one who was reminded by a colleague three months into the year that you forgot to update this.

On client projects, we have a handful of helpers that we drop into the application. We’re starting to extract more of these into plugins and will be releasing those as time permits. It just happened that I found myself looking at yet-another Rails code base this afternoon that was showing 2007 in the footer. An easily forgivable offense.. but if you’re going to go in there and change it (again), take a moment to do the right thing. ;-)

Our solution at Planet Argon on client projects is to create a basic view helper that renders the current year. This allows us to do the following.


  <div id="footer">
    &copy; Copyright <%= current_year -%>. All Rights Reserved.
  </div>

The helper code looks like:


  # add to application_helper.rb
  module ApplicationHelper
    def current_year
      Time.now.strftime('%Y')
    end
  end

Voila. Not rocket science.. is it?

Guess what? I’m getting really tired of adding this to every Rails project that I touch. So, I bottled this little gem into a new Rails plugin that we’ll just add to future projects.

Introducing Year after Year

This is really the smallest plugin that I could put together (and it includes specs!)

What does it provide you?

YearAfterYear will provide you a helper that will render the current year (dynamically)! That’s right… just add the plugin to your Rails application and you too can enjoy New Years 2009 without having to have a deployment ready with a one line change from 2008 to 2009!

To use.. add the following to any view from within Ruby on Rails.


  <%= current_year -%>

Installation

As I’m using git, you’ll need to grab this and put it into vendor/plugins. That’s it!

You can grab it on GitHub!

Happy New Years (8+ months early)!

Just a friendly reminder to not forget the small stuff… because your visitors will notice! ;-)

Updates…

I got a few requests for this to also provide a range of years for people who like to do: 2005-2007. So this is now provided as well.

year_range(start_year)

Example:

  <%= year_range(2005) %> # => 2005-2008

Master/Slave Databases with Ruby on Rails 5

Posted by Robby Russell Thu, 15 Nov 2007 22:02:00 GMT

Not terribly long ago, I announced Active Delegate, which was a really lightweight plugin that I developed to allow models to talk to multiple databases for specific methods. The plugin worked great for really simple situations, like individual models.. but when it came time to test with associations it fell apart. I haven’t had a chance to work on any updates and knew that it was going to take more work to get it going.

Earlier this week, we helped one of our bigger clients launch their new web site1. For the deployment, we needed to send all writes to a master database and a reads to slaves (initial deployment is talking to almost 10 slaves spread around the globe!). We needed something to get integrated quickly and decided to ditch Active Delegate for the time being and began looking at the following options.

I spoke with Rick Olson2 and he pointed me to a new plugin that he hasn’t really released yet. So, I’m going to do him a favor and announce it for him. Of course… I got his permission first… ;-)

Announcing Masochism!

Masochism3 is a new plugin for Ruby on Rails that allows you to delegate all writes to a master database and reads to a slave database. The configuration process is just a few lines in your environment file and the plugin takes care of the rest.

Installing Masochism

With piston, you can import Masochism with:


  $ cd vendor/plugins
  $ piston import http://ar-code.svn.engineyard.com/plugins/masochism/

You can also install it with the old-fashioned way:


  $ ./script/plugin install -x http://ar-code.svn.engineyard.com/plugins/masochism/

Configuring Masochism

The first thing that you’ll need to do is add another database connection in config/database.yml for master_database. By default, Masochism expects you to have a production database, which will be the read-only/slave database. The master_database will be the connection details for your (you guessed it…) master database.


# config/database.yml  
production:
  database: masochism_slave_database
  adapter: postgresql
  host: slavedb1.hostname.tld
  ...

master_database:
  database: masochism_master_database
  adapter: postgresql
  host: masterdb.hostname.tld
  ...

The idea here is that replication will be handled elsewhere and your application can reap the benefits of talking to the slave database for all of it’s read-only operations and let the master database(s) spend their time writing data.

The next step is to set this up in your environment file. In our scenario, this was config/environments/production.rb.


# Add this to config/environments/production.rb
config.after_initialize do 
  ActiveReload::ConnectionProxy.setup!    
end


Voila, you should be good to go now. As I mentioned, we’ve only been using this for this past week and we’ve had to address a few problems that the initial version of the plugin didn’t address. One of our developers, Andy Delcambre, just posted an article to show how we had a problem with using ActiveRecord observers and masochism, which we’re sending over a patch for now.

As we continue to monitor how this solution works, we’ll report any findings on our blog. In the meantime, I’d be interested in knowing what you’re using to solve this problem. :-)

1 Contiki, a cool travel company we’re working with

2 Rick just moved to Portland… welcome to stump town!

3 The Masochism plugin README

Multiple Database Connections in Ruby on Rails 15

Posted by Robby Russell Fri, 05 Oct 2007 22:54:00 GMT

We have a client that already has some database replication going on in their deployment and needed to have most of their Ruby on Rails application pull from slave servers, but the few writes would go to the master, which would then end up in their slaves.

So, I was able to quickly extend ActiveRecord with just two methods to achieve this. Anyhow, earlier today, someone in #caboose asked if there was any solutions to this and it prompted me to finally package this up into a quick and dirty Rails plugin.

Introducing… Active Delegate!

To install, do the following:


cd vendor/plugins;
piston import http://svn.planetargon.org/rails/plugins/active_delegate

Next, you’ll need to create another database entry in your database.yml.


login: &login
  adapter: postgresql
  host: localhost
  port: 5432

development:
  database: rubyurl_development
  <<: *login

test:
  database: rubyurl_test
  <<: *login

production:
  database: rubyurl_servant
  <<: *login

# NOTICE THE NEXT ENTRY/KEY
master_database:
  database: rubyurl_master
  <<: *login

At this point, your Rails application won’t talk to the master_database, because nothing is being told to connect to it. So, the current solution with Active Delegate is to create an ActiveRecord model that will act as a connection handler.


  # app/models/master_database.rb
  class MasterDatabase < ActiveRecord::Base
    handles_connection_for :master_database # <-- this matches the key from our database.yml
  end  

Now, in the model(s) that we’ll want to have talk to this database, we’ll do add the following.


  # app/models/animal.rb
  class Animal < ActiveRecord::Base
     delegates_connection_to :master_database, :on => [:create, :save, :destroy]
  end

Now, when your application performs a create, save, or destroy, it’ll talk to the master database and your find calls will retrieve data from your servant database.

It’s late on a Friday afternoon and I felt compelled to toss this up for everyone. I think that this could be improved quite a bit, but it’s working great for the original problem that needed to be solved.

If you have feedback and/or bugs, please send us tickets.

Be Careful that you don't Stub your Big Toe 6

Posted by Robby Russell Tue, 13 Feb 2007 07:09:00 GMT

In a project that I’m currently working on, we’re handling recurring payments for subscribers. I’ve decided to play with a different payment service API on this project (TrustCommerce), which supposedly has one of the easier systems to handle recurring payments as well as one-time charges to the same credit cards. They store all the credit card data so that our delivered product to the client is CISP-compliant.

I came across the TrustCommerce Subscription plugin for Rails, which does just everything that I need to do in this first product release… as well as things that aren’t requirements just yet.

Well, I got my test account from TrustCommerce and was working on some RSpecs to test my new subscription and noticed that it was failing. After some snooping around the error responses, I realized that… test accounts don’t give you the ability to test the Citadel features of TrustCommerce. It’ll be another week or so before finish getting our account setup, so what am I to do? I really want to finish writing these specs and move on to the other portions that are dependent upon this working.

Suppose that you were going to perform something like this in an AR callback.


class BillingDetail < ActiveRecord::Base

  # validations    

  before_create :store_credit_card_data_with_trust_commerce

  private 

    def store_credit_card_data_with_trust_commerce
      # some of this is still test data... prettyu much copied from the README
      # TODO: refactor... but keep me out of controllers!
      response = TrustCommerceGateway::Subscription.create(
          :cc =>  self.credit_card_number, 
          :exp => '0412', 
          :name => self.customer_name,
          :amount => 1,
          :cycle => '1y',
          :demo => 'y'
        )

      if response['status'] == 'approved'
          self.billing_id = response['billingid']
        else
        # handle failure
        end
    end
end

Enter Mock Objects

Since I am unable to succesfully use the TrustCommerceGateway::Subscription.create method until I get our real account, I needed a simple way to emulate the interaction with the web service.

This can be done by using a Mock object, which RSpec provides for you.


TrustCommerceGateway::Subscription.stub!(:create).and_return( {expected response} )

Let’s look at the following spec file (much of it removed to protect the innocent).


module ValidBillingDetail
  def valid_attributes
    { # a hash of valid key/values for this model }
  end

  def approved_trust_commerce_subscription
    { 'status' => 'approved', 'billingid' => '1093423' } 
  end
end

context "A new billing detail" do
  include ValidBillingDetail

  setup do
    TrustCommerceGateway::Subscription.stub!(:create).and_return( approved_trust_commerce_subscription )
  end

  # bunch of other specs

  specify "should store new billing info with 3rd party API and store the billingid" do
    @billing_detail = BillingDetail.create( valid_attributes )
    @billing_detail.billing_id.should_not_be nil
  end
end  

You’ll notice a few things. First, you’ll see that I’ve stubbed the create method and when it is called in the method in my model, it’ll return the hash that I’ve specified.

TrustCommerceGateway::Subscription.stub!(:create).and_return( approved_trust_commerce_subscription )

In the spec, you will see that I am checking that that the .billing_id.should_not_be nil. If you look back in the method in the model above, you will notice that an approved subscription returns a billing_id, which is set when the transaction is successful.

This is working out great for me and because the documentation is fairly easy to follow, I’m going to be able to mock much of the behavior that I’ll be using in the application, without needing to even connect to their API.

If you’re using RSpec, I highly encourage you to read more about mocks objects.

Testing Cookies in Ruby on Rails 2

Posted by Robby Russell Mon, 28 Aug 2006 13:27:00 GMT

Over the weekend, Brian Ford released a useful plugin for testing your Ruby on Rails applications called, assert_cookie.

Brian likes his cookies…

“I love cookies. There are, of course, tons of varieties and I’m no connoisseur but I love the soft chocolate chip right out of the oven, hot and gooey. But, if you’re like me, you don’t want your Rails code to be gooey.” -Brian Ford

To use assert_cookie, follow these steps.

  1. Install via, script/plugin install http://svn.planetargon.org/rails/plugins/assert_cookie
  2. Fill your tests with some cookies
  3. Test your cookies!
Here are a few examples that Brian posted.
  assert_cookie :pass, 
      :value => lambda { |value| UUID.parse(value).valid? }
  assert_cookie :yellow, :value => ['sunny', 'days']
  assert_cookie :delight, :value => 'yum'
  assert_cookie :secret, :path => lambda { |path| path =~ /secret/ }, 
      :secure => true

For more information on other plugins and tools that PLANET ARGON is releasing under open source licenses, visit www.planetargon.org.

Also, be sure to subscribe to Brian Ford’s feed as he says he’ll be announcing more plugins and tips soon. :-)

Have Fun!

RAILS PLUGIN: Resource Hacks

Posted by Robby Russell Thu, 03 Aug 2006 15:17:00 GMT

Jeremy Voorhis and Andrew Grim released a new plugin for Ruby on Rails called, resource hacks , which can be found in the PLANET ARGON open source repository located at www.planetargon.org.

Take a moment to read Jeremy’s announcement.

Enjoy and digg it. :-)