1

Using the same approach obtained from this solution:

Use both Account and User tables with Devise

I am trying to update an owner_id column on the Account model, after the User has been saved:

Account Model

class Account < ActiveRecord::Base
  has_many :users
  has_secure_token

  accepts_nested_attributes_for :users

  validates :name, :presence => true
end

User Model

class User < ActiveRecord::Base

  after_create :set_account_owner_id
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  belongs_to  :account

  validates :name, :presence => true

  protected

  def set_account_owner_id
    self.account.owner_id = self.id
    self.account.save
  end

end

Accounts Controller

class AccountsController < ApplicationController

  def new
    # Create a new Account and then update owner_id with User profile id
    @account = Account.new
    @account.users.build
  end

  def create
    @account = Account.new(account_params)
    if @account.save
      flash[:success] = "Account successfully created!"
      redirect_to accounts_path
    else
      render 'new'
    end
  end

  private

  def account_params
    params.require(:account).permit(:name, :token, :token_flag, :owner_id, users_attributes: [:name, :email, :password, :password_confirmation, :role])
  end

end

Rspec Test

RSpec.describe Account, type: :model do
  it "should create an Account and a User through accepts_nested_attributes_for" do
    @accountuser = {
      :name => "My App Name",
      :users_attributes => [{
          :name     => "John Doe",
          :email    => "jdoe@email.com",
          :password => "password",
          :password_confirmation => "password",
          :role => "dev",
        }]
      }

    account = Account.create!(@accountuser)
    account.owner_id.should == account.users[0].id
  end
end

The test Fails with the following error:

1) Account should create an Account and a User through accepts_nested_attributes_for
     Failure/Error: account.owner_id.should == account.users[0].id
       expected: 1
            got: nil (using ==)

In reading other threads I thought that the issue was due to the fact I was not invoking 'save' in the after_create, however, I keep getting the same results.

Any insights are appreciated.

Community
  • 1
  • 1
porterhaus
  • 439
  • 2
  • 5
  • 17

1 Answers1

2

In after_create callback it's not guaranteed that you will have an id of record. Use after_commit on: create instead.

So, instead of calling after_create :set_account_owner_id, call:

after_commit :set_account_owner_id, on: :create

Also, remember to add the test_after_commit gem if you are testing code using after_commit. From the after_commit doc:

Note that transactional fixtures do not play well with this feature. Please use the test_after_commit gem to have these hooks fired in tests.

Anand
  • 3,690
  • 4
  • 33
  • 64
dubadub
  • 3,312
  • 3
  • 23
  • 28
  • Dub I'll try both suggestions and let you know. – porterhaus May 25 '15 at 22:40
  • Dub wanted to make sure you got credit. For those who are looking for some additional insight: http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations – porterhaus May 25 '15 at 22:59
  • This got rid of a nasty bug that I was tracking elsewhere. For more on after_commit, see http://apidock.com/rails/ActiveRecord/Transactions/ClassMethods/after_commit – Anand Jul 22 '15 at 03:01