ruby-on-rails – 如何在ActiveRecord关联中创建/维护对特定对象的有效引用?

使用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
点赞