Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom callbacks with observer in rails3

i'm desperate with one problem.

i want to register custom callback :after_something and then use that callback into observer.

I have try with define_callbacks, set_callbacks but observer never trigger that callback.

I know that i can use AR callbacks, but i just prefer in some situation to use my own callbacks.

Thanks

like image 699
vule Avatar asked Feb 21 '11 11:02

vule


3 Answers

Here is a solution if someone looking for:

in your model call this:

notify_observers(:after_my_custom_callback)

In your observer just define method:

def after_my_custom_callback(record)

 #do things
end
like image 193
Alex Avatar answered Oct 02 '22 18:10

Alex


Observer use standard AR callbacks so it will not trigger your default one.

I think rather that inventing new callback (and monkeypatch default behaviour of AR) maybe you should use AR's. It is difficult to say what do you want. Can you give some use case?

try maybe something like

before_save MyCallbacks.new, :if => :some_condiditons_meet?

class MyCallbacks
  def before_save(object)
    sophistcated_use(object) if object.valid?
    damn_have_it?
  end
end

it actually covers behaviour of observer at some level

<--update-->

The entire callback chain of a save, save!, or destroy call runs within a transaction. That includes after_* hooks. If everything goes fine a COMMIT is executed once the chain has been completed.

I think the whole Idea of SINGLE observer is not best solution. After more dependencies will arrive your logic will be very complicated. Defining own transaction wrappers is good, but do you really need it? Maybe you can rearrange model for achieve it without writing up own transaction case.

For instance

class Friendship < ActiveRecord::Base
  belongs_to :user
  has_many :users, :through => :groups

  after_validation :save_my_records

  def save_my_records
    user.friend.history.save
    user.history.save
  end

end

Where friend is object => has got own observer where history is object => has got own observer

It is very abstract, but without your code I had no idea how to give some constructive example also after_validation is not best place to saving anything I think.

also notify_observer sound like hack to me :-)

like image 32
Piotr Mąsior Avatar answered Oct 02 '22 19:10

Piotr Mąsior


Thanks to Alex's answer I could solve this problem by defining a define_model_callbacks_for_observers method that should be called instead of define_model_callbacks (you might want to put this into a module):

def define_model_callbacks_for_observers(*args)
  types = Array.wrap(args.extract_options![:only] || [:before, :around, :after])

  callbacks = define_model_callbacks(*args)

  callbacks.each do |callback|
    types.each do |filter|
      set_callback(callback, filter) do
        notify_observers :"#{filter}_#{callback}"
        true
      end
    end
  end
end
like image 28
lacco Avatar answered Oct 02 '22 18:10

lacco