belongs_to belongs_to 仅关联 无 has_many 或 has_one
belongs_to belongs_to association only no has_many or has_one
你能在 Rails 中建立 belongs_to
belongs_to
关系吗?
Search results 给了我两个结果。事实上,我找不到关于这个主题的太多信息,这似乎表明不应该这样做或者是不好的做法。
我问 yesterday 关于 has_many 关系,但我想因为我找不到这方面的信息,所以我会提出一个问题,这样人们就可以更容易地在未来。我在转述另一个用户的回答(希望没问题)。
一个鞋可以有很多袜子,但只有一个活跃的袜子。其他袜子处于非活动状态。所有的袜子也都是独一无二的,有着独特的图案。我想确保我没有相同图案的袜子。我想我可以通过三种方式做到这一点
class Sock < ActiveRecord::Base
belongs_to :shoe
end
要确定袜子是活动的还是不活动的,请为其所有者鞋提供其活动袜子的参考,如下所示:
class Shoe < ActiveRecord::Base
belongs_to :sock
end
转到它的所有者 Shoe 并检查 Shoe 的活动袜子是否是当前的袜子。例如
def is_active
owner_shoe.active_sock == self
将它们与外键相关联
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
在Rails中,belongs_to
表示模型有外键。例如,如果一只袜子 belongs_to
一只鞋,那么你的袜子 table 将有一个 shoe_id
字段。您可以使用 a number of associations,但是让鞋子和袜子都使用 belongs_to
听起来不必要地复杂。
最直接的解决办法是稍微改变一下语言,把每只袜子想象成一只活动鞋。这样一来,如果您将一只袜子换成另一只鞋,那么您就不需要整理鞋子了。这样您的数据更有可能保持一致。
class Shoe < ActiveRecord::Base
has_one :sock
end
class Sock < ActiveRecord::Base
belongs_to :shoe
end
您现在可以调用 shoe.sock
获取鞋子的活动袜子,或 sock.shoe
获取袜子的鞋子。
或者,您可能希望每只鞋都有一个专门的袜子池。我们可以扩展我们以前的解决方案来支持它,将我们的关系命名为 active_sock
以使事情更清楚,并使用验证器来确保我们的袜子来自池:
class Shoe < ActiveRecord::Base
has_many :socks
has_one :active_sock, class_name: "Sock", foreign_key: "active_shoe_id"
validates :active_sock_id, inclusion: { in: sock_ids }
end
class Sock < ActiveRecord::Base
belongs_to :shoe
def active?
shoe.active_sock == self
end
end
现在您可以调用 shoe.socks
获取鞋子的所有可用袜子,调用 shoe.active_sock
获取活动袜子。从袜子这边,然后 sock.shoe
returns 哪只鞋 "owns" 这只袜子,以及 sock.active?
returns 这只袜子当前是否处于活动状态。
您遇到的问题是您的两项功能存在冲突:
A Shoe
can have many Socks
, but only one active Sock
您希望将两个模型关联到两个不同的关联上。虽然这很简单,但我觉得你尝试做的方式有点受限。
这是我设置基础关联的方式:
#app/models/sock.rb
class Sock < ActiveRecord::Base
#columns id | shoe_id | name | active (boolean) | created_at | updated_at
belongs_to :shoe
end
#app/models/shoe.rb
class Shoe < ActiveRecord::Base
#columns id | name | etc | created_at | updated_at
has_many :socks
scope :active, -> { where(active: true).first }
end
这将使您能够调用:
@shoe = Shoe.find 1
@shoe.socks.active #-> first sock with "active" boolean as true
它也不需要在您的 sock
模型中包含 active?
方法。您可以致电 @shoe.socks.find(2).active?
以获得关于它是否处于活动状态的响应。
现在,应该 可以很好地实现基本功能。
但是,您提到了几个扩展:
if a Sock is active
or inactive
I want to make sure I don't have socks with the same pattern
这增加了我将使用 join
模型 (has_many :through
) 处理的额外规范:
#app/models/sock.rb
class Sock < ActiveRecord::Base
has_many :shoe_socks
has_many :shoes, through: :shoe_socks
end
#app/models/shoe_sock.rb
class ShoeSock < ActiveRecord::Base
# columns id | shoe_id | sock_id | pattern_id | active | created_at | updated_at
belongs_to :shoe
belongs_to :sock
belongs_to :pattern
end
#app/models/shoe.rb
class Shoe < ActiveRecord::Base
has_many :shoe_socks
has_many :socks, through: :shoe_socks, extend: ActiveSock
scope :active, -> { where(active: true).first }
end
您可以阅读以下代码的更多信息here:
#app/models/concerns/active_sock.rb
module ActiveSock
#Load
def load
captions.each do |caption|
proxy_association.target << active
end
end
#Private
private
#Captions
def captions
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({active: items[i]})
return_array.concat Array.new(1).fill( associate )
end
return_array
end
#######################
# Variables #
#######################
#Association
def reflection_name
proxy_association.source_reflection.name
end
#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end
#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end
#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end
#Through
def through_collection
proxy_association.owner.send through_name
end
#Captions
def items
through_collection.map(&:active)
end
#Target
def target_collection
#load_target
proxy_association.target
end
此设置基本上会将所有“逻辑”放入连接模型中。在 IE 浏览器中,您将拥有 socks 数据库、shoes 数据库和一个包含两者配对的连接数据库。
这仍然允许您调用 @shoe.socks.active
,但不必降低数据模型中的数据完整性。
我还添加了一些我不久前写的代码——它使您能够从连接模型访问属性。它使用 ActiveRecord 中的 proxy_association
对象,因此不再调用 SQL.
此添加的代码会将 active?
属性附加到任何关联的 Sock
对象。
你能在 Rails 中建立 belongs_to
belongs_to
关系吗?
Search results 给了我两个结果。事实上,我找不到关于这个主题的太多信息,这似乎表明不应该这样做或者是不好的做法。
我问 yesterday 关于 has_many 关系,但我想因为我找不到这方面的信息,所以我会提出一个问题,这样人们就可以更容易地在未来。我在转述另一个用户的回答(希望没问题)。
一个鞋可以有很多袜子,但只有一个活跃的袜子。其他袜子处于非活动状态。所有的袜子也都是独一无二的,有着独特的图案。我想确保我没有相同图案的袜子。我想我可以通过三种方式做到这一点
class Sock < ActiveRecord::Base
belongs_to :shoe
end
要确定袜子是活动的还是不活动的,请为其所有者鞋提供其活动袜子的参考,如下所示:
class Shoe < ActiveRecord::Base
belongs_to :sock
end
转到它的所有者 Shoe 并检查 Shoe 的活动袜子是否是当前的袜子。例如
def is_active
owner_shoe.active_sock == self
将它们与外键相关联
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
在Rails中,belongs_to
表示模型有外键。例如,如果一只袜子 belongs_to
一只鞋,那么你的袜子 table 将有一个 shoe_id
字段。您可以使用 a number of associations,但是让鞋子和袜子都使用 belongs_to
听起来不必要地复杂。
最直接的解决办法是稍微改变一下语言,把每只袜子想象成一只活动鞋。这样一来,如果您将一只袜子换成另一只鞋,那么您就不需要整理鞋子了。这样您的数据更有可能保持一致。
class Shoe < ActiveRecord::Base
has_one :sock
end
class Sock < ActiveRecord::Base
belongs_to :shoe
end
您现在可以调用 shoe.sock
获取鞋子的活动袜子,或 sock.shoe
获取袜子的鞋子。
或者,您可能希望每只鞋都有一个专门的袜子池。我们可以扩展我们以前的解决方案来支持它,将我们的关系命名为 active_sock
以使事情更清楚,并使用验证器来确保我们的袜子来自池:
class Shoe < ActiveRecord::Base
has_many :socks
has_one :active_sock, class_name: "Sock", foreign_key: "active_shoe_id"
validates :active_sock_id, inclusion: { in: sock_ids }
end
class Sock < ActiveRecord::Base
belongs_to :shoe
def active?
shoe.active_sock == self
end
end
现在您可以调用 shoe.socks
获取鞋子的所有可用袜子,调用 shoe.active_sock
获取活动袜子。从袜子这边,然后 sock.shoe
returns 哪只鞋 "owns" 这只袜子,以及 sock.active?
returns 这只袜子当前是否处于活动状态。
您遇到的问题是您的两项功能存在冲突:
A
Shoe
can have manySocks
, but only one activeSock
您希望将两个模型关联到两个不同的关联上。虽然这很简单,但我觉得你尝试做的方式有点受限。
这是我设置基础关联的方式:
#app/models/sock.rb
class Sock < ActiveRecord::Base
#columns id | shoe_id | name | active (boolean) | created_at | updated_at
belongs_to :shoe
end
#app/models/shoe.rb
class Shoe < ActiveRecord::Base
#columns id | name | etc | created_at | updated_at
has_many :socks
scope :active, -> { where(active: true).first }
end
这将使您能够调用:
@shoe = Shoe.find 1
@shoe.socks.active #-> first sock with "active" boolean as true
它也不需要在您的 sock
模型中包含 active?
方法。您可以致电 @shoe.socks.find(2).active?
以获得关于它是否处于活动状态的响应。
现在,应该 可以很好地实现基本功能。
但是,您提到了几个扩展:
if a Sock is
active
orinactive
I want to make sure I don't have socks with the same pattern
这增加了我将使用 join
模型 (has_many :through
) 处理的额外规范:
#app/models/sock.rb
class Sock < ActiveRecord::Base
has_many :shoe_socks
has_many :shoes, through: :shoe_socks
end
#app/models/shoe_sock.rb
class ShoeSock < ActiveRecord::Base
# columns id | shoe_id | sock_id | pattern_id | active | created_at | updated_at
belongs_to :shoe
belongs_to :sock
belongs_to :pattern
end
#app/models/shoe.rb
class Shoe < ActiveRecord::Base
has_many :shoe_socks
has_many :socks, through: :shoe_socks, extend: ActiveSock
scope :active, -> { where(active: true).first }
end
您可以阅读以下代码的更多信息here:
#app/models/concerns/active_sock.rb
module ActiveSock
#Load
def load
captions.each do |caption|
proxy_association.target << active
end
end
#Private
private
#Captions
def captions
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({active: items[i]})
return_array.concat Array.new(1).fill( associate )
end
return_array
end
#######################
# Variables #
#######################
#Association
def reflection_name
proxy_association.source_reflection.name
end
#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end
#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end
#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end
#Through
def through_collection
proxy_association.owner.send through_name
end
#Captions
def items
through_collection.map(&:active)
end
#Target
def target_collection
#load_target
proxy_association.target
end
此设置基本上会将所有“逻辑”放入连接模型中。在 IE 浏览器中,您将拥有 socks 数据库、shoes 数据库和一个包含两者配对的连接数据库。
这仍然允许您调用 @shoe.socks.active
,但不必降低数据模型中的数据完整性。
我还添加了一些我不久前写的代码——它使您能够从连接模型访问属性。它使用 ActiveRecord 中的 proxy_association
对象,因此不再调用 SQL.
此添加的代码会将 active?
属性附加到任何关联的 Sock
对象。