Rails: хук для проверки модели, когда она добавляется в родительский ресурс? - PullRequest
0 голосов
/ 30 мая 2010

У меня есть ситуация, когда пользователь отправляет мультимодальную форму. Через эту форму я должен назначить пользователю случайный элемент из моей базы данных вместе с его учетной записью. Когда я перебираю данные, я помечаю назначенный им элемент логическим флагом in_use. Проблема в такой ситуации:

2.times do |n|
   # grab random item which will be parent
   parent = # some random code to grab an item not in use
   parent.in_use = 1
   parent.child.build
   children << child
end

Здесь задействованы три модели. Сам родитель находится внутри своего родителя, следовательно, оператор children << child. Проблема здесь в том, что краевое условие заключается в том, что код, который захватывает неиспользуемый случайный элемент, может захватить одного и того же родителя дважды, поскольку я не знаю ловушки, которая позволит мне сохранить parent.in_use после добавления дочернего элемента его родитель через <code>children << child. Цикл возобновится, флаг in_use не был сохранен в базе данных, и он может выбрать его снова. Есть ли способ сохранить его, а затем откатить, если проверка не удалась в такой ситуации?

Ответы [ 2 ]

0 голосов
/ 01 июня 2010

Ваш вопрос расстраивает, потому что вы говорите, что ваша проблема связана с двойным использованием одного и того же родителя, но код для извлечения родителя опущен. Тем не менее, код для нерелевантной запутанной контекстной 3-модельной взаимосвязи оставлен в.

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

С моей точки зрения, это звучит как кошмар. Как кто-то, кто написал ужасно запутанный код с ошибками, подобный этому, я настоятельно рекомендую вам сначала получить двух разных родителей. Не позволяйте ошибкам распространяться по вашему приложению, содержать их раньше или, что еще лучше, не допускать их возникновения:

class YourUnnamedModel < ActiveRecord::Base
  named_scope :unused  , :conditions => { :in_use => false }
  named_scope :random  , :order => 'RANDOM()'
  named_scope :limited , lambda { |n=1| return :limit => n }

  def self.example
    unused.random.limited(2).each do |parent|
      puts "doing stuff with #{parent.inspect}"
    end
    nil
  end

end

Предостережение: по какой-то глупой причине (https://rails.lighthouseapp.com/projects/8994/tickets/1274-patch-add-support-for-order-random-in-queries), возможно, что ваш 'RANDOM ()' может быть назван как-то еще.

0 голосов
/ 31 мая 2010

Это работает?

2.times do |n|
  # grab random item which will be parent
  parent = # some random code to grab an item not in use
  parent.child.build
  parent.in_use
  parent.save # <--- save the parent on the db
  children << child
end

Я не уверен насчет последней строки, так как вы не объяснили, что такое переменная children. Я также предполагаю, что parent.in_use - это метод, а не свойство (в противном случае вам придется написать parent.in_use = true или что-то подобное)

Еще одна вещь - кажется, вы используете внешний атрибут (называемый in_use или аналогичный) для того, чтобы сохранить, есть ли у родителя дочерние элементы. Вероятно, было бы проще просто посчитать количество детей. Есть несколько способов сделать это, но хорошим компромиссом является использование автоматического счетчика кэша.

class Parent << ActiveRecord::Base
  has_many :children, :counter_cache => true #this will had a children_count attribute

Атрибут назван так же, как таблица детей. Поэтому, если вы напишите has_many :issues, счетчик будет issues_Count.

Вам нужно будет добавить атрибут children_count в таблицу родителя.

Затем вы можете сделать if parent.children_count > 0 вместо проверки странных атрибутов parent.in_use.

Дополнительная информация о кеше счетчика на railscast # 23

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...