我有一个小问题 - 如何通过Rails 3中的一个表单创建许多模型并将其保存到数据库中
我的意思是 - 我有一个表单创建代码 - 生成随机 - 他们的内容,字符串。
在控制器中:
@code = Code.new(params[:code])
characters = [('a'..'z'), ('0'..'9'), ('A'..'Z')].map { |i| i.to_a }.flatten
@code.code_value = @code.code_letters + (0...8).map { characters[rand(characters.length)] }.join
现在我想多次点击一次创建代码,例如,我有input: code_quantity, :integer
然后我选择数量为1000,然后当我点击submit
时,在控制器中 - 创建动作应该创建它1 * code_quantity
次,但它应该创建唯一的每一个代码,如:
1000.times { @code = Code.new(params[:code]) }
:code_value
对唯一性进行了验证
如何在控制器动作中执行此操作,是否可能?
答案 0 :(得分:0)
首先,关注点 - 生成uniq随机代码似乎并不像控制器应该关注的那样。这是严格的模型相关行为,所以让我们重构一下并将其移动到模型中:
class Code < ActiveRecord::Base
CODE_CHARS = ['a'..'z', '0'..'9', 'A'..'Z'].flat_map &:to_a
after_initialize do
generate_code unless code_value.present?
end
def self.generate_code
code_letters + (0..8).map { CODE_CHARS.sample }.join
end
def generate_code
self.code_value = self.class.generate_code
end
end
现在,您可以在控制器中执行以下操作:
@codes = Array.new(params[:code_quantity]) { Code.new(params[:code]) }
@codes.each &:save
虽然不是那么容易 - 可能会发生一些模型会破坏唯一性验证并且不会被保存为结果(非常不可能,但是8个字符只有218340105584896个唯一组合)。要解决你需要的问题:
1)如果您还没有将唯一性约束添加到数据库中(唯一性验证不能确保记录的唯一性 - 并发性是......):
# New migration
def change
add_index :codes, :code_value, unique: true
end
2)覆盖save!
方法:
class Code
...
def save!(*args)
tries = 0;
begin
super
rescue
tries += 1
raise if errors.any? || tries > 10
generate_code
retry
end
end
现在,每当您尝试保存记录时,除了验证之外,它将因任何其他原因而失败,它将尝试在放弃之前重新生成代码10次。