What is purpose of around_create callback in Rails

2020-05-26 09:35发布

问题:

when is around_create callback code executed, in what situations we should use it?

回答1:

Had this question, too, and have now found the answer: around_create allows you to basically do both a before_create and an after_create in one method. You have to use yield to execute the save in between.

class MyModel < ActiveRecord::Base
  around_create :my_callback_method

  private
    def my_call_back_method
      # do some "before_create" stuff here

      yield  # this makes the save happen

      # do some "after_create" stuff here
    end
end


回答2:

Just found one use case for me:

Imagine a situation with polymorphic watcher and the watcher in some cases needs to perform action before save and in other cases after it.

With around filter you can capture save action in a block and run it when you need.

class SomeClass < ActiveRecord::Base

end

class SomeClassObserver < ActiveRecord::Observer
  def around_create(instance, &block)
    Watcher.perform_action(instance, &block)
  end
end

# polymorphic watcher
class Watcher
  def perform_action(some_class, &block)
    if condition?
      Watcher::First.perform_action(some_class, &block)
    else
      Watcher::Second.perform_action(some_class, &block)
    end
  end
end

class Watcher::First
  def perform_action(some_class, &block)
    # update attributes
    some_class.field = "new value"

    # save
    block.call
  end
end

class Watcher::Second
  def perform_action(some_class, &block)
    # save
    block.call

    # Do some stuff with id
    Mailer.delay.email( some_class.id )
  end
end


回答3:

A classic use-case for the "around" filters is to measure performance, or log or do other state monitoring or modification.



回答4:

Besides Tom Harrison Jr's answer about logging and monitoring, I'm finding that the key differentiator is to gain control over whether or not the operation runs at all. Otherwise, you can implement your own before_* and after_* callbacks to do the same thing.

Take around_update, for example. Let's say you have a case where you don't want the update to run. For example, I'm building a gem that saves drafts in another drafts table but doesn't save certain updates to the "master" table.

around_update :save_update_for_draft

private

def save_update_for_draft
  yield if update_base_record?
end

The details of the update_base_record? method referenced here don't really matter. You can see that the update operation simply won't run if that method doesn't evaluate to true.



回答5:

around_create is called when a model with the new? flag is saved. It can be used to add data to add/change values of the model, call other methods, etc... I cannot thnk of a specific use case for this call-back but it completes a set of "before, after, around" call-backs for the create action. There is a similar "before, after, around" call back set for the find, update, save, and delete events.



回答6:

Simpler and neat explanation about around callback I found, is given below

The around_* callback is called around the action and inside the before_* and after_* actions. For example:

class User
  def before_save
    puts 'before save'
  end

  def after_save
    puts 'after_save'
  end

  def around_save
    puts 'in around save'
    yield # User saved
    puts 'out around save'
  end
end

User.save
  before save
  in around save
  out around save
  after_save
=> true

Originally posted here