cheddargetter_client_rails

The CheddarGetter rails client aims to tie the CheddarGetter API closely into ActiveRecord models.

Much of the heavy lifting with the api itself is done through the cheddargetter_client_ruby gem.

Usage

Starting Out

Run the generator to get the config files

rails g cheddargetter

This will create /config/initializers/cheddargetter_client.rb and /config/cheddargetter.yml Please edit /config/cheddargetter.yml to include your CheddarGetter credentials.

In the model

It can be very simple if you go with the default columns, ie:

:customerCode => :id
:email        => :email,
:firstName    => :first_name,
:lastName     => :last_name,
:planCode     => :plan_code

Then the declaration in the model is simply:

class User < ActiveRecord::Base
 has_subscription
end

These are the only required columns however you can change their names locally very easily.

class User < ActiveRecord::Base
 has_subscription :customerCode => :customer_code,
  :firstName => :name,
  :lastName  => :l_name,
  :email     => :business_email,
  :planCode   => "FREE_PLAN"                   
end

Note that the plan code can also take a string.

The has_subscription will also takes additional key/values of items that appear both in your records for the user and CheddarGetter’s records. For instance zip code is a common one. Here are others:

:ccFirstName
:ccLastName
:ccExpiration
:ccNumber
:ccCountry
:ccAddress
:ccCity
:ccState
:company
:zip

When the save is called on the subscription object or the user it grabs all shared attributes from your ActiveRecord record.

In the controller

Make sure the subscription is always set on the user as some data may only exist there.

class SubscriptionController < ApplicationController
  def edit
    @user = current_user
  end

  def update
    @user = current_user

    if @user.update_attributes(params[:user])
      redirect_to edit_credit_card_path, :flash => {:success => 'Billing information updated'}
    else     
      render 'edit'
    end
  end
end

Or in a user controller

class UsersController < ApplicationController
 def new
  @user = User.new
 end

 def create
  @user = User.new(params[:user])

  if @user.save
   redirect_to after_creation_path, :flash => {:success => 'User successfully created'}
  else     
   render 'new'
  end
 end

 def update
  @user = User.find(params[:id])

  if @user.update_attributes(params[:user])
   redirect_to @user, :flash => {:success => 'User successfully updated'}
  else
   render 'edit'
  end
 end

end

The user save will take care of saving the subscription to CheddarGetter.

In the view

In order to save through the user param it is important to nest the subscription params in the user params with fields for. This is an example of how to set up the form properly.

<%= form_for(@user) do |f| %>
  <%= @user.errors.full_messages.each do |message|%>
    <%= message %>
  <% end %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>
  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>
  <div class="field">
    <%= f.label :plan_code, "User Plan" %><br />
    <%= f.select :plan_code, User::Plans #This is a collection of my plans, ie, [['Free Plan', 'FREE_PLAN'], ['Paid Plan'], ['PAID_PLAN']].  You will need to use your own plans here.
     %> 
  </div>

  The following fields are only required if selecting a paid plan.
  <%= fields_for(:'user[subscription]') do |s| %> #THIS IS THE TRICKY WAY TO NEST THE SUBSCRIPTION PROPERLY.
    <dl>
      <dt>First Name:</dt>
      <dd>
              <%= s.text_field :ccFirstName,:autocomplete => "off" %>
      </dd>

      <dt>Last Name:</dt>
      <dd>
              <%= s.text_field :ccLastName, :autocomplete => "off" %>
      </dd>

      <dt>Card Number:</dt>
      <dd>
              <%= s.text_field :ccNumber,:autocomplete => "off" %>
      </dd>
      <dt>Expiration Date:</dt>
      <dd>
              <%= s.text_field :ccExpiration, :autocomplete => 'off' %>
      </dd>
      <dt>Address:</dt>
      <dd>
              <%= s.text_field :ccAddress, :autocomplete => 'off' %>
      </dd>
      <dt>City:</dt>
      <dd>
              <%= s.text_field :ccCity, :autocomplete => 'off' %>
      </dd>
      <dt>State:</dt>
      <dd>
              <%= s.text_field :ccState, :autocomplete => 'off' %>
      </dd>
      <dt>Zip Code:</dt>
      <dd>
              <%= s.text_field :zip, :autocomplete => 'off' %>
      </dd>
      <dt>Country:</dt>
      <dd>
              <%= s.text_field :ccCountry, :autocomplete => 'off' %>
      </dd>
    </dl>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

You’ll want to user the current_subscription method to get a subscription object with current data. CheddarGetter only stores the last 4 of the credit card. This data is gotten by calling ccLastFour on the subscription object gotten through the current_subscription call.

Contributing to cheddargetter_client_rails

  • Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet

  • Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it

  • Fork the project

  • Start a feature/bugfix branch

  • Commit and push until you are happy with your contribution

  • Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright © 2011 Brent Wooden. See LICENSE.txt for further details.