【问题标题】:first_or_create vs find_or_create_byfirst_or_create 与 find_or_create_by
【发布时间】:2017-02-11 17:05:53
【问题描述】:

first_or_create 似乎记录得少得多,所以我想知道这是否只是因为这两种方法是同义词。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    基本上:

    Foo.where(attributes).first_or_create
    

    等同于:

    Foo.find_or_create_by(attributes)
    

    #first_or_create 有时会被误解为人们期望它根据给定的属性进行搜索,但事实并非如此。阿卡

    Foo.first_or_create(attributes)
    

    不会搜索满足attributesfoo。如果有的话,它将采用第一个foo。如果查找条件是用于创建的条件的子集,这将很有用。阿卡

    Foo.where(something: value).first_or_create(attributes)
    

    将在something: value 处找到第一个foo。如果不存在,它将使用attributes 创建它。

    【讨论】:

    • 然而,这两者在执行的 SQL 方面并不相同。 first_or_create 将使用ORDER BY id LIMIT 1,而find_or_create_by 将仅使用LIMIT 1。在大多数情况下这无关紧要,但随着数据集的增长,您可能会发现这种微小的差异会使事情变慢几个数量级(即使有索引)。
    • 确实如此,这意味着find_or_*_by 应该是where(..).first_or_* 的首选语法
    • 提交 nodoc the first_or_create methods and document alternatives 解释了为什么它的文档较少。
    • 是的,除了可能的混淆之外,还有更多内容。在my answer 中了解更多信息。 @Saul first_or_create 出现在 Rails 3.2.19 中,并且在 Rails 4.0 中被弃用了。在那段时间里,它的代码没有太大变化。这一切都归结为first,它按id 排序,除非明确指定其他排序。
    • 我可能遗漏了一些东西,但我怀疑 first_or_create 是否曾取消过 ORDER BY 子句。
    【解决方案2】:

    @ndnenkov 的回答是对的,但我想详细说明为什么我认为有人可能会使用 find_or_create

    考虑 Foo 必须具有 attribute_subset_1attribute_subset_2 才能创建它的情况。可以(伪)将其编码为:

    if attribute_subset_1 then
      Foo.where(attribute_subset_1).first_or_create(attributes)
    elsif attribute_subset_2 then
      Foo.where(attribute_subset_2).first_or_create(attributes)
    else
      Raise error " insufficient attributes"
    end
    

    这是我认为find_or_create_by 不起作用的情况......至少不容易。我很想知道是否有任何不同的看法,但对我来说,我发现first_or_create 的这种用法非常适合我的需求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 1970-01-01
      相关资源
      最近更新 更多