Thursday, May 5, 2011

Rails - Constants Hash?

I have a need for a model(?) on my app which basically contains a status of another entity. In the entity I want to store the id of the status, but in my app, the view is talking in terms of a nice word description. For instance, 1=New, 2=Used etc etc.

How can I go about implementing this in the best way that means I can easily set and retrieve this status column without repeating myself?

Ultimately I would like something like

Foo.status = 'New'  (actually sets value to 1)

and

Foo.status  (returns 'New', but stores 1)

Am I even thinking about this in the right way?

From stackoverflow
  • You can code a custom writer method:

    STATUS_VALUES = { 1 => 'new', 2 => 'modified', 3 => 'deleted' }
    
    class Foo
      attr_reader :status_id
    
      def status
        STATUS_VALUES[@status_id]
      end
    
      def status=(new_value)
        @status_id = STATUS_VALUES.invert[new_value]
        new_value
      end
    end
    

    For example, the following program:

    foo_1 = Foo.new
    
    foo_1.status = 'new'
    puts "status: #{foo_1.status}"
    puts "status_id: #{foo_1.status_id}"
    
    foo_1.status = 'deleted'
    puts "status: #{foo_1.status}"
    puts "status_id: #{foo_1.status_id}"
    

    outputs:

    status: new
    status_id: 1
    status: deleted
    status_id: 3
    
  • One way could be using constants

    module MyConstants
      New  = 1
      Used = 2
    end
    

    Then you can use them like this

    Foo.status = MyConstants::New
    

    or even like this if you're carefull about namespace polution

    include MyConstants
    Foo.status = New
    

    On another thought, maybe you want to use a state machine.

    Jon Smock : Not exactly what he wanted, I think, since "New" (the string) is different than MyConstants:New (the object).
  • I'd just go ahead and use symbols, something like

    Foo.status = :new
    

    They're basically immutable strings, meaning that no matter how many times you use the same symbol in your code, it's still one object in memory:

    >> :new.object_id
    => 33538
    >> :new.object_id
    => 33538
    >> "new".object_id
    => 9035250
    >> "new".object_id
    => 9029510 # <- Different object_id
    
    Svante : Heh, Ruby seems to have found quite a lot of Lisp.

0 comments:

Post a Comment