1

Using Ruby language, I have to store some ruby :symbols data type in a relational database (let's say just a simple Sqlite (https://www.sqlite.org/), maybe through Sequel's ORM (see: https://github.com/jeremyevans/sequel). So leave aside discussion of database specific features (postgres enum ect.)

In my application, symbols represent the status of a finite state machine (so I have to manage with a sort of enum).

Let's consider the following code (see also: https://github.com/soveran/micromachine):

require 'micromachine'

machine = MicroMachine.new(:new) # Initial state.

# Define the possible transitions for each event.
machine.when(:confirm, :new => :confirmed)
machine.when(:ignore, :new => :ignored)
machine.when(:reset, :confirmed => :new, :ignored => :new)

machine.trigger(:ignore)   #=> true
machine.state              #=> :ignored

As you can see I have represented different states using symbols:

:new, :ignored, :confirmed are in a sense a sort of enum of status (each finite state machine includes a "fixed" set of states).

Now I have to save (persist) machine.state in a column of a relational database.

What is the suggested way to store states (symbols in terms of ruby data struct) in a db ?

Here are some possible ideas:

  1. A "relational" method utilising a look-up table to map symbols to numbers, and the performing a join operation.

  2. An alternative would be to code an enumeration (embedding the lookup) inside the ruby program; see: How to store and compare :symbols in an ActiveRecord (Ruby on Rails) and: Enums in Ruby

  3. A trivial solution would be to just convert the string to a symbolbefore saving it to the db:

```

machine.state              #=> :ignored
machine.state.to_s         #=> "ignored"    
dataset.insert(:status => machine.state.to_s)

```

But I'm perplexed because ideally I want avoid an explicit symbol <-> integer mapping (when persisting in the db).

Any suggestion / best practice ?

UPDATE: For completeness: "state" can assume a lot (tens and tens) of different values (symbols), not just the few value in the example here proposed.

Community
  • 1
  • 1
Giorgio Robino
  • 2,148
  • 6
  • 38
  • 59

2 Answers2

0

I'd suggest you store the symbol as a string, and then convert it back to a symbol on read. Something like this (an ActiveRecord example):

class MiniMachine < ActiveRecord::Base

  def state
    super.to_sym if state?
  end

end

As saving a symbol into a field via ActiveRecord will automatically convert it to a string, you should not have to do anything else.

ReggieB
  • 8,100
  • 3
  • 38
  • 46
0

If you don't have any specific constraint on your code(i.e. performance, memory/disk space constraint) just choose the simplest solution. Based on information in your question I'd choose the p.3 - just to convert it to the string.

Alexey Shein
  • 7,342
  • 1
  • 25
  • 38
  • Yes, the "to_s" approach is simplest in my mind. BTW, I forgot to precisate that this "state" is a sort of "session" status attribute (say chatbot server with high number of client connections), so there is a bit of performance constraint: many clients does conversations with the server that have to store conversaton status in the database for each client, and retrieve the status for future conversations... – Giorgio Robino Oct 27 '15 at 11:17
  • 1
    I'd use a separate table to ease indexing only if I have lots of statuses (not your case), otherwise just store it as a string and don't forget to put an index on that column to make queries that involve that column fast. – Alexey Shein Oct 27 '15 at 11:21