【发布时间】:2014-01-27 12:20:12
【问题描述】:
Rails 4,Mongoid 而不是 ActiveRecord(但是为了这个问题,这应该改变任何东西)。
假设我有一个带有一些验证规则的 MyModel 域类:
class MyModel
include Mongoid::Document
field :text, type: String
field :type, type: String
belongs_to :parent
validates :text, presence: true
validates :type, inclusion: %w(A B C)
validates_uniqueness_of :text, scope: :parent # important validation rule for the purpose of the question
end
其中Parent 是另一个域类:
class Parent
include Mongoid::Document
field :name, type: String
has_many my_models
end
此外,我在数据库中的相关表中填充了一些有效数据。
现在,我想从 CSV 文件中导入一些数据,这可能与数据库中的现有数据发生冲突。简单的做法是为 CSV 中的每一行创建一个 MyModel 实例并验证它是否有效,然后将其保存到数据库中(或丢弃它)。
类似这样的:
csv_rows.each |data| # simplified
my_model = MyModel.new(data) # data is the hash with the values taken from the CSV row
if my_model.valid?
my_model.save validate: false
else
# do something useful, but not interesting for the question's purpose
# just know that I need to separate validation from saving
end
end
现在,这对于有限的数据量来说非常顺利。但是当 CSV 包含数十万行时,这会变得很慢,因为(最坏的情况)每一行都有一个写操作。
我想做的是存储有效项目的列表并在文件解析过程结束时将它们全部保存。所以,没什么复杂的:
valids = []
csv_rows.each |data|
my_model = MyModel.new(data)
if my_model.valid? # THE INTERESTING LINE this "if" checks only against the database, what happens if it conflicts with some other my_models not saved yet?
valids << my_model
else
# ...
end
end
if valids.size > 0
# bulk insert of all data
end
如果我能确定 CSV 中的数据不包含重复行或违反 MyModel 验证规则的数据,那将是完美的。
我的问题是:如何根据数据库和valids 数组检查每一行,而不必重复MyModel 中定义的验证规则(避免重复)?
我没有考虑其他(更有效)的方法吗?
【问题讨论】:
-
检查没有 ActiveRecord 的验证,作为参考:stackoverflow.com/questions/3563087/… 和 stackoverflow.com/questions/9816866/…
-
这很有趣,但似乎不是我想要的。如果我必须只测试存在或包含等验证规则,这将是可以的,但是声明
MyModel的实例在其Parent范围内应该是唯一的规则呢?
标签: ruby-on-rails validation ruby-on-rails-4 mongoid bulkinsert