У меня вопрос для новичков. Я пытаюсь убедиться, что у модели есть хотя бы одна связь через отношение HABTM. В основном я создал следующую проверку:

validate :has_tags?
def has_tags?
    errors.add(:base, 'Must have at least one tag.') if self.tags.blank?
end

Это отлично работает, когда я создаю новую запись. Проблема в том, что я беру модель и пытаюсь удалить ассоциацию, делая что-то вроде этого:

tag = Tag.find(params[:tag_id])$
@command.tags.delete(tag)$

Это разрешено, т.е. ассоциация будет удалена. На основе моих чтений об ассоциациях HABTM (http: / /guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association), я должен «использовать has_many: through, если вам нужны проверки, обратные вызовы или дополнительные атрибуты в объединении. модель."

Думаю, мой вопрос в том, как выполнить проверку метода .delete для ассоциации. Должен ли я делать это вручную, когда я вызываю удаление (т. Е. Запускаю отдельное соединение для подсчета количества ассоциаций перед выполнением удаления), или есть способ использовать модель проверки при удалении? Вот моя модель:

class Command < ActiveRecord::Base
  has_many :tagmapsorters
  has_many :tags, through: :tagmapsorters
  validates :text, presence: true
  validates :description, presence: true
  validates :text, uniqueness: true
  validate :has_tags?
  def has_tags?
    errors.add(:base, 'Must have at least one tag.') if self.tags.blank?
  end
end

Я ценю, что вы нашли время помочь мне.

Дэн

1
a2f0 22 Янв 2014 в 06:24

1 ответ

Лучший ответ

Любые обратные вызовы, которые вам нужны, должны быть зарегистрированы как before_destroy (для проверки) или after_destroy (для очистки) в модели соединения Tagmapsorter, поскольку это запись, которая фактически уничтожается.

1
PinnyM 22 Янв 2014 в 06:55
Это верно. Спасибо. Моя проблема заключалась также в том, что я вызывал .delete через ассоциацию, то есть @ command.tags.delete (tag), вместо использования .destroy, то есть @ command.tagmapsorters.find_by (tag_id: params [: tag_id]). Destroy. delete не запускает обратный вызов.
 – 
a2f0
22 Янв 2014 в 10:31
- просто замените destroy вместо delete (например, @command.tags.destroy(tag)). В противном случае вам не нужно менять синтаксис.
 – 
PinnyM
22 Янв 2014 в 18:55