Search code examples
ruby-on-railsrubyaasm

How can i create a state machine using on the fly using yaml configuration, where i can store and use multiple config files


I have a requirement in my rails application to build a FSM and that FSM should be configurable. In my application i am creating a employee exit workflow that includes some processes needs to be completed before exit of an employee from an organization. And catch is each organization of the application should be able to store their own resignation configuration, for example which events should be triggered when this state transitioned. Their can be external events on which state can transition etc.

I tried aasm gem but i didn't found any feature that allows dynamically creating states


Solution

  • Something along these lines should allow you use a yaml file in the appropriate model

    include AASM
    
      
      def apply_custom_configuration(config_file_path)
        config = YAML.load_file(config_file_path)
    
        aasm do
          config['states'].each do |state|
            aasm_state state['name'].to_sym, initial: state['initial'] || false
          end
    
          config['events'].each do |event|
            aasm_event event['name'].to_sym do
              transitions from: event['from'].map(&:to_sym), to: event['to'].to_sym
            end
          end
        end
      end
    

    Then something along these lines can be used where the actual employee exit is performed.

    config_file_path = Rails.root.join('config', 'employee_exit_workflows', 'organization1.yaml')
    employee_exit = EmployeeExit.new
    employee_exit.apply_custom_configuration(config_file_path)
    

    How about persisting the custom workflows in a database?

    To persist the data in your database:

    1. Creates a custom_workflows model
    2. Serialise the YAML
    3. Load and save the YAML configuration

    Here's a snippet for saving it to the database:

    config = YAML.load_file('path_to_your_yaml_file.yaml')
    custom_workflow = CustomWorkflow.new(organization: 'org_name', config: config)
    custom_workflow.save
    

    The snippet above assumes the new table has just two fields but you can modify it to suit your needs.

    You can then retrieve a custom workflow thus:

    workflows = CustomWorkflow.where(organization: 'org_name')