Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Active Record: Calling Build Method Should Not Save To Database Before Calling Save Method

I have a simple user model

class User < ActiveRecord::Base
    has_one :user_profile
end

And a simple user_profile model

class UserProfile < ActiveRecord::Base
    belongs_to :user
end

The issue is when I call the following build method, without calling the save method, I end up with a new record in the database (if it passes validation)

class UserProfilesController < ApplicationController

def create
        @current_user = login_from_session
        @user_profile = current_user.build_user_profile(params[:user_profile])
       #@user_profile.save (even with this line commented out, it still save a new  db record)
        redirect_to new_user_profile_path

end

Anyyyyyy one have anyyy idea what's going on.

The definition of this method says the following but it's still saving for me

build_association(attributes = {})

    Returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key, but has not yet been saved.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_one

like image 962
dmillion Avatar asked Feb 22 '23 11:02

dmillion


1 Answers

Ok, I'm sure experienced vets already know this, but as a rookie I had to figure it out the long way...let me see if I can explain this without screwing it up

Although I was not directly saving the user_profile object, I noticed in my logs that something was updating the user model's last_activity_time (and the user_profile model) each time I submitted the form (the user model's last_activity date was also updated when the logged in user did various other things too - I later realized this was set in the Sorcery gem configuration).

Per http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html AutosaveAssociation is a module that takes care of automatically saving associated records when their parent is saved. In my case, the user mode is the parent and the scenario they provide below mirrors my experience.

class Post
  has_one :author, :autosave => true
end 

post = Post.find(1)
post.title       # => "The current global position of migrating ducks"
post.author.name # => "alloy"

post.title = "On the migration of ducks"
post.author.name = "Eloy Duran"

post.save
post.reload
post.title       # => "On the migration of ducks"
post.author.name # => "Eloy Duran"

The following resolutions resolved my problem 1. Stopping Sorcery (config setting) from updating the users last_activity_time (for every action) or 2. Passing an ':autosave => false' option when I set the association in the user model as follows

class User < ActiveRecord::Base
    has_one :user_profile, :autosave => false
end
like image 170
dmillion Avatar answered May 18 '23 15:05

dmillion