ruby-on-railsaasm

Is there a way to associate a label with a state in an event machine?


It seems like a deceptively simple ask: is it possible to associate a human-friendly string with a machine-friendly state name in an event machine on Rails? I'm using AASM at the moment, but none of the event machine gems I've looked at seem to offer this.

I have weirdly-capitalized states, like "Sent to PE Review", which "flatten" to :sent_to_pe_review as a state symbol. I can't easily get back to a properly-cased label for display on the object in a view, or in a dropdown select on a form. It seems to me that there should be an option like label: "Sent to PE Review" on the definition of the state in the model, but I can't find any such reference.

I've resorted to creating a separate "status" field, and putting the appropriate string in it, depending on state, in a before_save callback. That fixes the view, but not the dropdown list in the form for jumping states. As I contemplate rigging up some sort of collection with state symbols and label strings, the whole thing is feeling very non-Rails-like, and I'm thinking I'm missing something simple. What's the "Rails way" to do this?


Solution

  • I wound up creating a hash in the class to do the translation:

    STATUS_HASH = [
      { state: "screening_in_process", label: "Screening In Process" },
      { state: "screenings_complete", label: "Screenings Complete" },
      ...
      { state: "work_complete", label: "Work Complete" },
      { state: "work_canceled", label: "Work Canceled" }
    ]
    

    In the edit _form, I can use (with simple_form, and HAML):

    = f.input :aasm_state, collection: Project::STATUS_HASH.map { |s| [s[:label], s[:state]] }
    

    Turns out that this solves both problems. In the show view, I can use:

    = Project::STATUS_HASH.find{ |s| s[:state] == @project.aasm_state }[:label]
    

    And I've removed the need for storing a separate field on the record for this, and the callback to update it.

    Maybe I should try to add support for a label into the AASM gem, but I guess it would, effectively, use the same sort of mechanism in the background.