Is there a way to make class and object constants in Ruby?

Discussion in 'Ruby' started by Xeno Campanoli, Apr 15, 2010.

  1. I am reading up in other areas, and it occurs to me much of the items I have as
    class and object variables really should be constants, but ideally still in the
    class or object context. Is there a way to do this?

    xc
    --
    "It's the preponderance, stupid!" - Professor Stephen Schneider, IPCC member
    Xeno Campanoli, Apr 15, 2010
    #1
    1. Advertising

  2. Am Wed, 14 Apr 2010 20:00:54 -0500 schrieb Xeno Campanoli:

    > I am reading up in other areas, and it occurs to me much of the items I
    > have as class and object variables really should be constants, but
    > ideally still in the class or object context. Is there a way to do
    > this?
    >
    > xc


    In class context you could do:

    class MyClass

    MYCONSTANT=6

    def initialize
    puts MYCONSTANT
    end

    end


    But I wonder, whether it makes sense at all to have constants at object
    level. This sounds weird to me.

    Thomas
    Thomas Volkmar Worm, Apr 15, 2010
    #2
    1. Advertising

  3. Xeno Campanoli

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Wed, Apr 14, 2010 at 8:00 PM, Xeno Campanoli <>wrote:

    > I am reading up in other areas, and it occurs to me much of the items I
    > have as class and object variables really should be constants, but ideally
    > still in the class or object context. Is there a way to do this?
    >
    > xc
    > --
    > "It's the preponderance, stupid!" - Professor Stephen Schneider, IPCC
    > member
    >
    >

    Variables that begin with capital letters are constants

    initial_constants = Module.constants
    class MyClass
    MY_FAVOURITE_NUMBER = 12
    MyFavouriteNumber = 12
    end
    Module.constants - initial_constants # => [:MyClass]
    MyClass.constants # => [:MY_FAVOURITE_NUMBER, :MyFavouriteNumber]


    So you can see that classes are already constants, and an example of how to
    create constants within a class.

    In Ruby, this really means that the reference may not be changed (or at
    least you will be warned if you try to do so), not that the object being
    referenced may not be mutated.

    class MyClass
    MyFavouriteNumber = 12
    MyFavouriteNumber = 13 # !> already initialized constant MyFavouriteNumber
    MyFavouriteNumber # => 13
    end

    If you change your constant, you will know, it will warn you (ie, it won't
    happen by accident). If your code breaks because of this... well... you'll
    have a pretty good idea where to look. While Ruby is dynamic enough to make
    such a change, it is not something you should do. If you need to change your
    constants, then they shouldn't be constants.

    If you really need your data to not change, to the point where you don't
    even want to allow yourself the opportunity to do so, you can freeze it, and
    it will throw an exception

    class MyClass
    MyFavouriteWord = "ambivalent"
    MyFavouriteWord << 'l'
    MyFavouriteWord # => "ambivalentl"
    MyFavouriteWord.freeze
    MyFavouriteWord << 'y'
    MyFavouriteWord # =>
    end
    # ~> -:6:in `<class:MyClass>': can't modify frozen string (RuntimeError)
    # ~> from -:1:in `<main>'



    But as far as I am aware, there is no way to recursively free any references
    it has (probably a good thing, you could recursively freeze your entire
    program)

    class MyClass

    SomeArray = [ 'abc' , 'def' ].freeze
    SomeArray # => ["abc", "def"]

    begin
    SomeArray << 'ghi'
    rescue => e
    e # => #<RuntimeError: can't modify frozen array>
    end

    SomeArray.last # => "def"
    SomeArray.last << 'ghi'
    SomeArray.last # => "defghi"

    end



    Generally, constants are used for data that should be hard coded in, you use
    a constant so that you can easily change it later, like using a macro in C.
    You can then drop it into your code, and it is replaced with the actual
    value (you can redefine macros too). And they are also used for keeping
    important references, like the constant STDIN. We can change the global we
    use as stdin, but we don't want to lose track the actual stdin, so we keep
    it in the constant.

    STDIN # => #<IO:<STDIN>>
    $stdin # => #<IO:<STDIN>>

    $stdin = DATA # => #<File:untitled>
    gets # => "this is the data\n"

    $stdin = STDIN # => #<IO:<STDIN>>

    __END__
    this is the data
    Josh Cheek, Apr 15, 2010
    #3
  4. Xeno Campanoli

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Wed, Apr 14, 2010 at 8:40 PM, Thomas Volkmar Worm <> wrote:

    > Am Wed, 14 Apr 2010 20:00:54 -0500 schrieb Xeno Campanoli:
    >
    > > I am reading up in other areas, and it occurs to me much of the items I
    > > have as class and object variables really should be constants, but
    > > ideally still in the class or object context. Is there a way to do
    > > this?
    > >
    > > xc

    >
    > In class context you could do:
    >
    > class MyClass
    >
    > MYCONSTANT=6
    >
    > def initialize
    > puts MYCONSTANT
    > end
    >
    > end
    >
    >
    > But I wonder, whether it makes sense at all to have constants at object
    > level. This sounds weird to me.
    >
    > Thomas
    >
    >

    I do for things that don't (or shouldn't) change. For example, I'm working
    on a Rails project where the admin can assign a level of trust to a user
    such that they can post images directly to the main page from Twitter. The
    database doesn't inherently support enumerated types, so the attribute is an
    integer, then I have class level constants that map those values to their
    meanings, and a set of methods that allow you to get booleans back when
    asking if that user is able to do that authorized thing, and they are
    embedded into named scopes so that I can pull all users who have this
    authorization level, or that authorization level, and so forth. So I just
    store a single integer in the database, but my application interprets it the
    same across every instance.
    Josh Cheek, Apr 15, 2010
    #4
  5. Thank you Josh and Thomas. The source of this question is my study of Erlang,
    where all 'Variables' do not vary after the initial assignment. I realized when
    reading up on the language that there are many areas in my classes where the
    thing I use, especially with Object Variables, are effectively constants, so I
    would do best to have them as actual constants. It turns out there is a lot of
    value in knowing that something cannot change, even if it can change but will
    have at least an obvious error. I don't expect to Erlangize my programs, but I
    have already identified things I can do to make my stuff safer and clearer just
    by making class and object variables into constants. Too bad there is not a
    special prefix for these as there is for the variables. That would be nice for
    referencing things. Still, no big deal.

    xc



    Josh Cheek wrote:
    > On Wed, Apr 14, 2010 at 8:40 PM, Thomas Volkmar Worm <> wrote:
    >
    >> Am Wed, 14 Apr 2010 20:00:54 -0500 schrieb Xeno Campanoli:
    >>
    >>> I am reading up in other areas, and it occurs to me much of the items I
    >>> have as class and object variables really should be constants, but
    >>> ideally still in the class or object context. Is there a way to do
    >>> this?
    >>>
    >>> xc

    >> In class context you could do:
    >>
    >> class MyClass
    >>
    >> MYCONSTANT=6
    >>
    >> def initialize
    >> puts MYCONSTANT
    >> end
    >>
    >> end
    >>
    >>
    >> But I wonder, whether it makes sense at all to have constants at object
    >> level. This sounds weird to me.
    >>
    >> Thomas
    >>
    >>

    > I do for things that don't (or shouldn't) change. For example, I'm working
    > on a Rails project where the admin can assign a level of trust to a user
    > such that they can post images directly to the main page from Twitter. The
    > database doesn't inherently support enumerated types, so the attribute is an
    > integer, then I have class level constants that map those values to their
    > meanings, and a set of methods that allow you to get booleans back when
    > asking if that user is able to do that authorized thing, and they are
    > embedded into named scopes so that I can pull all users who have this
    > authorization level, or that authorization level, and so forth. So I just
    > store a single integer in the database, but my application interprets it the
    > same across every instance.
    >



    --
    "It's the preponderance, stupid!" - Professor Stephen Schneider, IPCC member
    Xeno Campanoli, Apr 20, 2010
    #5
  6. Xeno Campanoli

    Chris Hulan Guest

    To make objects immutable you can 'freeze' them. After being frozen
    any attempt
    to change will result in an error:
    >> x = 'test'

    =>
    "test"
    >> x.freeze

    =>
    "test"
    >> x[0] = 'w'

    RuntimeError: can't modify frozen string
    Chris Hulan, Apr 20, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,712
    Thomas Weidenfeller
    Oct 12, 2005
  2. Rick DeNatale
    Replies:
    0
    Views:
    79
    Rick DeNatale
    Mar 15, 2007
  3. Xeno Campanoli
    Replies:
    2
    Views:
    122
    Eric Hodel
    Jan 25, 2008
  4. Kenneth McDonald
    Replies:
    5
    Views:
    301
    Kenneth McDonald
    Sep 26, 2008
  5. Steve Allan
    Replies:
    5
    Views:
    718
    Steve Allan
    Jul 29, 2003
Loading...

Share This Page