Hi,
I have a situation I’m hoping someone out there may be able to shed some light on. I have a Rails app (2.1.0 on Ruby 1.8.7) with a wizard-based sign up process, that has recently been changed from storing incremental data in the database to having a medium sized object graph living in the user session until the user completes the entire sign up process (this is a business requirement now). After the user commits all relevant data, I’m now calling save! on the top-level object to save all the rows at once. However, when the call to save! happens–and because I have two objects that have a belongs_to association, each pointing to other in addition to the normal bidirectional association–I end up in an endless validation loop. Funny thing is, when I was incrementally saving the data, this issue never arose–another way to put it, those relationships never caused a problem when saving/retrieving already-existing rows.
In the model tier, I have the following classes defined:
class PrimaryAccount < Account has_many :payment_methods, :foreign_key => “account_id” #using single table inheritance, which is why foreign key is not “primary_account_id” belongs_to :current_payment_method, :class_name => “PaymentMethod”, :foreign_key => “current_payment_method_id” #points to same table, so I can have many payment_methods, but also mark as being the current one to bill …
class PaymentMethod < ActiveRecord::Base belongs_to :account #normal bidirectional association …
class CreditCard < PaymentMethod …
In the controller tier, I have a session object that–on the final step–loads an Account model object based on the current session state, and then calls save! on that model:
class PrimaryAccountUser < User
attr_reader :credit_card
def initialize(service_id) @credit_card = {} #hash for storing credit card attributes end
def persist_to_database add_session_data_to_account(PrimaryAccount.new) account.save! @id = account.id return account end
private
def add_session_data_to_account(account) #adds the impl-specific things to the account
if(!@credit_card.blank?)
card = CreditCard.new do |cc|
cc.account_type = @credit_card[:type]
cc.account_name = @credit_card[:name]
cc.account_number = @credit_card[:number]
cc.cvv = @credit_card[:cvv]
cc.account_expiration = @credit_card[:expiration]
cc.address = @credit_card[:address]
cc.city = @credit_card[:city]
cc.state = @credit_card[:state]
cc.zip = @credit_card[:zip]
cc.country = @credit_card[:country]
cc.phone = @credit_card[:phone]
end
#strange...this won't populate the account_id on save!
account.payment_methods << card
#again, if I don't do this, then the payment_method won't have a populated account_id on save!
card.account = account
#doing this causes the endless validation loop
account.current_payment_method = card
end
return account
end
Am I crazy for thinking this ought to work?
Thanks in advance,
Ryan Frith ralafapa@gmail.com