1

Given the next model using the aasm gem:

class Job
  include AASM

  aasm do
    state :sleeping, :initial => true
    state :running, :cleaning

    event :run do
      transitions :from => :sleeping, :to => :running
    end

    event :clean do
      transitions :from => :running, :to => :cleaning
    end

    event :sleep do
      transitions :from => [:running, :cleaning], :to => :sleeping
    end
  end
end

I have 2 types of users on my web application (regular users, and super users). I need super users type, beeing able to call the event they want. Like calling #run on a job with state=cleaning.

So, as I understand, what I need is to resolve the transition's from at runtime. If the user is a superuser, the from would be all the states, but if the user is not a super user, each from would have different states.

Is there any clean way to do that? Do you have any ideas?

ascherman
  • 1,762
  • 2
  • 20
  • 41

1 Answers1

0

Making decisions in a model layer based on current_user has always been considered a code smell, so a couple of clean ways to achieve your goal could be:

  1. To implement some inheritance, like:

    CommonUserJob < Job
      # move your current AASM validations here
    end
    
    AdminJob < Job
      aasm do
        event :run do
          all_states = Job.aasm.states.map{|i| i.name}
          transitions :from => all_states, :to => :running
        end
        # other events here in same manner
      end
    end      
    

    Then you should get a CommonUserJob or AdminJob instance based on your user's role and call a state change.

  2. To implement some composition (refer to composition over inheritance), which would mean you move your role-specific aasm code to modules and extend job object with a particular one at a runtime.

Note that both of this suggestions leave your base Job class without any aasm validations at all. This seems to contradict a common Rails way, but follows a DCI paradigm, which states that we should decouple what the system is (domain model) from what the system does (functionality). Base class instances should still be able to get its current state though.

Community
  • 1
  • 1
twonegatives
  • 3,400
  • 19
  • 30