使用ActiveRecord,我有一个对象,客户端,零个或多个用户(即通过has_many关联).客户端还具有可以手动设置的“primary_contact”属性,但始终必须指向其中一个关联用户.即如果没有关联用户,primary_contact只能为空.
实现客户端的最佳方式是:
a)第一次将用户添加到客户端时,primary_contact被设置为指向该用户?
b)除非删除所有用户,否则始终保证primary_contact位于用户关联中? (这有两个部分:设置新的primary_contact或从关联中删除用户时)
换句话说,我如何指定和重新分配给定客户的用户之一的“主要联系人”的标题?我已经使用了大量的过滤器和验证,但我无法做到这一点.任何帮助,将不胜感激.
更新:虽然我确定有无数的解决方案,但我最终让用户在删除时通知客户端,然后在客户端使用before_save调用来验证(并设置,如果需要)其primary_contact.用户在删除之前会触发此调用.在更新关联时,这并没有捕获所有边缘情况,但它足以满足我的需要.
最佳答案 我的解决方案是在连接模型中执行所有操作.我认为这可以在客户端转换到零关联或从零关联转换时正常工作,如果存在任何现有关联,则始终保证指定主要联系人.我有兴趣听到任何人的反馈.
我是新来的,所以不能评论下面的弗朗索瓦.我只能编辑自己的条目.他的解决方案假定用户与客户是一对多,而我的解决方案假设有很多对很多人.我认为用户模型可能代表了“代理”或“代表”,并且肯定会管理多个客户端.在这方面,问题含糊不清.
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