# Responsible for handling the combo User/Account creation. Also deals with # Account creation when signing in as an existing User. class Signup extend ActiveModel::Naming include ActiveModel::Conversion include ActiveModel::Validations FIELDS = { :account => { :name => :account_name, :keyword => :keyword, :cardholder_name => :cardholder_name, :billing_email => :billing_email, :card_number => :card_number, :expiration_month => :expiration_month, :expiration_year => :expiration_year, :verification_code => :verification_code, :plan => :plan }, :user => { :name => :user_name, :email => :email, :password => :password, :password_confirmation => :password_confirmation, } }.freeze attr_accessor :account_name, :keyword, :user_name, :billing_email, :password, :password_confirmation, :cardholder_name, :email, :card_number, :expiration_month, :expiration_year, :plan, :verification_code def initialize(attributes = {}) if attributes attributes.each do |attribute, value| send(:"#{attribute}=", value) end end @check_password = true end # used by ActiveModel def persisted? false end def save delegate_attributes_for(:account) delegate_attributes_for(:user) unless existing_user if valid? begin save! true rescue ActiveRecord::RecordNotSaved delegate_errors_for(:account) delegate_errors_for(:user) false end else false end end def account @account ||= Account.new end def user existing_user || new_user end def user=(signed_in_user) @check_password = false @existing_user = signed_in_user end def new_user @new_user ||= User.new end def existing_user @existing_user ||= User.find_by_email(email) end def membership @membership ||= Membership.new(:user => user, :account => account, :admin => true) end def valid? errors.clear validate errors.empty? end def email_confirmed? user.email_confirmed? end private def delegate_attributes_for(model_name) FIELDS[model_name].each do |target, source| send(model_name).send(:"#{target}=", send(source)) end end def delegate_errors FIELDS.each do |model_name, fields| delegate_errors_for(model_name, fields) end end def delegate_errors_for(model_name) fields = FIELDS[model_name] send(model_name).errors.each do |field, message| errors.add(fields[field], message) end end def validate account.valid? delegate_errors_for(:account) if existing_user validate_existing_user else validate_new_user end end def validate_new_user new_user.valid? delegate_errors_for(:user) end def validate_existing_user if @check_password && !existing_user.authenticated?(password) errors.add(:password, "is incorrect") end end def save! Account.transaction do account.save! user.save! membership.save! end end end