您遇到的问题是您的两个功能相互冲突:
一个Shoe 可以有多个Socks,但只有一个活动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? 以获取有关它是否处于活动状态的回复。
现在,这个应该可以很好地用于基本功能。
但是,您提到了几个扩展:
如果 Sock 是 active 或 inactive
我想确保我没有相同图案的袜子
这增加了额外的规格,我将使用 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 对象。