gpt4 book ai didi

ruby-on-rails - Active Record has_many 生成带有外键 IS NULL 的 sql

转载 作者:行者123 更新时间:2023-12-04 21:47:11 24 4
gpt4 key购买 nike

我不希望以 NULL 作为外键的模型属于任何东西!

我有以下 Rails 应用程序,模拟 Ant 和 Ant 山(受 Jozef 启发)。

$ rails -v
Rails 3.2.8
$ rails new ant_hill
$ cd ant_hill

创建 Ant 山和 Ant 模型。一个 Ant 可以属于一个蚁丘,一个蚁丘可以有很多 Ant 。
$ rails generate model AntHill name:string
$ rails generate model Ant name:string ant_hill_id:integer
$ vim app/models/ant.rb
$ cat app/models/ant.rb
class Ant < ActiveRecord::Base
belongs_to :ant_hill
end
$ vim app/models/ant_hill.rb
$ cat app/models/ant_hill.rb
class AntHill < ActiveRecord::Base
has_many :ants
end
$ rake db:migrate
== CreateAntHills: migrating =================================================
-- create_table(:ant_hills)
-> 0.0013s
== CreateAntHills: migrated (0.0016s) ========================================

== CreateAnts: migrating =====================================================
-- create_table(:ants)
-> 0.0035s
== CreateAnts: migrated (0.0037s) ============================================

在控制台中运行以下代码。
$ rails c
Loading development environment (Rails 3.2.8)

创建几个 Ant ,坚持,不属于任何 Ant 山。
1.9.2-p290 :001 > Ant.create! name: "August"
=> #<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06">
1.9.2-p290 :002 > Ant.create! name: "Bertil"
=> #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13">

现在实例化一个蚁丘,但暂时不要保存它。
1.9.2-p290 :003 > ant_hill = AntHill.new name: "Storkullen"
=> #<AntHill id: nil, name: "Storkullen", created_at: nil, updated_at: nil>

我希望这个 Ant 山没有任何 Ant ,但它没有。
1.9.2-p290 :004 > ant_hill.ants
=> []

我仍然希望 Ant 山没有任何 Ant ,但现在它有两个。
1.9.2-p290 :005 > ant_hill.ants.count
(0.1ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" IS NULL
=> 2

同样,在处理外键时,它不应该生成包含“IS NULL”的查询。我的意思是“belongs_to NULL”不能属于任何东西,对吧?
1.9.2-p290 :006 > ant_hill.ants.all
Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" IS NULL
=> [#<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06">, #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13">]

持久化后,它的行为符合预期。
1.9.2-p290 :007 > ant_hill.save!
=> true
1.9.2-p290 :008 > ant_hill.ants.count
(0.4ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" = 1
=> 0
1.9.2-p290 :009 > ant_hill.ants.all
Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" = 1
=> []

有什么见解吗?这是预期的行为吗?

最佳答案

虽然这似乎违反直觉,但我认为鉴于您的示例,这种行为是有道理的。拍ant_hill.ants.count例如。 Count 是一种命中数据库的 ActiveRecord 查询方法,您实际上是在要求 ActiveRecord 为您提供所有不属于蚁丘的 Ant 。 Rails 只是让你做一些你不应该做的事情,而不是提示它。这应该引发异常吗?可能。

如果你真的想知道有多少 Ant 属于这个 ant_hill 对象,你应该使用 size。它在未持久化或关联已加载时查询对象,否则查询数据库。

ant_hill.ants.size

绕过这种奇怪的一种方法是通过验证 ant_hill_id 的存在来使 ant_hill_id 成为必填字段。

TL;DR 如果父对象未持久化到数据库,请避免使用 ActiveRecord 查询接口(interface)。

关于ruby-on-rails - Active Record has_many 生成带有外键 IS NULL 的 sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12621382/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com