Rails不保存嵌套属性

时间:2017-03-09 18:56:51

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

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

当我提交表单时,它保存任务但不保存相关的TaskItems。我没有看到我错过了什么,因为我搜索了很多这个问题并且似乎没有任何效果。请看下面的代码。

型号:

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>

1 个答案:

答案 0 :(得分:2)

您需要在类Task:

中的echo $m->a.",".$m->b.",".$m->c.","; 方法中添加inverse_of选项
has_many

这是由于在创建新的TaskItem实例时,它要求Task实例已存在于数据库中以便能够获取Task实例的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 。使用此选项,它会跳过验证。

您可以阅读post关于id选项及其用例的信息。

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

查看代码:

has_many

控制器代码:

<%= 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 %>