Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Constant Lookup

This is probably a simple question, but I'm trying to lookup the constant name in Ruby from the value. For example:

class Xyz < ActiveRecord::Base
  ACTIVE    = 1
  PENDING   = 2
  CANCELED  = 3
  SENT      = 4
  SUSPENDED = 5
end

I have a status of 1 in my db. I want to retrieve ACTIVE based on this so that I can display it in a view.

What's a good way to do that?

like image 869
jignesh Avatar asked May 22 '12 00:05

jignesh


People also ask

How do you find the constants in Ruby?

Ruby Constants Constants begin with an uppercase letter. Constants defined within a class or module can be accessed from within that class or module, and those defined outside a class or module can be accessed globally. Constants may not be defined within methods.

What do you understand by method lookup explain with an example?

The Method Lookup Path Saves The Day This is the to_a method that will get invoked by the range object from the above example. When an object receives a message it first looks in to its own class to see if a method is defined with the same name as the message, and if so invokes it.


2 Answers

class Module
  def constant_by_value( val )
    constants.find{ |name| const_get(name)==val }
  end
end

class Xyz
  ACTIVE    = 1
  PENDING   = 2
  CANCELED  = 3
  SENT      = 4
  SUSPENDED = 5
end

p Xyz.constant_by_value(4)
#=> :SENT

However, I wouldn't do this: using programmatic names as values for a view seems like a bad idea. You're likely to run into a situation where you want to change the display name (maybe "suspended" should be shown as "on hold") and then you have to refactor your code.

I'd put a mapping in your view or controller, using the constants from the model:

status_name = {
  Xyz::ACTIVE    => "Active",
  Xyz::PENDING   => "Pending", 
  Xyz::CANCELED  => "Canceled", 
  Xyz::SENT      => "Away!", 
  Xyz::Suspended => "On Hold"
}
@status = status_name[@xyz.status_id]
like image 74
Phrogz Avatar answered Sep 19 '22 14:09

Phrogz


I would put it into a constant array.

class xzy < ActiveRecord::Base
  STATUSES = %w{ACTIVE PENDING CANCELLED SENT SUSPENDED}

  def get_status
    STATUSES[self.status-1]
  end

  def get_status_id(name)
    STATUSES.index(name) + 1
  end
end

The minus 1 in #get_status and + 1 in #get_status_id are for zero-indexed arrays. I added the second method as I have found myself needing that from time to time.

like image 27
agmcleod Avatar answered Sep 21 '22 14:09

agmcleod