views:

206

answers:

3

Hi,

We are using AASM in quite a few of our models, but we're looking at simplifying a bit the models. One of the things we'd like to do is to move all the Notification stuff out of the models and into Observers.

So considering:

class ClarificationRequest < ActiveRecord::Base
  include AASM

  aasm_initial_state :open

  # States
  aasm_state :open
  aasm_state :closed

  # Events
  aasm_event :close, :after => :notify_closed do transitions :to => :closed, :from => [:open,:replied], :guard => :can_close? end
end

I've tried this, but with no luck:

class ClarificationRequestObserver < ActiveRecord::Observer
  observe :clarification_request

  def after_close
    puts '############### message from observer!!!!!'
  end
end

How can I move the :notify_closed to an Observer?

Thx!

.Karim

A: 

To be honest I think how you had it is fine. It makes sense to use the AASM hooks for stuff like this. This way you know it's transitioned OK and then you send the notification.

You could look at using active record dirty in a before_update to check if the state_was open and now closed.

tsdbrown
One of the major problems we have with this approach is that we actually want to create Events (kind of an audit model) that also needs to have the current_user_id, and there is, as far as i know, no easy or proper way to include that in Models... hence the observers?
khelal
Although this may not be ideal you can get the user id like this: In the User model add cattr_accessor :current_user. In the application controller add a before_filter that calls def set_current_user User.current_user = self.current_user
tsdbrown
+1  A: 

I've reply to your comment on github before, I'll repeat it here, just in case

class ClarificationRequest < ActiveRecord::Base
    include AASM

    aasm_initial_state :open

    # States
    aasm_state :open
    aasm_state :closed

    # Events
    aasm_event :close, :after => :notify_closed do transitions :to => :closed, :from => [:open,:replied], :guard => :can_close? end

    # Notify Observer
    def notify_closed
     notify :close # this will trigger after_close method call in ClarificationRequestObserver
     # notify :closed # this will trigger after_closed method call in ClarificationRequestObserver
     # notify :whatever # this will trigger after_whatever method call in ClarificationRequestObserver
    end
end
rstets
This is one hard working dude.
Jaryl
A: 

I would do something like this:

class ClarificationRequest < ActiveRecord::Base
  include AASM

  aasm_initial_state :open

  # States
  aasm_state :open
  aasm_state :closed, :enter => :do_close

  # Events
  aasm_event :close do transitions :to => :closed, :from => [:open,:replied], :guard => :can_close? end

  def recently_closed?
    @recently_closed
  end 
protected
  def do_close
    @recently_closed = true
  end

end


class ClarificationRequestObserver < ActiveRecord::Observer
  observe :clarification_request

  def after_save(clarification_request)
    puts '############### message from observer!!!!!' if clarification_request.recently_closed?
  end
end

You should also include the observer in the config.active_record.observers list in config/environment.rb

The reason for that is that an observer should observe an object. By actively notifying (and interacting with) the observer from the model you assume that there is one available, which I don't believe that you safely can do (seeing how observers usually behave in the real world). It should be up to the observer whether it is interested of the event or not.

Jimmy Stenke