Skip to main content

AASM state based on variable

General • Asked by Wouter van den Beld

Hi,

I am using AASM and i want to set the state based on the total_price of a purchase order.
is this code below the way to go or can it be refactored.

before_save :check_budget


event :over_budget do
        transitions from: [:new, :new_approval_needed], to: :new_approval_needed
    end

    event :on_budget do
        transitions from: [:new, :new_approval_needed], to: :new 
    end

  end

    def check_budget
        if aasm_state = 'new' || 'new_approval_needed'
                  if total_price > 500
                  over_budget
                  else
                  on_budget
                end
            else
        end
    end

Also, is it possible to set custom state names without the _ because it looks ugly on the PO if the state is NEW_APPROVAL_NEEDED i would like it to be NEW APPROVAL NEEDED


This is basically what the code would look like. There's not a significant way to refactor this other than pulling it out into a concern, but that hides the problem more than it cleans it up.

When you need to print out aasm_state, you can convert it from the string by doing this aasm_state.gsub("_", " ") to remove the underscores. You can then upcase the string or whatever you need to make it display nicer.


Hi Chris,

first of all, thank you for this great site! i love the videos and they are really helping me forward.

about my question, it looks kind of ugly but it works so i will leave it like this.

i found a solution for my naming problem.

instead of aasm_state you can call aasm.human_state and the text will be without the _
you can also use the .yml files to change the entire name i did not get that to work yet :)


This is more just a stylistic refactor, but you could also smash the event blocks inline to make them shorter. I also prefer case statements to ifs in situations like this. They're a little cleaner to read and using a ternary if statement for total_price also looks a little nicer, but this is all personal preference.

before_save :check_budget

event :over_budget { transitions from: [:new, :new_approval_needed], to: :new_approval_needed }
event :on_budget { transitions from: [:new, :new_approval_needed], to: :new }

def check_budget
  case aasm_state
  when 'new', 'new_approval_needed'
    (total_price > 500) ? over_budget : on_budget
  end
end

I didn't know about human_state! That's super useful! It also makes sense that they have locale options for the names. That's something I would have not even though of providing but makes perfect sense that they provide that.


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.