Почему этот обратный вызов выполняется? - PullRequest
2 голосов
/ 30 марта 2012

Я хочу запустить проверку перед обновлением записи. Я знаю о before_update, но я в значительной степени скопировал и вставил первый кодовый код из документации API.

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Моя урезанная модель выглядела тогда как

class User < ActiveRecord::Base
  attr_accessible :email
  validates :email, :presence => true

  before_save(:on => :update) do
    puts "******** before_save on => :update ********"
    # do something
  end
end

если я захожу в консоль и создаю новую запись, этот обратный вызов выполняется при вызове вставки SQL.

irb(main):001:0> User.new(:email => "test@test.com").save
  (0.1ms)  begin transaction
******** before_save on => :update ********
SQL (29.1ms)  INSERT INTO "users" ("created_at", "email", "first_name", "last_name", "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Fri, 30 Mar 2012 00:26:33 UTC +00:00], ["email", "test@test.com"], ["first_name", nil], ["last_name", nil], ["updated_at", Fri, 30 Mar 2012 00:26:33 UTC +00:00]]
   (433.1ms)  commit transaction
=> true
irb(main):002:0> 

Я бы ожидал увидеть это только при обновлении. Кто-нибудь может пролить свет на это?

[EDIT]

Я просто изменил обратный вызов на вызов функции без изменений в результате. Обратный вызов все еще выполняется при создании.

class User < ActiveRecord::Base

attr_accessible :email
validates :email, :presence => true

before_save :my_before_update, :on => :update

private

def my_before_update
    puts "******** before_save on => :update ********"
    # do something
end

конец

Вывод такой же.

Loading development environment (Rails 3.2.2)
irb(main):001:0> User.new(:email => "test@test.com").save
   (0.1ms)  begin transaction
******** before_save on => :update ********
  SQL (28.2ms)  INSERT INTO "users" ("created_at", "email", "first_name", "last_name",         "updated_at") VALUES (?, ?, ?, ?, ?)  [["created_at", Fri, 30 Mar 2012 02:28:45 UTC +00:00],     ["email", "test@test.com"], ["first_name", nil], ["last_name", nil], ["updated_at", Fri, 30     Mar 2012 02:28:45 UTC +00:00]]
   (131.2ms)  commit transaction
=> true

Ответы [ 3 ]

3 голосов
/ 30 марта 2012

ActiveRecord :: Обратные вызовы не поддерживают опцию :on ...

Из кодовой базы Rails единственное место, где упоминается обработка опции :on, находится в коде модуля проверки в ActiveModel :: Validations .

Если вы посмотрите код ActiveRecord :: Callbacks , вы увидите, что в нем нет упоминания :on, и модуль ActiveRecord :: Callbacks не включает в себя какой-либо из модуля ActiveModel :: Validations это будет обрабатывать эту опцию. Существует включение для ActiveModel :: Validations :: Callbacks, но оно просто предоставит определения для методов проверки before_ и after_. Однако обратные вызовы before_validation и after_validation будут обрабатывать опцию :on, как видно здесь в их определениях.

0 голосов
/ 30 марта 2012

После небольшого исследования, похоже, что вы правы, похоже, что вы можете передать :on => :update в before_save

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

before_save :run_this_before_update, :on => :update

def run_this_before_update
  puts "******** before_save on => :update ********"
  # do something
end

Похоже, что основной причиной использования этого является порядок, в котором Rails запускает обратные вызовы, посмотрите эту превосходную статью из сводных таблиц http://pivotallabs.com/users/danny/blog/articles/1767-activerecord-callbacks-autosave-before-this-and-that-etc-

0 голосов
/ 30 марта 2012

Я почти уверен, что это одна из тех областей, в которой Rails API менялся в разных версиях. Я помню, что был способ передать :on в качестве опции before_save, точно так же, как я вспоминаю, когда нужно было определить метод after_initialize (он не был доступен в качестве обратного вызова).

Нынешний способ чище и понятнее.

Если вы обнаружите, что текущая ссылка на документ before_save(:on => :update), проверьте новый репозиторий docrails Github, в котором вы можете форкать, изменять и фиксировать изменения в документах, которые будут включены (не требуются или не принимаются запросы на получение).

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