Content-based sites with paid memberships

7 Aug 2008

If you’ve ever wanted to create your own content-based web site that requires paid memberships, now you can do so easily with Ruby on Rails, Radiant, and the Content Management Rails Kit.

Built on the same recurring billing code used in the Software as a Service Rails Kit, the CMS Rails Kit is an extension to Radiant that enables you to have various paid or free membership levels for a content site. So you could easily implement a pay wall for your content, or simply require registration to access it.

Information may want to be free, but that doesn’t mean you can’t try to charge for it anyway. :)



SaaS Rails Kit now supports Authorize.net CIM

17 Jul 2008

I’ve been keeping busy on a number of projects, like the recently-released NextProof, a site that provides easy e-commerce for professional photographers.

I have still managed to find some time to add more awesome to the SaaS Rails Kit, though… this time in the form of support for Authorize.net CIM as a payment gateway. A number of people have wanted this, so I’m happy to be able to get it out there.

In other news, I’m close to releasing the next Rails Kit, so stay tuned. :)



RESTful searching in Rails

26 Jun 2008

Over and over again I see people asking about how to do a search the “RESTful way” with Rails, and every time I do I just shake my head and wonder why we sometimes get so caught up in how we do something that it keeps from actually doing it. So, with that introduction, I want to present to you a really simple implementation of the most basic type of searching you can do in a Rails application. It just so happens that this method will also handle the bulk of your searching needs.

Let’s say you want to search through orders for a shopping cart. Instead of doing something fancy, let’s just assume you want to search on the customer’s name, the customer’s email, and also optionally restrict the search to a date range. First, here’s a snippet from the view, index.html.erb:

...
< % form_tag({:action => ‘index’}, :method => ‘get’) do %>
  < label>Name/Email< /label>
  < %= text_field_tag :q, h(params[:q]) %>
  < label>Date Range< /label>
  < %= text_field_tag :start_on, h(params[:start_on]) %>
  < %= text_field_tag :end_on, h(params[:end_on]) %>
  />
  < %= submit_tag ‘Search’ %>
< % end %>
...

What, throwing search right into the index action? You betcha. Oh, you want pagination with that? No problem:

...
< %= will_paginate @orders, :params => params >
...

Bam. Ok, on to the controller:

class OrdersController < ApplicationController

  def index
    @orders = Order.paginate(:all,
      :order => ‘orders.created_at’,
      :page => params[:page],
      :conditions => search_conditions,
      :joins => :user)
  end

  ...

  protected
 
    def search_conditions
      cond_params = {
        :q => "#{params[:q]}%",
        :start_on => Chronic.parse(params[:start_on]),
        :end_on => Chronic.parse(params[:end_on])
      }
     
      cond_strings = returning([]) do |strings|
        strings < < "(users.name like :q or users.email like :q)" unless params[:q].blank?
        if cond_params[:start_on] && cond_params[:end_on]
          strings << "orders.created_at between :start_on and :end_on"
        elsif cond_params[:start_on]
          strings << "orders.created_at >= :start_on"
        elsif cond_params[:end_on]
          strings < < "orders.created_at <= :end_on"
        end
      end
     
      cond_strings.any? ? [ cond_strings.join(and), cond_params ] : nil
    end
end

It just doesn’t get much easier than this. If there was no search, then the :conditions arg gets passed in as nil, which gets silently dropped. If there was one, then we build some conditions based on which parameters were specified. With a little bit of help from the chronic gem, we get easy date entry, to boot.

We’re done. And I just don’t care whether it’s RESTful or not. ;)



Gitosis for protected git repositories

12 Jun 2008

A number of Rails Kits customers asked for access to the git repository for the Kit they purchased, and I considered using GitHub for that, but this kind of usage doesn’t line up well with GitHub, since I have lots of users who need only read-only access to a few repositories. Since I already have the VPS set up anyway, I thought I’d give gitosis a shot.

Following this fantastic gitosis guide, I was ready to serve my git repository for the SaaS Rails Kit to my customers—and only to my customers :)—in no time. Now when I have a new customer wanting git access, I just add a public key to my local gitosis-admin clone, push it to my VPS, and I’m done.



Rails 2.1 gotcha with has_one

9 Jun 2008

I just updated the SaaS Rails Kit for Rails 2.1, and added a couple new payment gateways, and I thought I’d mention a behavior change in Rails 2.1 that might catch you unawares.

The new behavior in Rails 2.1 for has_one is that Rails will now automatically validate the association for you, which can cause you some problems if you already were validating the association yourself, as I do with the SaaS Rails Kit. In my case, I validate the subscription associated with a new account, but only if everything is valid with the account first, as I don’t need to hit the gateway with your credit card info if your account info is invalid. When I started to upgrade the Kit to Rails 2.1, my spec that checks that behavior started failing, as it got back the generic “is invalid” error message, rather than the error message I was generating inside the Subscription model.

So, I thought I’d put this blog post out there to hopefully save some people some time wondering what’s going on, and also to give you a good example of why thoroughly testing your code is a good idea. :)