与has_many的Simple_Form关联:通过额外字段

时间:2012-10-11 05:03:50

标签: ruby-on-rails ruby-on-rails-3 associations has-many-through simple-form

我有两个模型,开发人员和任务,

class Developer < ActiveRecord::Base
  attr_accessible :address, :comment, :email, :name, :nit, :phone, :web
  has_many :assignments
  has_many :tasks, :through => :assignments
end

class Task < ActiveRecord::Base
  attr_accessible :description, :name, :sprint_id, :developer_ids
  has_many :assignments
  has_many :developers, :through => :assignments
end

class Assignment < ActiveRecord::Base
  attr_accessible :accomplished_time, :developer_id, :estimated_time, :status, :task_id
  belongs_to :task
  belongs_to :developer
end

我通过添加一个Assignment表来处理这个关系,所以我可以特别添加许多开发人员到一个任务,现在我也希望能够操作我添加到加入表中的其他字段,如&# 39;估计时间&#39;,&#39; completed_time&#39; ...等...我在Simple_form上得到的是 `

<%= simple_form_for [@sprint,@task], :html => { :class => 'form-horizontal' } do |f| %>
  <%= f.input :name %>
  <%= f.input :description %>
  <%= f.association :developers, :as => :check_boxes %>

  <div class="form-actions">
    <%= f.button :submit, :class => 'btn-primary' %>
    <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
                project_sprint_path(@sprint.project_id,@sprint), :class => 'btn' %>
  </div>
<% end %>`

这只允许我选择开发人员,我希望能够在那里修改estimated_time字段。

任何建议?

3 个答案:

答案 0 :(得分:26)

我喜欢简单形式的协会助手,在某些情况下让它变得非常简单。不幸的是,你想要的只是简单的形式无法解决。

您必须创建assignments才能实现此目的。

有两种可能的方法。

对于两者,您必须将以下内容添加到模型中:

class Task
  accepts_nested_attributes_for :assignments
end

请注意,如果您使用的是attr_accesible,则还应向其添加assignments_attributes

简单方法

假设您知道task最多可以分配多少个分配。假设为简单起见。

在你的控制器中,写下

def new
  @task = Task.build
  @task.assignments.build
end

这将确保有一项新任务。

在你的视图中写道:

= simple_form_for [@sprint,@task], :html => { :class => 'form-horizontal' } do |f| 
  = f.input :name 
  = f.input :description 

  = f.simple_fields_for :assignments do |assignment|
    = assignment.association :developer, :as => :select
    = assignment.estimated_time

  .form-actions
    = f.button :submit, :class => 'btn-primary'
    = link_to t('.cancel', :default => t("helpers.links.cancel")),
                project_sprint_path(@sprint.project_id,@sprint), :class => 'btn'

这种方法的问题:如果你想要超过1,2或3?

使用cocoon

Cocoon是一个允许您创建动态嵌套表单的gem。

您的观点将变为:

= simple_form_for [@sprint,@task], :html => { :class => 'form-horizontal' } do |f| 
  = f.input :name 
  = f.input :description 

  = f.simple_fields_for :assignments do |assignment|
    = render `assignment_fields`, :f => assignment
  .links
    = link_to_add_association 'add assignment', f, :assignments

  .form-actions
    = f.button :submit, :class => 'btn-primary'
    = link_to t('.cancel', :default => t("helpers.links.cancel")),
                project_sprint_path(@sprint.project_id,@sprint), :class => 'btn'

并定义部分_assignment_fields.html.haml

.nested_fields
  = f.association :developer, :as => :select
  = f.estimated_time
  = link_to_remove_association 'remove assignment', f

希望这有帮助。

答案 1 :(得分:4)

通过使用这个:

<%= f.association :developers, :as => :check_boxes %>

您实际上只设置了developer_ids属性,这将自动为您创建分配,因为它有很多:通过。为此,我认为您应该为每个分配使用嵌套属性,并且每个记录都有一个选择框或类似的选项,以便在此任务中为该特定分配选择相关的开发人员。它与Cojones的答案非常相似,但您不应该使用复选框进行此关联,因为您将要处理包含单个开发人员的单个作业。使用嵌套属性,您应该能够创建所需的任意分配。

我认为这是最简单的开始方式。

答案 2 :(得分:2)

我认为它应该看起来像这样:

= f.simple_fields_for :assignments do |fa|
  = fa.association :developer, as: :check_boxes
  = fa.input :estimated_time
  ...