Как создать / сохранить действительную ссылку на определенный объект в ассоциации ActiveRecord? - PullRequest
4 голосов
/ 28 апреля 2009

Используя ActiveRecord, у меня есть объект, Клиент, который равен нулю или более Пользователям (т.е. через ассоциацию has_many). Клиент также имеет атрибут «primary_contact», который можно установить вручную, но всегда должен указывать на одного из связанных пользователей. То есть primary_contact может быть пустым, только если нет связанных пользователей.

Какой лучший способ реализовать Клиент, такой:

a) При первом добавлении пользователя к клиенту primary_contact указывает на этого пользователя?

b) Первичный_контакт всегда гарантированно входит в ассоциацию пользователей, если только все пользователи не удалены? (Это состоит из двух частей: при установке нового primary_contact или удалении пользователя из ассоциации)

Другими словами, как я могу назначить и переназначить название «основного контакта» одному из пользователей данного клиента? Я возился с многочисленными фильтрами и проверками, но я просто не могу понять это правильно. Любая помощь будет оценена.


ОБНОВЛЕНИЕ: Хотя я уверен, что существует множество решений, я закончил тем, что Пользователь информировал Клиента, когда он удаляется, и затем использовал вызов before_save в Клиенте для проверки (и установки, если необходимо) его primary_contact. Этот вызов инициируется пользователем непосредственно перед его удалением. Это не охватывает все крайние случаи при обновлении ассоциаций, но достаточно для того, что мне нужно.

Ответы [ 3 ]

1 голос
/ 23 февраля 2010

Хотя я уверен, что существует множество решений, я закончил тем, что Пользователь информировал Клиента, когда он удаляется, и затем использовал вызов before_save в Клиенте для проверки (и установки, если необходимо) его primary_contact. Этот вызов инициируется пользователем непосредственно перед его удалением. Это не охватывает все крайние случаи при обновлении ассоциаций, но достаточно для того, что мне нужно.

1 голос
/ 28 апреля 2009

Мое решение - сделать все в модели соединения. Я думаю, что это работает правильно при переходах клиента в или из нулевых ассоциаций, всегда гарантируя, что основной контакт назначен, если есть какая-либо существующая ассоциация Мне было бы интересно услышать чей-либо отзыв.


Я новичок здесь, поэтому не могу комментировать Франсуа ниже. Я могу редактировать только свою собственную запись. Его решение предполагает, что пользователь-клиент - один ко многим, в то время как мое решение предполагает много ко многим. Я думал, что пользовательская модель представляет собой «агента» или «представителя», и, несомненно, будет управлять несколькими клиентами. В этом отношении вопрос неоднозначен.


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 голосов
/ 28 апреля 2009

Я бы сделал это, используя логический атрибут для пользователей. #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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...