Rails has_many 与预填充视图的关系

Rails has_many relationship with prefilled views

我有一个非常基本的 Rails 4 应用程序,并且正在使用 Cocoon 的嵌套表单来管理 has_many... :through 模型关联。

class Student < ActiveRecord::Base
  has_many :evaluations
  has_many :assessments, through: :evaluations

  # ... etc
end

class Evaluation < ActiveRecord::Base
  belongs_to :student
  belongs_to :assessment

  # ... etc
end

class Assessment < ActiveRecord::Base
  has_many :evaluations
  has_many :students, through: :evaluations

  accepts_nested_attributes_for :evaluation, reject_if: :all_blank
  # ... etc
end

当我在视图中使用 Cocoon 时,我想使用新的 Assessment 视图来预填充所有 Student 记录,以便为每个记录创建一个新的 Evaluation一。我不想在控制器端做一些 hacky 逻辑来手动添加一些新记录,那么我将如何构建传入请求?使用 Cocoon,我看到请求在 id 所在的 space 中有一些数字(我在下面用 ?? 替换了这些)。

{"utf8"=>"✓", "authenticity_token"=>"whatever", "assessment"=>{"description"=>"quiz 3", "date(3i)"=>"24", "date(2i)"=>"10", "date(1i)"=>"2015", "assessments_attributes"=>{"??"=>{"student_id"=>"2", "grade" => "A"}, "??"=>{"student_id"=>"1", "grade" => "B"}, "??"=>{"student_id"=>"3", "grade"=>"C"}}, }}, "commit"=>"Create Assessment"}

我在 Coccoon source code 中看到这是以某种方式生成的,但我无法弄清楚它是如何与 Rails 引擎一起工作的,从而在没有 [=20= 的情况下将其变成新记录].

上面的id填写应该用什么算法(或者说应该遵循什么规则)来创建新的记录?

"??"

你的参数绝对不是好兆头。

With Cocoon I see that requests have some number in the space where the id would go

那个 ID只不过是Rails创建的fields_for数组中的下一个ID。这不是您的记录 id(更多解释见下文)。


根据您的设置,我将执行以下操作:

#app/models/student.rb
class Student < ActiveRecord::Base
   has_many :evaluations
   has_many :assessments, through: :evaluations
end

#app/models/evaluation.rb
class Evaluation < ActiveRecord::Base
  belongs_to :student
  belongs_to :assessment
end

#app/models/assessment.rb
class Assessment < ActiveRecord::Base
   has_many :evaluations
   has_many :students, through: :evaluations
   accepts_nested_attributes_for :evaluations, reject_if: :all_blank
end

这将允许您执行以下操作:

#app/controllers/assessments_controller.rb
class AssessmentsController < ApplicationController
   def new
      @assessment = Assessment.new
      @students = Student.all
      @students.each do
         @assessment.evaluations.build
      end
   end
end

让你:

#app/views/assessments/new.html.erb
<%= form_for @assessment do |f| %>
   <%= f.fields_for :evaluations, @students do |e| %>
       <%= e.hidden_field :student_id %>
       <%= e.text_field :grade %>
   <% end %> 
   <%= f.submit %>
<% end %>

据我所知,这将提供您需要的功能。

请记住,每个 evaluation 都可以与现有的 students 连接,这意味着如果您拉取 @students = Student.all,它将相应地填充 fields_for

如果您想通过您的表单添加students,则情况略有不同。


你也应该清楚Cocoon的作用。

您看起来像是一位经验丰富的开发人员,所以我将切入正题 - Cocoon 是前端,您问的是后端。

具体来说,Cocoon 旨在让您能够向表单添加多个 fields_for 关联字段。这在 Railscast...

中进行了讨论

从技术上讲,Cocoon 只是一种为表单创建新 fields_for 记录的方法。如果您想动态 "add" 字段,则 是必需的(RailsCast 会告诉您更多信息)。

因此,如果您只想拥有一个 "static" 关联数据字段数组(我想这就是您要问的),您将能够使用提交的 fields_forMax 和我的回答中。

多亏了@rich-peck,我才能够准确地弄清楚我想做什么。我将接受他的回答,因为这基本上是我自己的回答。 :)

assessments/new.html.haml(只是原始的,没有花哨的格式)

= form_for @assessment do |f|
  = f.fields_for :evaluations do |ff|
    .meaningless-div
      = ff.object.student.name
      = ff.hidden_field :student_id, value: ff.object.student_id
      = ff.label :comment
      = ff.text_field :comment
      %br/

assessments_controller.rb

def new
  @assessment = Assessment.new
  @students = Student.all
  @students.each do |student|
    @assessment.evaluations.build(student: student)
  end
end