Rails 关联 has_many 通过禁止/归档解决方案?
Posted
技术标签:
【中文标题】Rails 关联 has_many 通过禁止/归档解决方案?【英文标题】:Rails associations has_many through ban/archive solution? 【发布时间】:2015-09-24 07:54:09 【问题描述】:我是 Rails 新手,正在解决一个问题。我有两张桌子:
鞋子和袜子
一个 Shoe 可以有多个 Socks,但只有一个活动 Sock。其他袜子处于非活动状态。所有袜子也都是独一无二的,具有独特的图案。我想确保我没有相同图案的袜子。我想我可以通过三种方式做到这一点
1) 使用 table socks 中的附加列来表示活动 sock
class Shoe < ActiveRecord::Base
has_many :socks
end
class Sock < ActiveRecord::Base
belongs_to :shoe
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :size
t.timestamps null: false
end
create_table :socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.boolean :active
t.timestamps null: false
end
end
end
这看起来很简单,但是很麻烦。我会用 shoe_id 搜索袜子,然后取出 active_sock 并返回它的图案。我想我会在数组中索引 [active_sock, shoe_id] 以加快速度。
2) 使用附加表来归档非活动袜子
class Shoe < ActiveRecord::Base
has_many :socks
has_many :inactive_socks
end
class Sock < ActiveRecord::Base
belongs_to :Shoe
end
class Inactive_sock < ActiveRecord::Base
belongs_to :Shoe
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.timestamps null: false
end
create_table :socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.timestamps null: false
end
create_table :inactive_socks do |t|
t.belongs_to :shoe, index:true
t.string :pattern
t.timestamps null: false
end
end
end
这似乎也很麻烦,但是当您只是处理活动袜子时,它易于使用且快速。但是在买新袜子的时候,我必须用两张表检查图案。
3) 使用 has_many :through 关系
class Shoe < ActiveRecord::Base
has_many :active_socks
has_many :socks, through: active_socks
end
class Active_Sock < ActiveRecord::Base
belongs_to :Shoe
belongs_to :Sock
end
class Sock < ActiveRecord::Base
has_many :active_socks
has_many :shoes, through: active_socks
end
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.string :name
t.timestamps null: false
end
create_table :socks do |t|
t.string :pattern
t.timestamps null: false
end
create_table :active_socks do |t|
t.belongs_to :shoe, index: true
t.belongs_to :sock, index: true
t.string :pattern
t.boolean :active
t.timestamps null: false
end
end
end
这似乎是选项 2,但我觉得我正在使用 Rails 工具来减少麻烦。当我搜索模式时,我只是检查 socks 表,当我搜索一个 active_sock 时,我只是搜索 active_socks 表。
我读过类似的帖子,似乎选项 1 和 2 常用于已关闭帐户、禁止用户、禁止帖子、归档等。您需要区分仅略有不同的数据的情况。那里的选择似乎是看您需要什么,然后选择最适合您的选项 1 或 2。
我对 has_many 的理解似乎是当你有一段关系并且你需要额外的元数据时,你可以使用它。我认为这符合这种情况。
我是否正确设置了选项 1,索引 [shoe_id and active] 的数组是否可以让我更快地搜索?选项 3 是否适合使用 has_many?我对选项 3 的解释可行吗?
【问题讨论】:
【参考方案1】:您的使用模式是什么?我猜您只是希望能够找到给定 Shoe 的活动 Sock,以及给定的 Sock 是活动的还是非活动的。要快速找到给定 Shoe 的活动 Sock,您只需要通过 belongs_to
关联为 Sock 提供其 Shoe 的外键。
class Sock < ActiveRecord::Base
belongs_to :shoe
end
要确定 Sock 是否处于活动状态,请为其所有者的鞋子提供对其活动袜子的引用,如下所示:
class Shoe < ActiveRecord::Base
belongs_to :sock
end
现在,您只需前往其所有者 Shoe 并检查 Shoe 的活动袜子是否是当前 Sock。例如。
def is_active
owner_shoe.active_sock == self
基本上,将它们与外键关联起来就可以了! 附言您将 Socks 使用复数形式,但 Rails 约定是对模型名称使用单数。
编辑:您要求进行迁移,因此这是上面代码的迁移。警告:我已经很长时间没有在 Rails 中进行迁移了,所以可能会出现问题。
class CreateGettingDressed < ActiveRecord::Migration
def change
create_table :shoes do |t|
t.belongs_to :active_sock, foreign_key: "sock_id"
t.string :size
t.timestamps null: false
end
create_table :socks do |t|
t.belongs :owner_shoe, foreign_key: "shoe_id"
t.string :pattern
end
end
end
【讨论】:
谢谢我修正了复数形式。我考虑过您所描述的解决方案,但我不确定如何在相互引用的表中实现外键。在我看来,我需要一个 has_many/one 等参考来描述该关联。我将重读active record associations guide,以便更好地理解它。 要实现和使用外键,我相信你只需要在类声明和迁移中使用关联,为该键创建一个整数列。稍后我将编辑我的帖子以获取示例迁移。 我找不到一个好的答案。我在它自己的question 中询问了它,以便未来的用户可以找到解决方案,并认为我也会让你知道。我也打算试试看会不会坏。以上是关于Rails 关联 has_many 通过禁止/归档解决方案?的主要内容,如果未能解决你的问题,请参考以下文章