在 rails 中动态创建模型的多个实例
Dynamically create multiple instances of a model in rails
我有两个相关模型 "Test" 和 "Student":
class Student< ActiveRecord::Base
has_many :tests
end
class Test< ActiveRecord::Base
belongs_to :Student
end
我想做的是为学生创建未知数量的测试,即从学生的 show.html.erb,用户可以创建多个测试。此外,一旦创建了一组测试,用户就可以像以前一样通过学生的 show.html.erb 添加任意数量的测试。
请注意,测试创建不是学生创建的一部分(就像在 this railscast 中一样)。学生是单独创建的,然后可以通过 app/views/students/show.html.erb.
上的按钮添加多个测试
当单击添加测试的按钮时,我在 students_controller.rb 中调用自定义操作(下面的 customAction1)。我能想到的是动态构建和附加,比如说 10 个(开始)测试实例到学生的实例(在 students_controller.rb 的自定义操作中),呈现自定义视图(addtests.html.erb 下面),然后允许用户在该视图中输入这些测试实例的各种输入字段,最后当单击创建按钮时,调用 students_controller.rb 中的另一个自定义操作(下面的 customAction2)以保存(仅非空)测试实例。
这是正确的(阅读 Rails)方法吗?由于我是 rails 的新手,请更正我执行上述操作的代码:
students_controller.rb
#called when button to add tests is clicked from students/show.html.erb view:
def customAction1
@student = Student.find(params[:student])
10.times {@student.tests.append}
render 'addtests'
end
addtests.html.erb
# Here I'm unable to show input fields for each of the 10 newly added tests
students_controller.rb
# Called when create button is clicked from addtests.html.erb after inputting fields for some tests
def customAction2
@student.tests.save # Is this correct?
render 'show' # render show.html.erb of this student
end
如果这确实是正确的方法,请告诉我如何编写 addtests。html.erb 视图。
您仍然可以通过学生添加测试作为更新学生而不是创建并使用 cocoon
gem 来帮助您处理嵌套表格,我正在考虑这样的事情
Gem文件
gem 'cocoon'
Gem link: https://github.com/nathanvda/cocoon
models/student.rb
accepts_nested_attributes_for :tests
students_controller.rb
def show
@student = Student.find(params[:id])
@student.tests.build #you can check here if the student has already tests you can skip this build
end
def student_params
#add your own student parameters before the tests attributes
params.require(:student).permit(tests_attributes: [:id, :name, :_destroy]
end
students/show.html.haml
= form_for @student do |f|
= f.fields_for :tests do |builder|
= render 'tests/test_fields', f: builder
= link_to_add_fields 'Add Tests', f, :tests
此表单将提交给 students#update
操作,仅将 test_attributes
作为参数
tests/_test_fields.html.haml
-#add other test attributes that you might have
= f.input :name
= link_to_remove_association 'Remove Test', f
最后看了修改版的嵌套表格railscast解决了问题。以下是步骤:
students_controller.rb
#called when button to add tests is clicked from students/show.html.erb view:
def addTests
@student = Student.find(params[:student])
render 'addtests'
end
addtests.html.erb
<%= form_for(@student, url: {action: "realAddTests"}, method: :post) do |student_form| %>
<% test1 = Test.new %> #to show fields for one test by default
<%= student_form.fields_for(:tests, test1) do |f| %>
<%= render('test_fields', f: f) %>
<% end %>
<br />
<%= link_to_add_fields 'ADD MORE', student_form, :tests %><br /><br />
<%= student_form.submit "Save", class: "btn btn-primary" %>
<% end %>
_test_fields.html.erb #partial used above
<fieldset>
<%= f.label "Name" %>
<%= f.number_field :name %>
<%= f.label :date %>
<%= f.date_field :date %>
<%= f.label :time %>
<%= f.time_field :time %>
</fieldset>
students_controller.rb
# Called when save button is clicked in addtests.html.erb after inputting fields for some tests
def realAddTests
new_tests_hash = params[:student][:tests_attributes]
new_tests_hash.each do |key, value|
new_test_attributes = value.permit(:name, :date, :time)
@test = Test.new(new_test_attributes)
end
end
修改 app\assets\javascripts\tests.coffee 和 app\helpers\application_helper 完全按照 railscast 中指定的方式进行修改:
app\assets\javascripts\tests.咖啡:
jQuery ->
$(document).on 'click', 'form .add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
app\helpers\application_helper.rb:
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
以上是对我有用的完整步骤集,我可以一次性为一个学生创建和保存多个测试。
我有两个相关模型 "Test" 和 "Student":
class Student< ActiveRecord::Base
has_many :tests
end
class Test< ActiveRecord::Base
belongs_to :Student
end
我想做的是为学生创建未知数量的测试,即从学生的 show.html.erb,用户可以创建多个测试。此外,一旦创建了一组测试,用户就可以像以前一样通过学生的 show.html.erb 添加任意数量的测试。
请注意,测试创建不是学生创建的一部分(就像在 this railscast 中一样)。学生是单独创建的,然后可以通过 app/views/students/show.html.erb.
上的按钮添加多个测试当单击添加测试的按钮时,我在 students_controller.rb 中调用自定义操作(下面的 customAction1)。我能想到的是动态构建和附加,比如说 10 个(开始)测试实例到学生的实例(在 students_controller.rb 的自定义操作中),呈现自定义视图(addtests.html.erb 下面),然后允许用户在该视图中输入这些测试实例的各种输入字段,最后当单击创建按钮时,调用 students_controller.rb 中的另一个自定义操作(下面的 customAction2)以保存(仅非空)测试实例。
这是正确的(阅读 Rails)方法吗?由于我是 rails 的新手,请更正我执行上述操作的代码:
students_controller.rb
#called when button to add tests is clicked from students/show.html.erb view:
def customAction1
@student = Student.find(params[:student])
10.times {@student.tests.append}
render 'addtests'
end
addtests.html.erb
# Here I'm unable to show input fields for each of the 10 newly added tests
students_controller.rb
# Called when create button is clicked from addtests.html.erb after inputting fields for some tests
def customAction2
@student.tests.save # Is this correct?
render 'show' # render show.html.erb of this student
end
如果这确实是正确的方法,请告诉我如何编写 addtests。html.erb 视图。
您仍然可以通过学生添加测试作为更新学生而不是创建并使用 cocoon
gem 来帮助您处理嵌套表格,我正在考虑这样的事情
Gem文件
gem 'cocoon'
Gem link: https://github.com/nathanvda/cocoon
models/student.rb
accepts_nested_attributes_for :tests
students_controller.rb
def show
@student = Student.find(params[:id])
@student.tests.build #you can check here if the student has already tests you can skip this build
end
def student_params
#add your own student parameters before the tests attributes
params.require(:student).permit(tests_attributes: [:id, :name, :_destroy]
end
students/show.html.haml
= form_for @student do |f|
= f.fields_for :tests do |builder|
= render 'tests/test_fields', f: builder
= link_to_add_fields 'Add Tests', f, :tests
此表单将提交给 students#update
操作,仅将 test_attributes
作为参数
tests/_test_fields.html.haml
-#add other test attributes that you might have
= f.input :name
= link_to_remove_association 'Remove Test', f
最后看了修改版的嵌套表格railscast解决了问题。以下是步骤:
students_controller.rb
#called when button to add tests is clicked from students/show.html.erb view:
def addTests
@student = Student.find(params[:student])
render 'addtests'
end
addtests.html.erb
<%= form_for(@student, url: {action: "realAddTests"}, method: :post) do |student_form| %>
<% test1 = Test.new %> #to show fields for one test by default
<%= student_form.fields_for(:tests, test1) do |f| %>
<%= render('test_fields', f: f) %>
<% end %>
<br />
<%= link_to_add_fields 'ADD MORE', student_form, :tests %><br /><br />
<%= student_form.submit "Save", class: "btn btn-primary" %>
<% end %>
_test_fields.html.erb #partial used above
<fieldset>
<%= f.label "Name" %>
<%= f.number_field :name %>
<%= f.label :date %>
<%= f.date_field :date %>
<%= f.label :time %>
<%= f.time_field :time %>
</fieldset>
students_controller.rb
# Called when save button is clicked in addtests.html.erb after inputting fields for some tests
def realAddTests
new_tests_hash = params[:student][:tests_attributes]
new_tests_hash.each do |key, value|
new_test_attributes = value.permit(:name, :date, :time)
@test = Test.new(new_test_attributes)
end
end
修改 app\assets\javascripts\tests.coffee 和 app\helpers\application_helper 完全按照 railscast 中指定的方式进行修改:
app\assets\javascripts\tests.咖啡:
jQuery ->
$(document).on 'click', 'form .add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
app\helpers\application_helper.rb:
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
以上是对我有用的完整步骤集,我可以一次性为一个学生创建和保存多个测试。