我有一个如下的客户端模型:
class Client < ActiveRecord::Base
has_many :custodians,:dependent => :destroy
我有一个托管人模型如下:
class Custodian < ActiveRecord::Base
belongs_to :client
在我的保管人表中,我有一个id=0、name="N/A"的记录,我想将其包括在我的所有collection_selections中,而不考虑client_id。
例如,对于client_id=10,我希望在collection_select 中包含以下内容
Custodian.where('client_id = 10 or client_id = 0')
我知道我可以根据自己的观点来做,但我的观点太多了,所以不实用。另外,我想在托管人模型或协会上有一个更DRY的方法。我在托管人模型上尝试了default_scope,但无法使其工作。
基本上,我正在寻找一种方法,在每个关联和collection_select中始终包含id为0的保管人。
使用has_many
和belongs_to
方法无法执行您想要的操作。要实现belongs_to
关系,Custodian
记录必须具有单个client_id
字段。您的逻辑要求custodian_id=0
记录属于许多Client
记录,因此它必须有许多client_id
字段,但只能有一个。请参阅Rails指南活动记录关联下面的关联(http://guides.rubyonrails.org/association_basics.html)
您可以使用has_and_belongs_to_many
关系来完成您想要的任务。通过使Custodian
和Client
模型has_and_belongs_to_many
相互对应,您将能够使custodian_id=0
记录属于许多Client
记录,而所有其他托管记录将只属于一个客户端(即使它们可能属于多个客户端,但您的程序逻辑必须只允许它们属于一个。)请参阅上述Rails指南的has_and_belongs_to_many
部分。需要明确的是,以下是您的模型的外观:
class Client < ActiveRecord::Base
has_many_and_belongs_to_many :custodians
end
class Custodian < ActiveRecord::Base
has_many_and_belongs_to_many :client
end
此外,由于custodian_id=0
的特殊情况,在创建新的Client
记录时,需要使用active_record
回调(可能是before_validation
或before_create
)为custodian_id=0
记录关系建立查找表记录。
类似地,您需要使用before_destroy
回调来实现自己的:dependent => :destroy
功能,以保留custodian_id=0
记录并删除所有其他关联的Custodian
记录。您还必须销毁相应的查找表条目。
这听起来是一项艰巨的工作,但如果你绝对必须将custodian_id=0
记录与每个Client
关联起来,这是我能看到的唯一方法。你可能想评估一下,这真的很有必要。可能还有其他程序逻辑可以让你在不经过这个过程的情况下获得类似的结果。
您可以使用实例或类方法:
#app/models/client.rb
Class Client < ActiveRecord::Base
has_many :custodians,:dependent => :destroy
def inc_zero(id)
where("client_id = ? OR client_id = 0", id)
end
def self.inc_zero_custodians(id)
joins(:custodians).where("client_id = ? OR client_id = 0", id)
end
end
#-> Client.custodians.inc_zero(10)
#-> Client.inc_zero_custodians(10)