在我的Ruby on Rails应用程序中,我试图根据用户在表单上输入的数字动态创建n个数据库记录。为了简单起见,我将使用一本书及其章节的类比来说明我想要做的事情。下面是我的模型,属性和表格来创建一本书。
型号:
class Book < ActiveRecord::Base
has_many :chapters
end
class Chapter < ActiveRecord::Base
belongs_to :book
end
图书属性:
id
,book_title
,number_of_chapters
,created_at
,updated_at
章节属性:
id
,chapter_title
,contents
,book_id
,created_at
,updated_at
表单以创建新书:
<%= form_for(@book) do |f| %>
<%= f.text_field :book_title %>
<%= f.text_field :number_of_chapters %>
<%= f.submit %>
<% end %>
当用户创建图书时,他们可以输入图书的标题和图书的章节数。如果用户输入5章,那么我们需要能够动态地将5条记录插入章节表中,每个记录都有一个唯一生成的章节标题名称。
生成的章节标题可以简单如下:
chapter1
chapter2
chapter3
chapter4
chapter5
我在研究中找到的最接近的解决方案是创建一个嵌套的模型表单。但由于几个原因,嵌套模型形式不是理想的解决方案。我无法预测需要插入第二个模型的记录数量,它可能是几个或高达10,000个记录。加上手动数据输入该许多记录的字段值是不实际的。
我有一些我认为需要做的事情,但我需要帮助将它们捆绑在一起。
我的第一个想法是使用after_save
回调来触发创建章节的方法。我会将以下内容添加到Book模型中。
after_save Chapter.generate_chapter_titles
但是从性能的角度来看,我怀疑after_save
是否是最好的方法,因为我们可能一次创建数千条记录。
在章节模型中,我考虑使用以下方法根据chapter_titles
创建number_of_chapters
值。
def generate_chapter_titles
1.upto(book.number_of_chapters) do |chapter|
print "chapter%d" % chapter
end
但现在我陷入了困境,我还没有想到如何从generate_chapter_titles
获取输出并创建单独的章节db记录。同时确保新生成的章节与从中创建的书籍相关联。
非常感谢有关使此功能正常工作的任何帮助。我在发布之前试图对此进行研究,但答案仍然没有找到我。我是一个编程和Ruby noob,所以我愿意承认Ruby和Ruby on Rails API文档中的一些信息超出了我的想象。我非常感谢任何关于分解和理解我需要使其功能增加的帮助。
更新 - 最终解决方案
感谢@margo,我所要做的就是使用下面的代码更新create
中的books_controller.rb
方法。现在,章节将根据为number_of_chapters
输入的值自动生成。
class BooksController < ApplicationController
[...]
def create
@book = Book.new(book_params)
if @book.save
ActiveRecord::Base.transaction do
@book.number_of_chapters.times do |n|
Chapter.create!(book_id: @book.id, title: "Chapter #{n+1}")
end
end
redirect_to @book, notice: "Book created successfully."
else
render 'new'
end
end
[...]
end
答案 0 :(得分:0)
首先,您需要在transaction中包装本书章节的创建。如果在完成之前发生错误,事务将确保保存所有章节或回滚任何提交。
您可以在books_controller中的create方法中创建所有章节。下面是一个例子,你必须填写各个部分。
在你的books_controller中
def create
@book = Book.new(book_params)
if @book.save
generate_chapters(@book)
end
end
private
def generate_chapters(book)
ActiveRecord::Base.transaction do
book.number_of_chapters.times do |n|
Chapter.create!(book_id: book.id, title: "Chapter #{n+1})"
end
end
end
我建议你从这种方法开始并让它运作起来。如果您要同时创建数千条记录,那么您可能需要考虑将其移至后台作业,但这是一个单独的问题。