Как избежать двойного сохранения модели ActiveRecord? - PullRequest
2 голосов
/ 14 марта 2012

Модель "Один"

class One < ActiveRecord::Base
  before_save :do_stuff

  private
    def do_stuff
      two = Two.find(8)
      two.field2 = 'Value'
      two.save!
    end
end

Модель "Два"

class Two < ActiveRecord::Base
  before_save :do_stuff

  private
    def do_stuff
      one = One.find(7)
      one.field2 = 'SomeValue'
      one.save!
    end
end

Выполнение:

two = Two.find(1)
two.somefield = 'NewVal'
two.save!

Запустится бесконечный цикл.Каков был бы наиболее подходящий способ реализации ruby-on-rails двух моделей, которые должны менять друг друга при обратном вызове before_save?

Ответы [ 2 ]

2 голосов
/ 14 марта 2012

Мы надеемся, что в редких случаях вам понадобится отключить фильтр before_save с помощью attr_accessor или переместить его в блок after_save, чтобы избежать зацикливания. Например,

:

class One < ActiveRecord::Base
  attr_accessor :not_doing_stuff
  before_save :do_stuff,
    :unless => :not_doing_stuff

private
  def do_stuff
    two = Two.find(8)
    two.field2 = 'Value'
    two.save!
  end
end

Вы бы отключили триггер, по крайней мере, на одном из них:

class Two < ActiveRecord::Base
  before_save :do_stuff

private
  def do_stuff
    one = One.find(7)
    one.not_doing_stuff = true
    one.field2 = 'SomeValue'
    one.save!
  end
end

Подобные вещи всегда очень уродливы, поэтому старайтесь избегать этого, если только не вспомнитеДругого пути нет.Если вам это нужно, убедитесь, что вы написали достаточно модульных тестов, чтобы гарантировать, что он не будет блокироваться в бесконечный цикл при некоторых крайних случаях.

1 голос
/ 14 марта 2012

Не вызывайте save в before_save: это вызовет бесконечный цикл.Вместо этого верните true или false - true, если все, что вы положили в before_save, успешно выполнено, false, если это не удалось.Возврат false приведет к отмене сохранения и всех других обратных вызовов.

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