An on-line store build with Ruby on Rails 21

Posted by Daniel Wanja Sat, 03 Dec 2005 15:04:00 GMT

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.

show larger image

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.

show larger image

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
end

Migration

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
end

The “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.

Comments

Leave a response

  1. todd Sat, 10 Dec 2005 19:10:10 GMT
    is the shopping cart available as an install? i too am on dreamhost, and am in a way stuggling with getting rails up and running. this is an excellent resource!
  2. Daniel Wanja Sun, 11 Dec 2005 12:03:18 GMT
    The shopping cart is not available for download. We started developing a "more" generic version where more than one type of product can be sold. I will need to see with Lee what he thinks about making the source code available. To me that sounds as a good idea. But I don't think we will release before adding the new functionality. For setting up Rails on Dreamhost you should check Tom's blog at http://convergentarts.com/ or Dreamhost's wiki at http://wiki.dreamhost.com/index.php/Ruby_on_Rails
  3. Leslie Freeman Fri, 14 Apr 2006 23:48:14 GMT
    Hi, This was a great article to find! I am currently setting up my first ruby on rails ecommerce solution. I am looking at using the payment gem and I am glad to hear that it was as painless to use as it looks! I am also interested in using the shipping gem to calculate shipping costs as the business has a UPS account. Did you end up using this gem? I have had a hard time finding anything other than the API documentation for either of these gems and I was wondering if you have any good links to other info. Thanks! Leslie
  4. Daniel Wanja Sat, 15 Apr 2006 09:45:08 GMT
    Hi Leslie, I have not used the shipping gem. For autumnriderstees.com the charges are based on the amount and ship_to country. So we have a ShippingCharge active record that defines the shpping charges without using an external system. For the payment gem I downloaded the api documentation from Authorise.Net website, thats what the payment gem was coded against. I guess if you check UPS, if you didn't already, you may find more info. I saw that you can download their documentation at http://www.ups.com/e_comm_access/gettools_index?loc=en_US, and they provide some more info at http://www.ups.com/content/us/en/bussol/offering/technology/automated_shipping/online_tools.html. Although they mention some restrictions on the shipping calculator usage. Let me know what you find out as I am currently working on a product for a client that may need to use this gem in the near future.
  5. Kevin Mon, 17 Apr 2006 08:30:52 GMT
    What Authorize.net reseller are you using? Would you recommend them?
  6. Daniel Wanja Mon, 17 Apr 2006 20:13:20 GMT
    I don't use the merchant account directly, it's Lee's dad that runs the 'business' and it's his account. He went directly throught Authorize.Net with their online merchant interface. I believe it works well for him, althought I don't believe he has a huge volume. If he does, I may need to get back to him and ask for a couple more free t-shirts. See http://www.authorize.net/solutions/merchantsolutions/merchantservices/merchantinterface/ for more info on the merchant interface.
  7. Leslie Freeman Mon, 17 Apr 2006 22:46:40 GMT
    Daniel, Thanks for the information and the links. That was a way of approaching getting that info that I hadn't thought about. I am hopefully going to be getting to the shipping gem in the next week or so and I'll let you know what I figrue out.
  8. Neil Bradley Wed, 19 Apr 2006 07:26:31 GMT
    Can you use PayPal with Authorise.net? I have been tasked with creating an Online Store to be able to allow people to purchase items with Credit Card and/or PayPal.
  9. Daniel Wanja Thu, 20 Apr 2006 07:43:16 GMT
    I short I don't know if you can use PayPal with Authorise.Net, but I would assume not. It seems that both a different merchant accounts. But having a PaylPal merchant account would also allow you to accept credit cards.
  10. Daniel Wanja Mon, 22 May 2006 07:34:24 GMT
    Also check out Active Merchant - A ruby library for integrations with credit card gateways at http://home.leetsoft.com/am. This is written by the guys that work on Shopify.
  11. datta Wed, 30 Aug 2006 10:52:49 GMT

    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 ?

  12. Daniel Wanja Wed, 30 Aug 2006 11:52:32 GMT
    When we create a new transaction we pass the location of the payment yml file to the :prefs parameter.
       @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'   
                         )

    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

  13. Charlie Wed, 06 Dec 2006 00:43:19 GMT

    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?

  14. Daniel Wanja Wed, 06 Dec 2006 11:08:09 GMT
    The url_for method takes a :protocol parameter which we set to https for the checkout link. The code looks similar to this:
    url_for(:action => 'checkout', :only_path => false, :protocol => 'https://' )
    
    We did buy a certificate at GoDaddy for $20 a year. The other cost we had was that in order to deploy the certificate on our shared host we needed a fixed ip address, so that’s $50 more a year.
  15. Charlie Thu, 07 Dec 2006 02:27:22 GMT

    Great! Thanks for the information, specially for the certificate tips. It has opened my eyes to new possibilities.

  16. rashantha de silva Sun, 07 Jan 2007 20:52:03 GMT

    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?

  17. Daniel Wanja Fri, 12 Jan 2007 09:32:14 GMT

    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.

  18. Sam Fri, 12 Jan 2007 10:34:22 GMT

    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.

  19. Raj Thu, 09 Aug 2007 11:05:57 GMT

    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

  20. Raj Thu, 09 Aug 2007 11:05:58 GMT

    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

  21. davidbennettuk@yahoo.co.uk Wed, 10 Oct 2007 01:33:43 GMT

    On October 9th 2007

    http://www.autumnriderstees.com/

    gives

    Application error

    Rails application failed to start properly”

Comments