2012-03-30 4 views
2

Я хочу, чтобы проверка выполнялась до того, как запись будет обновлена. Я знаю before_update, но я в значительной степени копировал и вставлял первые коды из api docs.Почему этот обратный вызов выполнен?

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 => "[email protected]").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", "[email protected]"], ["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 => "[email protected]").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", "[email protected]"], ["first_name", nil], ["last_name", nil], ["updated_at", Fri, 30  Mar 2012 02:28:45 UTC +00:00]] 
    (131.2ms) commit transaction 
=> true 
+0

Такое же поведение в обычном запуске приложения. – mober

+0

Возможно, я что-то пропустил, но ничего не вижу в документах о передаче '(: on =>: update)' before_save и почему бы не использовать 'before_update'? –

+0

Как я упоминал ранее, я знаю, что есть 'before_update', но сегодня случилось, что у меня открылись документы, когда мне это было нужно, и это не сработало. ': on' объясняется для валидаций в руководствах -> http://edgeguides.rubyonrails.org/active_record_validations_callbacks.html#, когда обратные вызовы поступают сразу после него, и в документах снова упоминается шаблон': on'. Поэтому я вытащил строки ... – mober

ответ

3

ActiveRecord :: Callbacks сделать не Suppo к.т. в :on вариант ...

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

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

0

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

Текущий путь более чистый и более явный.

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

+0

Thanx для ссылки. Я проверю это. – mober

0

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

+0

Я просто изменил его на вызов функции. Те же результаты. Обратный вызов выполняется при создании. Thanx для ссылки. Я иду и проверяю это. – mober

+0

Я только что вернулся из упомянутого blogpost, и что-то не так, что он там делает ... Его отношение говорит, что его текущий_модель 'принадлежит_от: credit_card' и имеет обратный вызов' before_create: build_credit_card' Это означает, что дочерний объект 'current_model' создает родительский элемент в обратном вызове ... что наиболее похоже неправильно. Кроме того, ограничения foreign_key тоже неправильны, что заставляет порядок, на котором конец отношения вызывается, и прочее. – mober

+0

@mober, re: сообщение в блоге, если они сначала сохраняют кредитную карту в обратном вызове и присваивают ее текущей модели, тогда отношение 'own_to' будет автосохранять эти отношения. Таким образом, это правильный способ создания этого ... – kafuchau

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