Rails - 在保存到数据库之前更新嵌套属性

时间:2012-06-06 16:49:36

标签: ruby-on-rails-3 nested-forms

Stackoverflow的长期读者,但从未发现自己能够提出问题(尚未得到回答)。我想这是第一次所有的事情,所以在这里... ...

系统信息
Ruby Version = 1.8.7
Rails Version = 3.2.2

情况:
我们有一个具有用户注册系统的应用程序。为了正确地连接和填充我们的所有表,我们在注册视图中使用复杂/嵌套表单。我实际上已经完美地运行了嵌套表单,所有内容都应该填充,真的非常棒。

问题在于:我需要在表单发布之后设置其中一个嵌套属性的值,但是在保存记录之前。

这是一个快速示例,因此您可以更好地了解我正在谈论的内容: 用户在我们的网站上注册。当他们注册记录时,在用户数据表中创建。每个用户也被归类为team_mate(联接表)并分配给他们自己的个人团队(首先)。但是,“团队”(表)中还有一个“别名”字段,在用户的初始创建时,我们希望将其设置为用户的名字(无需让他们将名字输入'别名'表单上的字段)。

所以,我想问题是:如何在表单发布之后和将记录保存到数据库之前手动设置嵌套属性的值?

表模式的(简单)示例如下:

用户(id,first_name,last_name,created_at,updated_at)

Team_mates(id,user_id,team_id,created_at,updated_at) - 连接表

团队(id,别名,created_at,updated_at)

型号:

User.rb

class User < ActiveRecord::Base
  has_many :team_mates, :dependent => :destroy
  has_many :teams, :through => :team_mates, :foreign_key => :team_id
  accepts_nested_attributes_for :team_mates, :allow_destroy => true

  before_save :set_defaults

  private
    def set_defaults
      #want to set :users => :team_mates_attributes => :team_attributes => :alias to @user.first_name here

      # Would prefer to handle this here instead of in the controller.
    end
  end

Team.rb

class Team < ActiveRecord::Base
  has_many :team_mates, :dependent => :destroy
  has_many :users, :through => :team_mates, :foreign_key => :user_id

end

Team_mate.rb

class TeamMate < ActiveRecord::Base
  belongs_to :user
  belongs_to :team

  accepts_nested_attributes_for :team, :allow_destroy => true
end

控制器

Users_controller.rb

class UsersController < ApplicationController

def new
  @user = User.new
  @user.emails.build(:is_default_email => 1)
  @user.build_login

  @user.team_mates.build.build_team(:alias => 'Clinton444', :created_at => Time.new, :updated_at => Time.new)

  respond_to do |format|
    format.html
    format.json { render :json => @match }
  end
end

def create
  @user = User.new(params[:user])

  @user.attributes = ({ "user" => { "team_mates" => { "team" => { "alias" => @user.first_name } } } }) #--this doesn't work...

  @user.attributes = ({ :user => { :team_mates => { :team => { :alias => @user.first_name } } } }) #--neither does this...


  respond_to do |format|
    if @user.save
      format.html  { redirect_to(@user, :notice => 'User was successfully created.') }
      format.json  { render :json => @user, :status => :created, :location => @user }
    else
      format.html  { render :action => "new" }
      format.json  { render :json => @user.errors, :status => :unprocessable_entity }
    end
  end
end

查看

new.html.haml

  = form_for(@user, :html => {:class => '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 => "control-label"
  .controls
    =f.text_field :first_name, :class => "span8"

.control-group
  = f.label :last_name, :class => "control-label"
  .controls
    =f.text_field :last_name, :class => "span8"

= f.fields_for :emails do |e|
  =e.hidden_field :is_default_email, :class => "span8"

  .control-group
    = e.label :email, :class => "control-label"
    .controls
      =e.text_field :email, :class => "span8"

= f.fields_for :team_mates do |tm|
  = tm.fields_for :team do |t|
    =t.hidden_field :alias, :class => "span8"
    =t.hidden_field :created_at, :class => "span8"
    =t.hidden_field :updated_at, :class => "span8"

= f.fields_for :login do |e|
  .control-group
    = e.label :user_login, :class => "control-label"
    .controls
      =e.text_field :user_login, :class => "span8"

  .control-group
    = e.label :password_encrypted, :class => "control-label"
    .controls
      =e.text_field :password_encrypted, :class => "span8"

.control-group
  .controls
    =f.submit :class => 'btn btn-primary btn-medium'

最后

表单帖子上的Rails服务器输出

  Parameters: {"user"=>{"team_mates_attributes"=>{"0"=>{"team_attributes"=>{"created_at"=>"Wed Jun 06 09:52:19 -0600 2012", "alias"=>"asfs444", "updated_at"=>"Wed Jun 06 09:52:19 -0600 2012"}}}, "first_name"=>"lkjlkjlsdfslkjeowir", "last_name"=>"ouisodifuoixv", "emails_attributes"=>{"0"=>{"is_default_email"=>"1", "email"=>"lpisfsopf@psflsjdk.com"}}, "login_attributes"=>{"user_login"=>"lkjsdfooiusfd", "password_encrypted"=>"[FILTERED]"}}, "utf8"=>"✓", "commit"=>"Create User", "authenticity_token"=>"CQLQ93/0VlncSzMlmtLPHgaVrrvjuHFN+lN6CYCsiR8="}

请注意:我非常擅长使用轨道。此外,我已经在论坛中搜索了这样一个问题的答案。我找到了一些类似的,但是当我测试它们时,它们都没有用。

最后,在查看模型之后,您可能想知道电子​​邮件/登录的来源。它们是在我们系统的模型中构建的,但实际上并不是这个问题的一部分,所以我省略了它们的代码。他们正在工作,所以问题不在于那一方。

无论如何,感谢您的时间,如果您需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:0)

检查http://archives.ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes

  

支持新对象的创建和编辑   现有的我们必须使用一对多的哈希数组   关联或一对一关联的单个哈希。如果没有:id   属性存在然后假定它代表嵌套模型   创建

不是100%肯定..我之前没有使用\测试过,但这应该给你一个想法

@user.teams.each do |team| 
  team.team_mates do |team_mate|
    # To edit existing
    team_mate.team_attributes = [ { :id => team.id,  :alias => @user.first_name } ]

    # To create new
    team_mate.team_attributes = [ { :alias => @user.first_name } ]

    team_mate.save
  end 
end