Rails:检查数据库中是否存在记录的最佳方法是什么?

时间:2010-11-22 23:32:47

标签: ruby-on-rails activerecord

我的方法将国家/地区列表(代码,名称)加载到数据库中,但在此之前,如果国家/地区数据尚不存在,则必须检查。这很好用:

 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新手,我想学习最佳实践。所以,在这段代码中,我不确定可能(或可能不会)优化的两件事:

  1. find_by_attribute返回“select * from table”语句。在这种情况下,当我不需要来自数据库的任何数据时 - 我只想知道记录是否存在 - 选择整行对我来说似乎有点低效。有没有更好的方法来解决这个问题?例如,“使用ActiveRecord?
  2. 从表格中选择1 ...”
  3. 这个问题可能很愚蠢,但我想确定一下:当我用get_countries.each开始循环时,是否可以使用方法而不是变量?是不是每个循环调用相同的方法(N次)?换句话说,这会更有效率吗?

    countries = get_countries

    countries.each do | country |

  4. 对这几行代码的任何评论都是受欢迎的,因为它的工作原理并不一定意味着我正在以正确的方式做到这一点。

    谢谢。

7 个答案:

答案 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中,我们有四种方法来检查数据库中是否存在记录?

  1. .present?

    这是最耗时的方法,因为它返回数据库中的所有记录。

  2. .ANY? / .empty?

    以上两者都具有相同的性能效率,因为它们最终都会在数据库上触发'COUNT'查询。因此,与.present?

  3. 相比,这两者都是有效的
  4. .exist?

    最后一个更加优化,在检查记录的存在时它应该是您的首选。它使用'SELECT 1 ... LIMIT 1'方法。

  5. 当您的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是数组上的一个方法。