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
[email protected]