I’m building a web site with a subscription-based payment system using ActiveMerchant. The first rule is, don’t put any user financial information into your local database, just pass the user input to your payment system (i.e. Pay Pal, Authorize.net, etc.). So how do you handle this information? attr_accessor to the rescue. You can have something like this:

class Subscription < ActiveRecord::Base
belongs_to :user
has_many :transactions, :class_name => "SubscriptionTransaction"

attr_accessor :card_number, :card_verification, :card_type, :ip_address
attr_accessor :address1, :address2, :city, :state, :zip

# more stuff


Now you can work with the users credit card number (as just one example) without commiting it to the Subscription table.

But – one thing you need is the card expiration date. You can get that information from the user in a drop down menu in the view:

<%= f.label :card_expires_on %><br />
<%= f.date_select :card_expires_on, :start_year => Date.today.year, :end_year => (Date.today.year+10), :add_month_numbers => false, :discard_day => true %>

This is a multiparameter situation, and it won’t work when :card_expires_on is a virtual attribute. Here’s the Rails Lighthouse ticket number 2675

There are some workarounds, but they seem to be pretty clumsy. Ultimately, I added :card_expires_on to the Subscription model. Without the card number, it’s not particularly dangerous, but I still don’t like it much.

The funny thing is, I always assume that when I hit something like this, it’s a programming error on my part. It’s actually pretty rare for me to hit a real Rails bug, which attests to the high quality of the code.