has_many 関連付けを持つ 2 つのモデルがあります。ただし、「多数」のうち、プライマリは 1 つだけです。これを設計する 1 つの方法を次に示します。
アプローチ #1
class Person < ActiveRecord:Base
has_many :address
def find_primary
self.address.where('is_primary = ?', "true").first
end
end
class Address < ActiveRecord:Base
belongs_to :person
attr_protected :is_primary
def make_primary
self.person.address.each { |a| a.update_attribute(:is_primary, false) }
self.update_attribute(:is_primary,true)
end
def is_primary?
self.is_primary
end
end
make_primary
その人の住所の数がO(n)であるのが好きではありません。また、マルチスレッド環境 (つまりパッセンジャーですよね?) でも問題になる可能性があります。make_primary
たぶん、アプローチ#2でよりうまく機能する最適化があるでしょうか?
また、複数のアドレスをプライマリにすることができる、見つけにくいバグが簡単に発生する可能性があります。
アプローチ #2
class Person < ActiveRecord:Base
has_many :address
belongs_to :primary_address, :class_name => 'Address', :foreign_key => :primary_address_id
end
class Address < ActiveRecord:Base
belongs_to :person
has_one :person_as_primary, :class_name => 'Person', :foreign_key => :primary_address_id
def make_primary
self.person.primary_address = self
self.save!
end
end
マルチスレッドと O(n) の問題を回避することは別として、このアプローチはfind_primary
単にself.primary_address
.
ただし、ここで懸念されるのは、その保証がないことです。
[person, nil].include?(person.primary_address.person_as_primary)
ここに私の質問があります:
1)私が言及しなかった追加の利点/欠点はありますか?
2) 他にどのようなアプローチを検討する必要がありますか? 特に、上記の問題のいずれも発生しないものはありますか?