From: Xeno Campanoli on 14 Apr 2010 21:00 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
From: Thomas Volkmar Worm on 14 Apr 2010 21:35 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
From: Josh Cheek on 14 Apr 2010 21:35 [Note: parts of this message were removed to make it a legal post.] On Wed, Apr 14, 2010 at 8:00 PM, Xeno Campanoli <xeno.campanoli(a)gmail.com>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
From: Josh Cheek on 14 Apr 2010 23:24 [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 <tvw(a)s4r.de> 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.
From: Chris Hulan on 20 Apr 2010 10:16
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 |