Rails has_many, сборка, обратное_оф

#ruby-on-rails #ruby-on-rails-3 #activerecord #associations #has-many

#ruby-on-rails #ruby-on-rails-3 #activerecord #ассоциации #имеет-много

Вопрос:

У меня есть 2 модели, подобные такой:

 class User < ActiveRecord::Base
    has_many :user_services, :inverse_of => :user

    validates_length_of :user_services, :maximum => 3
end

class UserService < ActiveRecord::Base
    belongs_to :user, :inverse_of => :user_services

    validates_associated :user
end
  

Я хотел бы сделать что-то вроде:

 user_service = user.user_services.build(...)
if user_service.save
...
  

но это выдает ошибку «слишком глубокий уровень стека». Я предполагаю, что из-за validates_associated в сочетании с inverse_of . Кто-нибудь знает, почему это происходит?

Вызов save непосредственно для объекта user, а не для объекта user_service, похоже, работает, но мне интересно, есть ли способ добиться этого в обратном порядке.

Спасибо!

Ответ №1:

Это происходит потому, что ваши проверки имеют циклическую зависимость.

 validates_length_of :user_services
validates_associated :user
  

http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_associated

Обновить

Вы можете удалить циклическую зависимость, если перепишете свой код таким образом:

 class User < ActiveRecord::Base
  has_many :user_services, :inverse_of => :user
  validates_length_of :user_services, :maximum => 3
end

class UserService < ActiveRecord::Base
  belongs_to :user, :inverse_of => :user_services

  def user_services_amount
     return 0 if self.user.nil?
     self.user.user_services.length
  end

  validates :user_services_amount, :inclusion => { :in => 0..3 }
end
  

Комментарии:

1. Спасибо! Да, похоже, это как-то связано с этой проблемой, которую я нашел: rails. lighthouseapp.com/projects/8994/tickets /…

2. Добавьте решение этой циклической проблемы

3. Хорошее решение. Но, похоже, требуется повторный рефакторинг магического числа : вы могли бы убрать magic 3 из всех проверок с помощью User.max_services_allowed метода.

4. Спасибо за доработку! Работает хорошо.

5. Вероятно, связано с этими проблемами: 7809 , 16640