I did generated devise controllers and views and defined both User and Account models like the following:
User
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:confirmable, :lockable, :timeoutable, :trackable,
:omniauthable, omniauth_providers: [ :google_oauth2 ]
has_one :account, autosave: true, dependent: :destroy, inverse_of: :user
before_validation :set_account
enum :role, { basic: 0, admin: 1, courier: 2, client: 3 }
def set_account
self.build_account
end
accepts_nested_attributes_for :account
end
Account
class Account < ApplicationRecord
belongs_to :user, autosave: true
end
Strong parameter config
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_signup_parameters, only: :create
.
.
.
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_signup_parameters
added_attrs = [ :first_name,
:last_name,
:name,
:email,
:password,
:password_confirmation,
:card_name,
:card_number,
:card_cvv,
:card_expiration_month,
:card_expiration_year,
account_attributes: [
:name,
:plan,
:plan_discount_pct,
:plan_period,
:plan_price,
:tier
]
]
devise_parameter_sanitizer.permit(:sign_up, keys: added_attrs)
end
end
In the logs you can see that the data for the nested attributes are there but following that you see rails creating the Account with all empty values:
Processing by Users::RegistrationsController#create as HTML
Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>**{"account_attributes"=>{"tier"=>"corporate", "plan"=>"SMB", "name"=>"Batman", "plan_period"=>"GoldAnnual"}**, "first_name"=>"Bruce", "last_name"=>"Wayne", "name"=>"Batman", "email"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "card_name"=>"Bruce Wayne", "card_number"=>"[FILTERED]", "card_expiration_month"=>"[FILTERED]", "card_expiration_year"=>"[FILTERED]", "card_cvv"=>"[FILTERED]", "save"=>"1", "commit"=>"Submit"}
TRANSACTION (0.2ms) BEGIN /*action='create',application='Freighteen',controller='registrations'*/
User Exists? (6.5ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1 /*action='create',application='Freighteen',controller='registrations'*/
CACHE User Exists? (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
User Create (0.5ms) INSERT INTO "users" ("email", "encrypted_password", "reset_password_token", "reset_password_sent_at", "remember_created_at", "sign_in_count", "current_sign_in_at", "last_sign_in_at", "current_sign_in_ip", "last_sign_in_ip", "confirmation_token", "confirmed_at", "confirmation_sent_at", "unconfirmed_email", "failed_attempts", "unlock_token", "locked_at", "created_at", "updated_at", "name", "first_name", "last_name", "role")
VALUES ('[email protected]', '$2a$12$MoG2NgRuikEE9yEMguK4iOybH7MN3BmDRS6sf78SUNJpK.rx9z3Cu', NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, 'sGBMeBMesDm-2h3j9Jcj', NULL, '2025-01-05 04:41:22.332196', NULL, 0, NULL, NULL, '2025-01-05 04:41:22.331966', '2025-01-05 04:41:22.331966', 'Batman', 'Bruce', 'Wayne', 0) RETURNING "id" /*action='create',application='Freighteen',controller='registrations'*/
**Account Create (0.6ms) INSERT INTO "accounts" ("user_id", "created_at", "updated_at", "tier", "plan", "plan_period", "plan_discount_pct", "plan_price", "name") VALUES (11, '2025-01-05 04:41:22.341682', '2025-01-05 04:41:22.341682', NULL, NULL, NULL, NULL, 0.0, NULL) RETURNING "id"**
Note that account attributes are present but don't get created.
What am I missing? I didn't think I have to build manually given the configuration.
self.build_account.before_validation :set_account,def set_account self.build_account end. why do you have this? it's not needed.plan_idof an existing plan. In addition this will avoid denormalization.