我的方法将国家/地区列表(代码,名称)加载到数据库中,但在此之前,如果国家/地区数据尚不存在,则必须检查。这很好用:
def self.load_countries
get_countries.each do |country|
code, name = country
if find_by_code(code).nil?
create({ 'name' => name, 'code' => code })
end
end
end
然而,由于我是Ruby新手,我想学习最佳实践。所以,在这段代码中,我不确定可能(或可能不会)优化的两件事:
这个问题可能很愚蠢,但我想确定一下:当我用get_countries.each开始循环时,是否可以使用方法而不是变量?是不是每个循环调用相同的方法(N次)?换句话说,这会更有效率吗?
countries = get_countries
countries.each do | country |
对这几行代码的任何评论都是受欢迎的,因为它的工作原理并不一定意味着我正在以正确的方式做到这一点。
谢谢。
答案 0 :(得分:10)
你可以使用存在吗?在ActiveRecord中运行。
def self.load_countries
get_countries.each do |country|
code, name = country
unless exists?(:code => code)
create({ :name => name, :code => code })
end
end
end
get_countries函数只被调用一次。它返回一个可枚举的数据类型,然后逐个遍历它们。
答案 1 :(得分:3)
使用find_or_create_by
get_countries.each do |country|
code, name = country
find_or_create_by_code_and_name(code, name)
end
答案 2 :(得分:1)
1)为模型添加唯一性验证(假设Rails 3)
validates :code, :uniqueness => true
使用db / seeds.rb将种子数据加载到数据库。恕我直言'load_countries'方法不属于模型(特别是如果它是一次性操作)。
答案 3 :(得分:1)
在Ruby on rails中,我们有四种方法来检查数据库中是否存在记录?
.present?
这是最耗时的方法,因为它返回数据库中的所有记录。
.ANY? / .empty?
以上两者都具有相同的性能效率,因为它们最终都会在数据库上触发'COUNT'查询。因此,与.present?
.exist?
最后一个更加优化,在检查记录的存在时它应该是您的首选。它使用'SELECT 1 ... LIMIT 1'方法。
当您的ActiveRecord对象已经在内存中时(如果您预先加载它们),请记住一件事,那么不要使用'exists?'而是使用'any?',因为'存在?'对于对象是否在内存中总是命中数据库,而'any? /空?如果记录已经加载到内存中,则填充不会再次命中数据库。
您还可以参考这篇文章:Check if record is exist in ROR
答案 4 :(得分:0)
也许您必须在数据库模型中使用UNIQUE代码?
我是说这个 http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000086
答案 5 :(得分:0)
您可以在ActiveRecord模型中使用unique validation,例如:
class Country < ActiveRecord::Base
validates_uniqueness_of :code
validates_uniqueness_of :name
end
答案 6 :(得分:0)
1。)您不一定需要选择整行,您可以使用:select =&gt;限制你获取的列的选项,但这对我来说似乎是一个微优化。我不担心。如果这种方法的效率让你感到困扰,那么你最好找出一种避免在循环中进行SQL查询的方法;例如,考虑在循环之前选择所有现有国家,将它们存储在数组或散列中,并使用它来查看该国家是否已存在。然后,不是几十次访问数据库,而是只创建一个(不包括添加新记录的那些)。另一方面,这听起来不像你将要运行很多次的代码(听起来像是一个种子数据库表的情况),所以它可能并不重要。
2。)不,get_countries方法不会在循环的每次迭代中被调用,只在#each开始之前调用一次;假设get_countries返回一个数组,#each是数组上的一个方法。