2014-01-12 5 views
0

У меня есть модель Tag, и может существовать иерархия из нескольких Tag s: то есть некоторый Tag может быть супер- или субтегем другого тега и т. Д.Rails: проверка группы элементов

Примечание: есть не одно большое дерево тегов; это всего лишь несколько отдельных тегов, а иногда один тег - супер-тег для другого одного или нескольких тегов. Он отлично работает.

Каждый Tag также belongs_to :user.

Существует ограничение: все Tag s в иерархии должны принадлежать одному и тому же User. Я попытался реализовать это ограничение с помощью системы проверки Rails, но мне не удалось. Давайте посмотрим, почему:

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

Предположим, что мы имеем простую иерархию 3 теги:

tag1 -> tag2 -> tag3 

Каждый из этих тегов принадлежит одному и тому же пользователю (например, «user1»).

В один прекрасный день мне нужно сменить владельца на «user2». На самом деле невозможно, чтобы пользователи проверяли всю иерархию перед сохранением каждого тега.

Скажем, я пытаюсь сделать что-то вроде этого:

tag1.owner = user2 
tag2.owner = user2 
tag3.owner = user2 

, а затем сохранить каждую метку. Но когда я пытаюсь сохранить первый тег, все остальные еще не сохранены, а пользователь, хранящийся в БД для этих тегов, - «user1». Проверка не выполняется.

Решение может заключаться в том, чтобы сохранить сразу все теги (как одну «транзакцию»), а затем проверить все теги, затронутые этой транзакцией, и если все они действительны, то совершите транзакцию; в противном случае откат. Это было бы просто идеально, и это может выглядеть синтаксически как-то так:

tag1.owner = user2 
tag2.owner = user2 
tag3.owner = user2 

transaction do 
    tag1.save 
    tag2.save 
    tag3.save 
end 

И это все! Но, насколько я знаю, в Rails ничего подобного не поддерживается. Но какова лучшая практика для того, чтобы делать то, что мне нужно? В настоящее время я просто отключил эту проверку, но мне не очень нравится это «решение».

ответ

0

Я не знаю, о передовом опыте, но так как никто не ответил, и это было в то время, я думал, что я отправлю, что вы можете сделать:

tag1.owner = user2 
tag2.owner = user2 
tag3.owner = user2 

tag1.transaction do 
    tag1.save! 
    tag2.save! 
    tag3.save! 
end 

потому

  • Сделки «за» соединение с базой данных и метода transaction определяется как оба класса и метод экземпляра ActiveRecord::Base
  • в отличие от save, save! сама по себе не обернуты в сделка

, как описано в http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

Смежные вопросы