Rails - 在一个表单中创建许多模型 - 在控制器中

时间:2014-09-16 10:14:26

标签: ruby-on-rails ruby ruby-on-rails-3


我有一个小问题 - 如何通过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对唯一性进行了验证 如何在控制器动作中执行此操作,是否可能?

1 个答案:

答案 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次。