Ask A Question

Notifications

You’re not receiving notifications from this thread.

AASM state based on variable

Wouter van den Beld asked in General

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

Reply

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.

Reply

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 :)

Reply

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.

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 76,990+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2023 GoRails, LLC. All rights reserved.