ActiveRecord, mapping a column value to a symbol

Hi

Is it possible to map a column value to a symbol?

For example, lets say I have an integer in a table that will hold -1,
0 or 1

I want these to map to :negative, :neutral, :positive

Or is there a better way to accomplish this. I want something similar
to an enum in C, so that from code i can can talk about things in
terms of abstract values, but that are stored in one column in the DB.

The other way I could do this would be to have another table mapping
the values, but this seems unnecessarily expensive.

Thanks
Ryan

Ryan wrote:

Hi

Is it possible to map a column value to a symbol?

For example, lets say I have an integer in a table that will hold -1,
0 or 1

I want these to map to :negative, :neutral, :positive

Or is there a better way to accomplish this. I want something similar
to an enum in C, so that from code i can can talk about things in
terms of abstract values, but that are stored in one column in the DB.

The other way I could do this would be to have another table mapping
the values, but this seems unnecessarily expensive.

Thanks
Ryan

I might create a method like the following...

def symbolized_value
   case value
      when 1 : :positive
      when 0 : :neutral
      when -1 : :negative
   end
end

Ryan wrote:

For example, lets say I have an integer in a table that will hold -1,
0 or 1

I want these to map to :negative, :neutral, :positive

If you will just want to compare if an object has one of these values,
then instead of have lots of "object.value == :negative" and so forth,
you could define some predicates on your class:

def negative?
  value == -1
end

etc. Then instead of using the symbols, you hide the values in these
predicates.

You can define similar setters:

def negative
  value = -1
end

Depending on how you intend using the values, there's a number of things
you can do to hide the implementation from users of the model.

Ryan wrote:

Hi

Is it possible to map a column value to a symbol?

For example, lets say I have an integer in a table that will hold -1,
0 or 1

I want these to map to :negative, :neutral, :positive

class SomeModel < ActiveRecord::Base

  VALUE_MAP = {:negative => -1, :neutral => 0, :positive => 1}

  def value=(sym)
    write_attribute :value, VALUE_MAP[sym]
  end

  def value
   VALUE_MAP.invert[read_attribute(:value)]
  end

end

hth

ilan

Thanks for the help. Just tried out Ilan's solution and works great.

Instead of:
  VALUE_MAP.invert[read_attribute(:value)]
It's a bit more efficient/elegant to use
  VALUE_MAP.key[read_attribute(:value)]

If you have a larger map and/or efficiency is important you could also
use an array:
VALUE_MAP = [:negative,:neutral,:positive]
def value=(sym);self[:value]=VALUE_MAP.index(sym)-1;end
def value;VALUE_MAP[read_attribute(:value)+1];end
-j

I get a NoMethodError when using key. I'm using Ruby 1.8.6

Hello everyone,

Can anyone recommend a blogging engine that would suit my needs? My website
would require multiple blogs, each "owned" by a different user, with each
being separately customizable. Right now I'm making use of separate
WordPress installations for each user, but I would rather find a solution
that could be integrated with the rest of the application instead of
switching back and forth between Rails and PHP (for WordPress).

I've looked at several blogging engines, but most of them seem geared
towards just one blog, or one blog with multiple authors and not multiple
blogs with one author each. Is there anything out there which I could use
and modify, or am I pretty much stuck writing my own engine to accomplish
it? As far as the blog itself goes, we don't need much more than the
ability for authors to write posts, others to post comments, and the
standard search/archive stuff.

Any help would be appreciated.

Regards,

Wayne M.
Co-Founder, LibertyTruth.org

No virus found in this outgoing message.
Checked by AVG.
Version: 7.5.518 / Virus Database: 269.21.6/1318 - Release Date: 3/7/2008
2:01 PM

I believe that's a typo. It probably should be:

VALUE_MAP.keys[read_attribute(:value) + 1]

Fjan wrote:

Instead of:
  VALUE_MAP.invert[read_attribute(:value)]
It's a bit more efficient/elegant to use
  VALUE_MAP.key[read_attribute(:value)]

If you have a larger map and/or efficiency is important you could also
use an array:
VALUE_MAP = [:negative,:neutral,:positive]
def value=(sym);self[:value]=VALUE_MAP.index(sym)-1;end
def value;VALUE_MAP[read_attribute(:value)+1];end
-j

Fjan,

I like that solution much better than mine, I kick myself for not having
not thought of the array solution instead of the map! You may have won
this round but the war isn't over! :slight_smile:

ilan

@Ryan/Mike

I get a NoMethodError when using key. I'm using Ruby 1.8.6

Sorry, you are right, it's a new method in Ruby 1.9, I didn't realize
that. A hash invert is kind of an expensive thing to do on every call
so then I'd rather do the invert once and store it in a constant, or
use the array version.

@ilan
The real Ruby-ists don't worry about performance they tell me :slight_smile: