views:

25

answers:

2

Hello, I'm creating a observer model: booklogger_observer.rb

The observer model looks a little something like this:

class BookLoggerObserver < ActiveRecord::Observer
  observe :book

  def after_create(record)
     @logitem = ......app specific stuff
     @logitem = ......
     @logitem = ......
     assign_meta(@logitem)
     @logitem.save!
  end

  def after_save(record)
     @logitem = ......
     @logitem = ......
     @logitem = ......
     assign_meta(@logitem)
     @logitem.save!
  end

  def assign_meta(@logitem)
     @logitem = ......
     @logitem = ......
     @logitem = ......
  end

end

Where I'm stuck is I want to use DEF assign_meta to perform actions that are common across after_create and after_save, but I'm not familar with passing the @logitem to the DEF and then sending it back to be saved.

Can you help me understand this flow?

Thank you

A: 

in ruby the last line is what is the output so your after_save and after_create will contain the @logitem so there is no need to pass it back to the def.

You also don't need after_create because create requires a save so it's just redundant.

You might as well just save the variable in the assign_meta if you don't need to do anything else with it but you can save it in the original defs too.

use this if you don't have business after assigning the meta information

def assign_meta(logitem)
    logitem = .....
    logitem.save(false)
 end

use this if you need to do more work back in the original def.

def assign_meta(@logitem)
    @logitem = .....
    @logitem.save(false)
 end
Sam
+1  A: 

You can absolutely use a common method for some of the work in your observer. But there are a couple problems with the other answer. First, a parameter can't be a global (like def assign_meta(@logitem)). Second, calling save actually returns true or false, not the object.

Finally, there is a difference between after_save and after_create, which is why they both exist. after_create allows you to perform certain actions only when the record is brand new - like creating dependencies.

I have an issue with @logitem - what is it? Also, if you're observing the book model, then why is this called the book logger observer? Since your example is purely fictional, I'll try to create an example that works, and is more clear. I'll assume a "logitem" is another model you have setup to track site events:

class BookObserver < ActiveRecord::Observer
  def after_create(book)
    @log_item = LogItem.new :action => "created book"
    assign_meta(@log_item, book)
    @log_item.save!
  end

  def after_save(book)
    @log_item = LogItem.new :action => "saved book"
    assign_meta(@log_item, book)
    @log_item.save!
  end

  protected 

  def assign_meta(log_item, book)
    log_item.item_name = book.name
  end
end

In this example, a new log_item is created. The action description is given, then the common data (in this case, the item_name) is set in the assign_meta method. It's protected because it should only be accessed from inside the other instance methods (after_create, after_save, etc). And the observer is renamed to be more intuitive.

I hope this helps!

Jaime Bellmyer