title: Update nested attributes before saving to database
body: <p>Long time reader of Stackoverflow but have never found myself in a position to ask a question (that hasn't already been answered).  I guess there's a first time for everything so here it goes...</p>
  
  <p><strong>System Info:</strong> <br />
  Ruby Version = 1.8.7 <br />
  Rails Version = 3.2.2</p>
  
  <p><strong>Situation:</strong><br />
  We have an application with a user registration system in place.  In order to hook up and populate all of our tables correctly, we are utilizing Complex/Nested Forms within the registration view.  I actually have the nested forms working perfectly, everything is being populated as it should, its awesome really.</p>
  
  <p>Here is the problem:  I need to set one of the value of one of the nested attributes AFTER the form post but BEFORE the records are saved.</p>
  
  <p>Here is a quick example so you can see what I'm talking about a little bit better:
  A user registers with our site.  When they register a record is created in the Users data table.  Each user is also classified as a team_mate (join table) and assigned to their very own individual team (at first).  But, a 'team' (table) also has an 'alias' field in it which, on the initial creation of the user we would like to set to the users first name (without having to have them enter their first name into an 'alias' field on the form). </p>
  
  <p><strong>So, I guess the question would be:</strong>  How to I manually set the value of a nested attribute after the form post and before the records are saved to the database?</p>
  
  <p>A (simplistic) example of the table schema looks is as follows:<br /></p>
  
  <p>Users (id, first_name, last_name, created_at, updated_at)</p>
  
  <p>Team_mates(id, user_id, team_id, created_at, updated_at) - join table</p>
  
  <p>Teams(id, alias, created_at, updated_at)  </p>
  
  <p><strong>Models:</strong></p>
  
  <p>User.rb</p>
  
  <pre><code>class User &lt; ActiveRecord::Base
    has_many :team_mates, :dependent =&gt; :destroy
    has_many :teams, :through =&gt; :team_mates, :foreign_key =&gt; :team_id
    accepts_nested_attributes_for :team_mates, :allow_destroy =&gt; true
  
    before_save :set_defaults
  
    private
      def set_defaults
        #want to set :users =&gt; :team_mates_attributes =&gt; :team_attributes =&gt; :alias to @user.first_name here
  
        # Would prefer to handle this here instead of in the controller.
      end
    end
  </code></pre>
  
  <p>Team.rb</p>
  
  <pre><code>class Team &lt; ActiveRecord::Base
    has_many :team_mates, :dependent =&gt; :destroy
    has_many :users, :through =&gt; :team_mates, :foreign_key =&gt; :user_id
  
  end
  </code></pre>
  
  <p>Team_mate.rb</p>
  
  <pre><code>class TeamMate &lt; ActiveRecord::Base
    belongs_to :user
    belongs_to :team
  
    accepts_nested_attributes_for :team, :allow_destroy =&gt; true
  end
  </code></pre>
  
  <p><strong>Controller</strong></p>
  
  <p>Users_controller.rb</p>
  
  <pre><code>class UsersController &lt; ApplicationController
  
  def new
    @user = User.new
    @user.emails.build(:is_default_email =&gt; 1)
    @user.build_login
  
    @user.team_mates.build.build_team(:alias =&gt; 'Clinton444', :created_at =&gt; Time.new, :updated_at =&gt; Time.new)
  
    respond_to do |format|
      format.html
      format.json { render :json =&gt; @match }
    end
  end
  
  def create
    @user = User.new(params[:user])
  
    @user.attributes = ({ "user" =&gt; { "team_mates" =&gt; { "team" =&gt; { "alias" =&gt; @user.first_name } } } }) #--this doesn't work...
  
    @user.attributes = ({ :user =&gt; { :team_mates =&gt; { :team =&gt; { :alias =&gt; @user.first_name } } } }) #--neither does this...
  
  
    respond_to do |format|
      if @user.save
        format.html  { redirect_to(@user, :notice =&gt; 'User was successfully created.') }
        format.json  { render :json =&gt; @user, :status =&gt; :created, :location =&gt; @user }
      else
        format.html  { render :action =&gt; "new" }
        format.json  { render :json =&gt; @user.errors, :status =&gt; :unprocessable_entity }
      end
    end
  end
  </code></pre>
  
  <p><strong>View</strong></p>
  
  <p>new.html.haml</p>
  
  <pre><code>  = form_for(@user, :html =&gt; {:class =&gt; 'form-horizontal'}) do |f|
  - if @user.errors.any?
    .alert
      %h2
        = pluralize(@user.errors.count, "error")
        prohibited this post from being saved:
      %ul
        - @user.errors.full_messages.each do |msg|
          %li
            = msg
  %fieldset
  .control-group
    = f.label :first_name, :class =&gt; "control-label"
    .controls
      =f.text_field :first_name, :class =&gt; "span8"
  
  .control-group
    = f.label :last_name, :class =&gt; "control-label"
    .controls
      =f.text_field :last_name, :class =&gt; "span8"
  
  = f.fields_for :emails do |e|
    =e.hidden_field :is_default_email, :class =&gt; "span8"
  
    .control-group
      = e.label :email, :class =&gt; "control-label"
      .controls
        =e.text_field :email, :class =&gt; "span8"
  
  = f.fields_for :team_mates do |tm|
    = tm.fields_for :team do |t|
      =t.hidden_field :alias, :class =&gt; "span8"
      =t.hidden_field :created_at, :class =&gt; "span8"
      =t.hidden_field :updated_at, :class =&gt; "span8"
  
  = f.fields_for :login do |e|
    .control-group
      = e.label :user_login, :class =&gt; "control-label"
      .controls
        =e.text_field :user_login, :class =&gt; "span8"
  
    .control-group
      = e.label :password_encrypted, :class =&gt; "control-label"
      .controls
        =e.text_field :password_encrypted, :class =&gt; "span8"
  
  .control-group
    .controls
      =f.submit :class =&gt; 'btn btn-primary btn-medium'
  </code></pre>
  
  <p><strong>And finally</strong></p>
  
  <p>Rails server output on form post</p>
  
  <pre><code>  Parameters: {"user"=&gt;{"team_mates_attributes"=&gt;{"0"=&gt;{"team_attributes"=&gt;{"created_at"=&gt;"Wed Jun 06 09:52:19 -0600 2012", "alias"=&gt;"asfs444", "updated_at"=&gt;"Wed Jun 06 09:52:19 -0600 2012"}}}, "first_name"=&gt;"lkjlkjlsdfslkjeowir", "last_name"=&gt;"ouisodifuoixv", "emails_attributes"=&gt;{"0"=&gt;{"is_default_email"=&gt;"1", "email"=&gt;"lpisfsopf@psflsjdk.com"}}, "login_attributes"=&gt;{"user_login"=&gt;"lkjsdfooiusfd", "password_encrypted"=&gt;"[FILTERED]"}}, "utf8"=&gt;"✓", "commit"=&gt;"Create User", "authenticity_token"=&gt;"CQLQ93/0VlncSzMlmtLPHgaVrrvjuHFN+lN6CYCsiR8="}
  </code></pre>
  
  <p>After looking at the models you might be wondering where emails/logins are coming from.  They're built within the model on our system, but are not really part of this question so I omitted the code for them.  They are working, so the problem isn't on that side.</p>