5

我有任务和用户。当用户完成一项任务时,我会创建一个 Completion,其中有一个字段供用户指示他们花费了多长时间。我需要一个表单来显示所有任务及其完成状态和 time_spent 属性。提交时,应该更新存在的完成并创建新的完成。如果可能的话,我想在 Formtastic 中执行此操作,但我会对基本的 Rails 3 解决方案感到满意。

class Completion < ActiveRecord::Base
  belongs_to :task
  belongs_to :user

  # attribute time_spent
end

class User < ActiveRecord::Base
  has_many :completions
  has_many :tasks, :through => :completions
end    

class Task < ActiveRecord::Base
  belongs_to :milestone
  has_many :completions
  has_many :users, :through => :completions
end

一个额外的方面是我只想显示一组特定的任务,例如属于里程碑的任务。我是否应该在 Milestone 控制器上创建一个表单来发布到 Completions 控制器?

class Milestone < ActiveRecord::Base
  has_many :tasks
  has_many :completions, :through => :tasks
end

更新我已经找了好几天了, 我发现了很多 死胡同 Rails 表单中的Multiple objects很接近,但它要求所有链接对象都已经存在。

这个问题的不同之处在于,一些链接还不存在,并且没有用于嵌套链接的单一模型。例如,Ryan Daigle 的嵌套对象表单帖子)我已经在一个表单中进行了这项工作以进行编辑用户的所有可能完成,但我需要以一种形式编辑可能完成的子集。我是否需要为has_manyCompletions 和belongs_toUser 创建一个冗余对象 MilestoneCompletions?ActiveModel 可以has_many吗?

4

2 回答 2

5

我终于解决了这个问题。一个关键是fields_for的集合参数。另一种是生成包含现有记录和新记录的集合。

所以在视图中,类似:

<%= form_for @user do |f| %>
  <table>
    <tr><th>Completed</th><th>Time spent</th><th>Task</th></tr>

    <%= f.fields_for :completions, available_completions_for_milestone(@user, @milestone) do |cf| %>
      <tr>
        <td><%= cf.check_box :status, {disabled: cf.object.persisted?}, "done", "unreported" %></td>
        <td><%= cf.text_field :time_spent_text %></td>
        <td><%= cf.object.task.description %></td>
      </tr>
      <%= cf.hidden_field :task_id %>
    <% end -%>

使用辅助方法:

def available_completions_for_milestone(user, milestone)
  user_completions = user.completions.in_milestone(milestone)    
  available = []
  milestone.tasks.each do |t|
    c = user_completions.select{|c| c.task_id == t.id}.first
    if !c then # make it
      c = user.completions.build( task: t )
    end
    available << c
  end
  available
end

请注意,已在数据库中的完成已被检查和禁用,因此它们不能被取消选中。未选中状态的值是“未报告”,用户模型可以过滤掉这些记录,这样它们就不会进入数据库:

has_many :completions
accepts_nested_attributes_for :completions, :reject_if => proc { |attrs| attrs['status'] == 'unreported' }

我还必须completions_attributes在 User 模型上设置 attr_accessible。如果您可以task_ids访问,那么update将删除PUT.

于 2011-02-08T03:04:47.550 回答
0

我自己回答这个问题,作为任何其他读者的可能解决方案,但它并不令人满意,所以我没有将其标记为可接受。

为了解决这个问题,在表单生成操作中,我只是create在“非活动”状态下缺少任何关联。(通过在模型中添加一个status字段Completion。)然后我使用表单的“object[]”数组编辑功能。RISCfuture在 forms_for API docs的第二条评论中有一些有用的提示。

于 2011-02-04T17:57:09.603 回答