如何为具有多对多关系的三个模型制作表单

时间:2013-09-16 14:19:24

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

为具有多对多关系的模型创建表单的最佳方法是什么?

详细说明:

我有3个模型:User,Task,TaskAssignment:


用户模型

class User < ActiveRecord::Base   
  has_many :task_assignments
  has_many :tasks, through: :task_assignments
end

任务模型

class Task < ActiveRecord::Base
  has_many :task_assignments
  has_many :users, through: :task_assignments
end

TaskAssignment模型(加入表格)

我无法使用has_and_belongs_to_many,因为我需要在TaskAssignment模型中添加其他字段。

class TaskAssignment < ActiveRecord::Base
  belongs_to :task
  belongs_to :user
end

通过创建一个新任务,应该可以为一个任务分配多个用户,所以我创建了这个表单视图:

任务编辑表单视图

<%= form_for(@task) do |f| %>
  <div class="field">
    <%= f.label :note %><br>
    <%= f.text_field :note %>
  </div>

  <select name="task[users]" size="5" multiple>
    <% @users.each do |user| %>
      <option value="<%= user.id %>"><%= user.email %></option>
    <% end %>
  </select>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

现在,我想知道如何继续使用我的控制器:

任务控制器

  def create
    @task = Task.new(task_params)

    respond_to do |format|
      if @task.save
        format.html { redirect_to @task, notice: 'Task was successfully created.' }
        format.json { render action: 'show', status: :created, location: @task }
      else
        format.html { render action: 'new' }
        format.json { render json: @task.errors, status: :unprocessable_entity }
      end
    end
  end

我想我必须做那样的事情:

@task = Task.new(task_params)
users = ???
@task.users << users

  1. 是应该保存n:m数据的方式还是有其他魔术轨道功能?
  2. 如何从选择框中获取数据?我尝试通过将选择框的名称设置为name="task[users]"来接收它们,但变量task_params仅包含note - 字段

2 个答案:

答案 0 :(得分:1)

您无需以任何特殊方式保存对象。请记住在:user_ids => []中允许task_params

此外,使用表单助手collection_select可能会让您的生活更轻松。

<%= f.collection_select :user_ids, @users, :id, :email, {}, { :multiple => true, :size => 5 } %>

答案 1 :(得分:1)

有一个名为accepts_nested_attributes_for的帮助器,允许父对象创建和更新其嵌套对象。在这种情况下,您希望Task能够创建和更新TaskAssignment

首先,允许Task接受其孩子的属性并为其分配属性。

class Task < ActiveRecord::Base
  has_many :task_assignments
  has_many :users, through: :task_assignments

  accepts_nested_attributes_for :task_assignments
end

这应该指向正确的方向。创建表单看起来就像在fields_for for one-to-many中解释的那样。