I am guessing the PaidAccount
contains a lot of extra attributes for a paid-account, including aspecification of the account-plan, which is a list of available plans. So your relation should look like
class PaidAccount < ActiveRecord::Base
belongs_to :account_plan
end
(which means that the PaidAccount
has a attribute account_plan_id
)
There are two approaches: use a nested form, or use something more ad hoc.
Using a nested form
I am using simple_form
and haml
--> please check into that, makes the code a lot easier to write and show :)
So in that case, I would do the following:
class User
has_one :paid_account
has_one :account_plan, through: :paid_account
accepts_nested_attributes_for :paid_account
end
Because we are not creating a new account_plan
, we are linking to an existing one.
Your form would simply become:
= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { id: "payment-form" }) do |f|
= f.simple_fields_for :paid_account do |pa|
= pa.association :account_plan
The problem with this approach: when do you create the paid_account
, a bit hard to tell without seeing the rest of your code. I see two options:
- you only want to create it when an account-plan is chosen.
- or you allow users only to select an account-plan, when they already have decided to be paying (and you can already create the
PaidAccount
object).
I am guessing it is the first option. For the nested form to work, you will always have to create the nested PaidAccount
and delete it when saving when the account-plan is not filled in. That is actually easy to do, so we add
accepts_nested_attributes_for :paid_account, reject_if: :blank
And your controller new
action should become:
def new
@account_plans = AccountPlan.order(:price)
build_resource({})
resource.build_paid_account
respond_with self.resource
end
Also note you will have to correctly specify your strong parameters, so your permits
should look something like
def post_params
params.require(:user).permit(:email, :password, :paid_account_attributes => [:account_path_id])
end
The more ad hoc approach
- use the view as you had before
- allow the
account_plan
in yourpost_params
(as above) - check the value of
account_plan
in the create action, and build aPaidAccount
with the correct account plan if needed.
So your create
action would look like
def create
account_plan_id = params[:user].delete(:account_plan)
super
if account_plan_id.present?
resource.build_paid_account(account_plan_id: account_plan_id)
end
Stripe.api_key = Rails.configuration.stripe_secret_key
Stripe::Customer.create(
card: params[:stripeToken],
description: resource.email
)
end