【问题标题】:Rails not saving nested attributesRails 不保存嵌套属性
【发布时间】:2017-03-09 18:56:51
【问题描述】:

我有表任务和项目。我有一个 Item 表格,我在其中记录了我的 Tasks 可能拥有的所有可能的项目,它工作正常。然后我有一个任务表单,其中所有项目都显示在一个字段旁边,以便为每个项目设置成本值。这将导致 Task 和 Item 之间的连接:TaskItem(此表包含 task_id、item_id 和 cost)。

当我提交表单时,它保存的是任务,而不是关联的任务项。我没有看到我缺少什么,因为我搜索了很多这个问题,但似乎没有任何效果。请看下面的代码。

型号:

class Task < ApplicationRecord
    has_many :task_items
    has_many :items, :through => :task_items

    accepts_nested_attributes_for :task_items, :allow_destroy => true
end

class Item < ApplicationRecord
    has_many :task_items
    has_many :tasks, :through => :task_items
end

class TaskItem < ApplicationRecord
    belongs_to :task
    belongs_to :item

    accepts_nested_attributes_for :item, :allow_destroy => true
end

控制器:

def new
    @items = Item.all

    @task = Task.new
    @task.task_items.build
end

def create
    @task = Task.new(task_params)
    @task.save
    redirect_to action: "index"
end

private def task_params
    params.require(:task).permit(:id, :title, task_items_attributes: [:id, :item_id, :cost])
end

我的看法:

<%= form_for :task, url:tasks_path do |f| %>
<p>
    <%= f.label :title %><br>
    <%= f.text_field(:title, {:class => 'form-control'}) %><br>
</p>

<% @items.each do |item| %>
    <% @task_items = TaskItem.new %>
    <%= f.fields_for :task_items do |ti| %>
        <%= ti.label item.description %>
        <%= ti.text_field :cost %>
        <%= ti.hidden_field :item_id, value: item.id %>
    <% end %>
<% end %>

<p>
    <%= f.submit({:class => 'btn btn-primary'}) %>
</p>

【问题讨论】:

  • 当您尝试保存 TaskItem 时,日志输出是什么?
  • 使用纯渲染:params[:task].inspect 我得到了这个:<:parameters>"Teste 1", "task_items"=>{"item_id"=> "4", "cost"=>"55"}} 允许:false>
  • "task"=>{"title"=>"Teste565656", "task_items"=>{"item_id"=>"4", "cost"=>"55"}}, " commit"=>"Save Contato"} 不允许的参数:task_items (0.0ms) begin transaction SQL (21.0ms) INSERT INTO "tasks" ("title", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "Teste565656"], ["created_at", 2017-03-09 19:31:41 UTC], ["updated_at", 2017-03-09 19:31:41 UTC]] ( 122.5ms) 提交事务重定向到localhost:3000
  • 您的 task_params 错误中有一个错误:根据您视图中的代码,它应该声明 :cost 而不是 :valor
  • 抱歉,task_params 已修复,但这不是问题的原因。不知何故 task_items_attributes 在保存我的任务时没有被理解。

标签: ruby-on-rails ruby nested-attributes fields-for


【解决方案1】:

您需要在Task类的has_many方法中添加inverse_of选项:

class Task < ApplicationRecord
  has_many :task_items, inverse_of: :task
  has_many :items, through: :task_items

  accepts_nested_attributes_for :task_items, :allow_destroy => true
end

这是由于在创建新的TaskItem 实例时,它要求Task 实例已经存在于数据库中,才能获取Task 实例的id。使用此选项,它会跳过验证。

您可以阅读此post 关于inverse_of 选项及其用例。

fields_for 有一个选项来指定要存储信息的对象。这与从 has_many 集合构建每个 TaskItem 相结合,应确保正确设置所有关系。

查看代码:

<%= form_for @task do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field(:title, {:class => 'form-control'}) %><br>
  </p>

  <% @items.each do |item| %>
    <% task_item = @task.task_items.build %>
    <%= f.fields_for :task_items, task_item do |ti| %>
      <%= ti.label item.description %>
      <%= ti.text_field :cost %>
      <%= ti.hidden_field :item_id, value: item.id %>
    <% end %>
  <% end %>

  <p>
    <%= f.submit({:class => 'btn btn-primary'}) %>
  </p>  
<% end %>

控制器代码:

def index
end

def new
  @items = Item.all
  @task = Task.new
end

def create
  @task = Task.new(task_params)
  @task.save
  redirect_to action: "index"
end

private

def task_params
  params.require(:task).permit(:id, :title, task_items_attributes: [:id, :item_id, :cost])
end

【讨论】:

  • 我的日志中仍然显示“Unpermitted parameter: task_items”,并且未创建 task_items。我应该在其他任何地方使用 inverse_of 吗?我是否正确使用了 _attributes?非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多