MikeMarsian
MikeMarsian

Reputation: 638

How to combine the benefits of constants and symbols in RoR?

currently I use constants for things like *task_type*:

class TaskType
    TWITTER_MENTION_REPLY = "twitter_mention_reply"
    TWITTER_FOLLOW = "twitter_follow"
    TWITTER_DM_REPLY = "twitter_dm_reply"
    TWITTER_RETWEET = "twitter_retweet"
end

so when I initialize a new task, I assign type like this:

new_task.task_type =  TaskType::TWITTER_MENTION_REPLY

the advantage of this approach is that in case the constant is typed incorrectly, the interpreter gives an error. The disadvantage is that comparing strings is costly, symbols are much better for that. So the question is, how to combine these two benefits?

I tried to create the following class:

class TaskType
     TWITTER_MENTION_REPLY = :twitter_mention_reply
end

but the problem with it was that when saving it to db, the saved field looks like this: --:twitter_mention_reply

Upvotes: 2

Views: 902

Answers (2)

lbz
lbz

Reputation: 9728

The benefit of symbols come from the symbol having an object identifier; that's the reason of a O(1) comparison between symbols. Strings are just different.

Your goals here are:

  • Having a set of task types to choose from with TaskType::SOME_CONSTANT to choose from
  • Save TaskType into a database
  • Lowering the cost of comparison between task types

Since task type are stored in a database (along a model I suppose) I would take more care of what can optimize your SQL query than what can lower the cost of the comparison in Ruby.

My first choise would be using plain strings. Otherwise I would use integers, as they are well understood by any Ruby ORM and any database.

class TaskType
    TWITTER_MENTION_REPLY = 0
    ...
end

Upvotes: 2

Victor Deryagin
Victor Deryagin

Reputation: 12215

Conversion to string before saving to db might help:

:twitter_mention_reply.to_s  # => "twitter_mention_reply"
# back to symbol
"twitter_mention_reply".to_sym  # => :twitter_mention_reply

Upvotes: 2

Related Questions