【问题标题】:Rails Nested Form Not Saving Nested AttributesRails嵌套表单不保存嵌套属性
【发布时间】:2014-09-06 21:36:13
【问题描述】:

我有以下用户控制器:

class UsersController < ApplicationController

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    @customer = Customer.new

    if @user.save
      flash.notice = "User '#{@user.email}' was succefully created."
      redirect_to user_path(@user)
    else
      render 'new'
    end
  end

  def show
    @user = User.find(params[:id])
  end

  private

  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, customer_attributes: [:id, :company])
  end
end

我有以下用户模型:

class User < ActiveRecord::Base
  has_one :customer
  accepts_nested_attributes_for :customer, :allow_destroy => true
end

以及以下客户模型:

class Customer < ActiveRecord::Base
  belongs_to :user
end

最后是表格:

<%= form_for [@user] do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :email %><br>
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %><br>
    <%= f.password_field :password %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation %><br>
    <%= f.password_field :password_confirmation %>
  </div>
  <%= f.fields_for :customers do |company| %>
    <div class="field">
      <%= company.label :company %><br>
      <%= company.text_field :company %>
    </div>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

当我提交表单时,我在日志中看到:`Unpermitted parameters: customers' 但看来我确实允许这样做。

另外,我想在显示和索引视图中显示每个用户的公司名称。我不知道该怎么做。

我记得过去使用build 方法来获得类似工作的东西,但这次我似乎无法弄清楚。

【问题讨论】:

  • 将“”替换为“”

标签: ruby-on-rails ruby-on-rails-4


【解决方案1】:

除了@Mandeep的回答,让我给你一些进一步的信息:

  1. 您需要为表单“构建”关联对象
  2. 您需要根据您的模型所具有的关联来处理此问题
  3. 您需要根据所述关联保存属性

执行此操作的方法相对简单(由Mandeep 概述)。然而,为什么的原因可能不太明显:


构建

首先,您需要建立关联关联。这一点非常重要,主要是因为 Rails(由于是基于 Ruby 构建的)是一个 object orientated 框架。

面向对象,不涉及太多细节,意味着您使用 Rails 所做的一切都将基于对象。对于我们心爱的 Rails,这意味着每个 Model 都是一个 object

由于这个事实,嵌套模型范例必须在 Rails 中构建,只要您想创建这样的表单。为此,您需要使用build methods - 它告诉ActiveRecord(Rails 的object relational mapper)您有另一个要填充的关联模型/对象:

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def new
      @user = User.new #-> initializes "User" object
      @user.build_customer #-> "builds" the associated object
   end
end

这为 Rails 提供了一组关联数据,它可以使用您的表单填充这些数据(考虑到您调用了正确的方法)

--

协会

其次,您需要考虑您拥有的关联。这很重要,因为在“构建”过程中以不同方式处理单个和多个关联。

您正在使用has_one 关系,这意味着您需要使用单数关联名称(尽管您可以随意调用关联):

如果您使用has_many 关联,则需要使用复数关联方法:

这解释了使用build_customer方法的必要性;但也应该让您有权使用单数关联名称来实现此工作所需的所有方法,即fields_forparams

#app/views/users/new.html.erb
<%= form_for @user do |f| %>
  ...
  <%= f.fields_for :customer do |c| %>
      ...
  <% end %>

  <%= f.submit %>
<% end %>

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def create
      @user = User.new user_params
      @user.save
   end

   private

   def user_params
      params.permit(:user).permit(:user, :params, customer_attributes: [:x. :y])
   end

end

--

保存

上面的控制器代码会保存你需要的属性。

您必须了解,传递 nested 属性意味着您发送关联数据的模型需要从属于您的“主”模型。正如最初讨论的那样,模型中的ActiveRecord associations 会发生这种情况。

希望这能让你更清楚

【讨论】:

    【解决方案2】:

    将您的代码更改为:

    def new
      @user = User.new
      @user.build_customer
    end
    

    您的表格:

    <%= form_for @user do |f| %>
      // user fields
      <%= f.fields_for :customer do |customer| %> 
        // customer fields
      <% end %>
    <% end %>   
    

    您的 create 方法中也不需要 @customer = Customer.new。

    【讨论】:

    • 我可以编辑你的代码吗?最好不要使用 @customer 变量 imo
    • @RichPeck 当然,但它是 has_one 关系,所以它会有所作为吗?我的意思是,如果您要构建多个关联的属性,那么符号是要走的路,但对于 has_one? :)
    • @RichPeck 啊,我看到你保存了一个实例变量:)
    • @RichPeck 仅与变量有关还是还有其他问题?
    • 只有 var - 我正在写一个更全面的答案来解释事情;但你的会让它为他工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    相关资源
    最近更新 更多