【问题标题】:I do not understand a many_to_one <=> one_to_one model association我不明白 many_to_one <=> one_to_one 模型关联
【发布时间】:2018-01-01 04:22:38
【问题描述】:

怎么说?我不明白续集文档试图告诉我关于关联的内容,以防两个模型通过一个模型中的外键链接 A 在 may_to_one 案例中是另一个模型中的主键。 我一直认为:如果它在一个方向上是 many_to_one,那么在另一个方向上一定是 one_to_many……但续集提供了一个令人困惑的章节,旨在澄清主题,另外还有一个我无法遵循的示例。

上面写着 "Differences Between many_to_one and one_to_one"

如果要在两个模型之间建立 1-1 关系,其中一个表中的外 > 键直接引用关联表,则必须使用 many_to_one 在一个模型中,而 one_to_one 在另一个模型中。怎么做 你知道在哪个模型中使用哪个吗?最简单的记忆方法是 其表具有外键的模型使用 many_to_one,并且 另一个模型使用 one_to_one"

并继续提供这个奇怪的例子:

# Database schema:
#  artists            albums
#   :id   <----\       :id
#   :name       \----- :artist_id 
#                      :name

class Artist
  one_to_one :album
end
class Album
  many_to_one :artist
end

在专辑中,我可能会发现几行指向同一个艺术家...为什么艺术家不应该指向他/她的所有专辑? 在很多情况下,续集文档非常难以阅读,但这一章读起来很容易,但对我来说毫无意义:(

【问题讨论】:

  • 因为您只需要在一个表中指定关系,并且对于多对一关系,在每个“子”记录中都有一个指向父记录 ID。如果要查找父项的所有子项,则查询所有子记录的 parent_id 字段等于父项的 id。
  • 我同意这个例子没有什么意义,因为它似乎暗示Artist 只能有 1 个Album (one_to_one) 但很多 Albums 可以属于 1 Artist (many_to_one)。我认为这只是为了展示关联之间的差异,因为上面更明确地记录了每个关联,但他们本可以选择一个更好的例子
  • 我坐在一个没有运行的模型前面(最后的复数 s 太多了......因为在续集中,如果是模型或桌子,并不总是很清楚)......我在屏幕上度过了漫长的一夜之后,凌晨 4 点打开文档,发现了这个“额外的变质)......我仍然无法想象一个单一的场景,其中多对一以合乎逻辑的方式加倍以一对一作为回报。这就是为什么我认为我从 sql 到续集模型时错过了一个重要概念。
  • one_to_one 很有用,因为它直接返回对象,而在许多关联中你有一个数组。它也更快,因为它强制续集选择第一个结果,而不是遍历整个表来寻找命中。

标签: ruby associations one-to-one many-to-one sequel


【解决方案1】:

对我来说同样的问题。

require "logger"
require "sequel"

db = Sequel.connect "postgres://localhost/postgres", :logger => Logger.new(STDOUT)

db.drop_table :artists, :cascade => true if db.table_exists?(:artists)
db.create_table :artists do
  primary_key :id
  foreign_key :album_id, :albums
end

db.drop_table :albums, :cascade => true if db.table_exists?(:albums)
db.create_table :albums do
  primary_key :id
  foreign_key :artist_id, :artists
end

class Artist < Sequel::Model(db[:artists])
  one_to_one :album
end
class Album < Sequel::Model(db[:albums])
  one_to_one :artist
end

artist_1 = Artist.create
album_1  = Album.create

artist_1.update :album => album_1
album_1.reload
puts album_1.artist.nil?

artist_2 = Artist.create
album_2  = Album.create

album_2.update :artist => artist_2
artist_2.reload
puts artist_2.album.nil?

我们可以通过将任何one_to_one 替换为many_to_one 来修复此示例。

class Album
  many_to_one :artist
end

在这种情况下,artist.album_id 不会被使用。

class Artist
  many_to_one :albums
end

在这种情况下album.artist_id 不会被使用。

问题在于方法名称one_to_onemany_to_one 是由底层sequel 逻辑选择的,它们对用户不友好。

您可以为这些方法创建用户友好的别名。我更喜欢将它与 cmets 一起使用。例如:

db.create_table :artists do
  primary_key :id
  foreign_key :album_id, :albums
end    
db.create_table :albums do
  primary_key :id
end

class Artist < Sequel::Model(db[:artists])
  many_to_one :album # I have album_id foreign key
end
class Album < Sequel::Model(db[:albums])
  one_to_one :artist # I don't have artist_id foreign key
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多