Рельсы заставляют модель требовать другую модель

Если у меня есть has_and_belongs_to_many связь между двумя моделями, скажем Users и Accounts, могу ли я потребовать, чтобы у User был хотя бы один Account, и как?

Кроме того, используя отношение has_and_belongs_to_many, может ли Account не иметь User?

Что мне нужно, так это отношения, в которых Accounts может жить самостоятельно и принадлежать Billers, но они также могут принадлежать Users, если User подписался с ним. Возможно ли это и как?


person macdamaniac    schedule 12.07.2012    source источник


Ответы (2)


Я бы лично отказался от HABTM. Вместо этого я бы использовал has_many :though=>

Вам нужно будет создать две новые модели account_users и account_billers. Скорее всего, у вас уже есть таблицы соединений для HABTM, но это сделает их моделями, поэтому им потребуются поля идентификаторов.

Таким образом, вы получите что-то вроде следующего:

class Account < ActiveRecord::Base
  has_many :account_billers
  has_many :account_users

  has_many :billers, :through=> :account_billers
  has_many :users, :through=> :account_users
end

class User < ActiveRecord::Base
  has_many :account_users
  has_many :accounts, :through=>:account_users

  validates :accounts, :length => { :minimum => 1}
end

class Biller < ActiveRecord::Base
  has_many :account_billers
  has_many :accounts, :through=>:account_billers

  validates :accounts, :length => { :minimum => 1}
end

class AccountUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :account
end

class AccountBiller < ActiveRecord::Base
  belongs_to :biller
  belongs_to :account
end
person Ben Miller    schedule 12.07.2012
comment
Это установило бы требование, чтобы у пользователей и биллеров были учетные записи, но учетные записи могли бы существовать без пользователя или биллера. - person Ben Miller; 12.07.2012

Чтобы проверить наличие хотя бы одной ассоциации, вы можете использовать собственный метод проверки, что-то вроде

class User < ActiveRecord::Base
  has_and_belongs_to_many :accounts
  validate :require_at_least_one_account

  private
    def require_at_least_one_account
      errors.add(:accounts, "must amount to at least one") if accounts.size < 1
    end
end

(Хотя это вызывает вопрос о том, как учетная запись распределяется между пользователями)

Что касается вашего второго вопроса, похоже, вы ищете полиморфные ассоциации, но вы не можете сделать это напрямую с помощью отношения HABTM, вам придется изменить его на has_many :through и ввести модель соединения.

person HargrimmTheBleak    schedule 12.07.2012
comment
Вы можете использовать полиморфизм, но нет хорошего способа сделать ограничения FK с полиморфизмом. Если user1521444 еще не очень хорошо разбирается в моделях и отношениях, я бы избегал этого. - person Ben Miller; 13.07.2012
comment
С полиморфными ассоциациями кажется, что вы можете иметь учетную запись, принадлежащую либо пользователю, либо биллеру, но может ли одна и та же учетная запись принадлежать обоим при полиморфной ассоциации? - person macdamaniac; 13.07.2012
comment
Если у вас могут быть учетные записи, принадлежащие как пользователям, так и биллерам одновременно, я не думаю, что AR поддерживает это из коробки. Вы можете проверить этот вопрос stackoverflow.com/questions/3209322/rails-polymorphic -has-many - person HargrimmTheBleak; 13.07.2012