2009-04-28 4 views
4

ActiveRecordを使用して、私は0以上のユーザが(has_many関連を介して)オブジェクトClientを持っています。クライアントには、手動で設定できる 'primary_contact'属性もありますが、常に関連するユーザーの1つを指し示す必要があります。私。 primary_contactは、関連付けられたユーザーがいない場合のみ空白にすることができます。ActiveRecordアソシエーションの特定のオブジェクトに対する有効な参照を作成/維持するにはどうすればよいですか?

a)は、ユーザがクライアントに追加された最初の時間は、primary_contactは、そのユーザーを指すように設定されています

クライアントように実装するための最良の方法は何ですか?

b)すべてのユーザーが削除されない限り、primary_contactは常にユーザーの関連付けに含まれますか?

つまり、「プライマリコンタクト」のタイトルを特定のクライアントのユーザーの1人に指定して再割り当てするにはどうすればよいですか?私は数多くのフィルタとバリデーションを手がかりにしてきましたが、それは正しくできません。どんな助けもありがとう。


UPDATE:私はソリューションの無数があると確信しているが、私はそれを削除してから検証するためにクライアントにbefore_saveコールを使用して(必要に応じて設定)されているときに、ユーザーがクライアントに通知したことになりましたそのprimary_contact。この呼び出しは、削除される直前にユーザーによってトリガーされます。これはアソシエーションを更新するときにすべてのエッジケースを捕捉するわけではありませんが、必要なものに対しては十分です。

答えて

1

私はソリューションの無数があると確信しているが、私はそのprimary_contactそれは削除してから検証するためにクライアントにbefore_saveコールを使用して(必要に応じて設定)されているときに、ユーザーがクライアントに通知したことになりました。この呼び出しは、削除される直前にユーザーによってトリガーされます。これはアソシエーションを更新するときにすべてのエッジケースを捕捉するわけではありませんが、必要なものに対しては十分です。

1

私のソリューションは、結合モデルですべてを行うことです。私はこれがゼロ協会への、またはゼロアソシエーションからのクライアントの移行で正しく動作すると思います。既存の関連があれば、常にプライマリコンタクトが指定されます。私は誰の意見を聞くことに興味があるでしょう。


私はここにいるので、以下のFrançoisにはコメントできません。自分のエントリーを編集することしかできません。彼のソリューションでは、クライアントとユーザーは1対多であると仮定していますが、私のソリューションでは多くのことを想定しています。私はユーザーモデルがおそらく "代理人"または "代理人"を表していたと思っていたし、確かに複数のクライアントを管理するだろう。これに関しては疑問が曖昧です。


class User < ActiveRecord::Base 
    has_many :user_clients, :dependent => true 
    has_many :clients, :through => :user_client 

end 

class UserClient < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :client 

    # user_client join table contains :primary column 

    after_create :init_primary 
    before_destroy :preserve_primary 

    def init_primary 
    # first association for a client is always primary 
    if self.client.user_clients.length == 1 
     self.primary = true 
     self.save 
    end 
    end 

    def preserve_primary 
    if self.primary 
     #unless this is the last association, make soemone else primary 
     unless self.client.user_clients.length == 1 
     # there's gotta be a more concise way... 
     if self.client.user_clients[0].equal? self 
      self.client.user_clients[1].primary = true 
     else 
      self.client.user_clients[0].primary = true 
     end 
     end 
    end 
    end 

end 

class Client < ActiveRecord::Base 
    has_many :user_clients, :dependent => true 
    has_many :users, :through => :user_client 

end 
0

私は、ユーザーのブール属性を使用してこれを行うだろう。 #has_oneを使用すると、このブール値がtrueに設定されている最初のモデルを見つけることができます。

class Client < AR::B 
    has_many :users, :dependent => :destroy 
    has_one :primary_contact, :class_name => "User", 
          :conditions => {:primary_contact => true}, 
          :dependent => :destroy 
end 

class User < AR::B 
    belongs_to :client 

    after_save :ensure_only_primary 
    before_create :ensure_at_least_one_primary 
    after_destroy :select_another_primary 

    private 
    # We always want one primary contact, so find another one when I'm being 
    # deleted 
    def select_another_primary 
    return unless primary_contact? 
    u = self.client.users.first 
    u.update_attribute(:primary_contact, true) if u 
    end 

    def ensure_at_least_one_primary 
    return if self.client.users.count(:primary_contact).nonzero? 
    self.primary_contact = true 
    end 

    # We want only 1 primary contact, so if I am the primary contact, all other 
    # ones have to be secondary 
    def ensure_only_primary 
    return unless primary_contact? 
    self.client.users.update_all(["primary_contact = ?", false], ["id <> ?", self.id]) 
    end 
end 
関連する問題