An on-line store build with Ruby on Rails 21
In this non-technical article I wanted to share my impressions of writing an online store with Ruby on Rails. http://www.autumnriderstees.com/
Background
On September 9th Lee’s dad mentioned that he would receive a stock of new quality designer T-shirts with funny bikers logos on September the 22nd and asked Lee if he could setup an on-line store. Lee asked me if I could help out writing it in Ruby on Rails and if I thought it was feasible. Hey, I just finished “Agile Web Development with Rails”, how hard could it be, the book contains everything we need. So “heck, yea, we can do it”. So Lee told his dad: “Sure, we’ll do”. Well, it took us just a little longer, not much thought, considering we just met once a week for a month, and two weekends. But considering that Lee just started a new Rails gig, me just being father for the second time and a little sleep depraved, we manage to go-life on October the 16th at RubyConf 2005. First Ruby and Rails is really cool, Dave Thomas books are invaluable in many aspects, not the least being that the most of the order processing part of the application is taken straight from book.
The application
The application is composed of the Store and the Order processing application. The Store allows selecting 4 T-shirt designs each in 5 sizes, to add the ones you like to shopping cart and finally go to a checkout page where shipping and billing information can be entered. Payment processing is done using the payment ruby library that supports Authorize.net merchant accounts (that’s just the one we needed and we go the credit card payment processing integrated in 10 minutes :-). All in all we built the most basic on-line store that one can build. Nowadays such a store can certainly be setup for a couple of dollars with yahoo and other providers. But the fun part was to do it and learn from that. Maybe if Shopify was open for business we wouldn’t have tried to write our own on-line store…but then again we wouldn’t have learn as much.
There are many things that can be improved and we are already planning for next year to add support for more products, designs and configurations to support things like Mugs and Long-Sleeve Shirts. So there will quite some refactoring for the next iteration.
The development process
Well…we where not too formal I believe, we used Basecamp to communicate ideas and create todos and then we just jumped in. Lee’s approach is usually more intellectual and he wants to get things pretty nicely laid-out before starting and I like to start and learn from what we discover and improve has we move along. Together we got a good mix. Lee’s dad just wants to sell his t-shirts. Now regarding Basecamp, if first thought it would be “overkill” for such a small project but it’s really a nice communication tool and helped us out getting organized without having to really think about it.
The look and feel
It’s got to work well, but that doesn’t matter if it’s not looking good. It’s got to look good. Well…we are software programmers, software designers, software architects, but even thought I don’t like to admit it, pretty lousy graphic designers. My first attempts to prototype the site gave a good feel of the structure and style…but just didn’t cut it. On the side for simple html work I use RapidWeaver, a cool tool on OSX to rapidly build html website of predefined types. This tool does a great job of separating content and style and provides a bunch of pretty nice html design that rely heavily on css. Well it took me about five minutes to get a pretty nice proto for the store using that tool and that’s what we went with. The nice part is that is was pretty straight forward to change the static site into dynamic .rhtml pages. Layouts in Rails are just awesome. From an usability point of view, we still have one step to much as the cart and checkout page should really become one. For the next version, we will try to have it similar to the Panic’s Good Store.
DataModel
The data model was fairly straight forward mostly consisting of an Order having many LineItem.
Architecture
Although a file structure of an application doesn’t depict an architecture, Ruby on Rails really provides a nice starting point for organizing your code in a clean MVC (model-view-controller) manner and really makes it straight forward for a simple application like this one.
Credit Card Payment
Let’s look at some code. First we need the payment gem.
require 'payment'Then we just need to submit the transaction. I was really as simply as that. Of course you need a merchant account.
def process_payment(order, credit_card_number, credit_card_expiration_mmyy )
@transaction = Payment::AuthorizeNet.new(
:prefs => "#{RAILS_ROOT}/config/payment.yml",
:amount => @cart.total_price,
:expiration => credit_card_expiration_mmyy,
:first_name => order.bill_to_last_name,
:last_name => order.bill_to_first_name,
:card_number => credit_card_number,
:invoice => order.order_number,
:test_transaction => RAILS_ENV != 'production'
)
@transaction.submit
@transaction.authorization
endMigration
We went only through the following database schema migrations:
001_initial_schema.rb
002_add_order_ship_date_and_status.rb
003_add_order_date.rb
004_add_users.rb
005_add_product_options.rb
However writing migrations in Ruby is just such a simple solution and make so much sense that I am surprised that there is no standard tools like that in the Java world.
Let’s look at migrating the schema to version 2. We need to add two columns to the orders table and default existing values to ‘Open’. No to move from version 1 to 2, simply issue the command rake migrate. If for some reasons we wanted to revert to version 1, we could issue the command rake migrate VERSION=1.
class AddOrderShipDateAndStatus < ActiveRecord::Migration
def self.up
add_column :orders, :shipped_at, :datetime, :null => true
add_column :orders, :status, :string, :limit => 40, :default => 'New', :null => false
execute "UPDATE orders SET status = 'Open'"
end
def self.down
remove_column :orders, :status
remove_column :orders, :shipped_at
end
endThe “Ajax” thing
Of course we had to play with this. We only used the no page refresh approach when updating the cart. Note when you change the quantity of a given item, the Cart and Checkout tab both get updated dynamically, as well as the total of the order. Note that I only found after the fact the “right” way to update multiple ids from a single server call using evaluate_remote_response instead of our custom solution. In addition with the new javascript supported template (.rjs) all that will be cleaned up for our next iteration.
Testing
We didn’t take a fully Test First Development approach, but Rails makes it so much fun to test that we quickly went back to writing tests while we where developing some of the classes like the cart model and the store controller.
Hosting
I believe that deploying a Rails application in a hosting environment is the weakest point of Rails today. We are using two hosts for different matters, TextDrive and Dreamhost. On other projects we are working with Tom who also happen to have helped Dreamhost setting up Rails on their server and made it pretty easy to deploy a Rails application. So Dreamhost is the route we went, however the application doesn’t always respond nicely and at least not in a consistent manner. I guess that’s maybe what we deserve by using a $9/month hosting plan. Let’s hope that http://railsbase.com from TextDrive will provide a more compelling experience where we don’t have to regularly kill ghost fastcgi processes.
Conclusion
It was a fun learning experience and Rails made it just enjoyable. Ruby and Ruby on Rails forces you to write clean and simple code, encourages you to write unit tests and to refactor stuff as you move along. It’s impressive when comming from a java enterprise background how much more enjoyable and faster development becomes when using Rails.
hi, I am trying to connect to authorize.net through payment gem.. but getting invalid id and password error which I confirmed from authorize.net are correct id and password.. can you tell me the content of payment.yml …(after spacing out your id and password) did you use the api login id or test login id ?
The payment.yml file contains the following two lines and is in the config folder. In that case the merchant account login id is “yourid” and the password is “secret”.
login: yourid
password: secret
Really interesting.
How about the ssl certificate for the https protocol? Did you buy one (it is very expensive)? Or there is another cheaper solution? How did you change from a http connection to a https one from the rails code?
Great! Thanks for the information, specially for the certificate tips. It has opened my eyes to new possibilities.
in regards to the hosting. why isn’t it easy to set up a ruby hosting server? i didn’t exactly understand that. where is basecamp running and what config?
Hi Rashantha,
When the article was written there was not good hosting provider that support Rails without having issues with fcgi. Now hosting providers support mongrel and the situation got easier. However, unless you have sysadmin skills it’s not pretty straight forward to configure your server. Capistrano made deployment pretty easy, but there are situations where it would be nice to be able drop a packaged rails application as a single file into a server and have it deployed, without capistrano.
My advice would be to ditch shared hosting. My rails dispatchers are living on about 100 meg of virtual memory each. Add in html tidy, imagemagik, and whatever and things tend to grow. I can’t assign blame to individual gems because I have not looked in to it. With Xen hosting the app is in memory 24/7 and only gets swapped to disk if I run too much on the server (which I tend to do). Shared hosting just plain sucks all around with mysql connection limits, getting hacked, cpanel, overselling, etc. . . Ditch it and go with Xen if you value your sanity. Rails runs very well when it has room to breath. All the 500 errors and misc garbage you see on other peoples sites is due to misconfiguration or dispatchers missing in action. Dedicated memory and CPU time will solve your deployment troubles. Get Xen.
Hey guys great site. Any chance of publishing a step by step tutorial on this? I’m new to RoR and am especially interested in the payment procedure.
Thanks
Hey guys great site. Any chance of publishing a step by step tutorial on this? I’m new to RoR and am especially interested in the payment procedure.
Thanks
On October 9th 2007
http://www.autumnriderstees.com/
gives
Application error
Rails application failed to start properly”