That's right -- assigning to a constant is a warning, not an error; "constants" are just an indicator of how you should use something, not a rule that you do use it that way.
That may sound horrendous coming from a static-programming world, but it's immensely useful in various metaprogramming facilities, and it enables things that would otherwise be completely impossible in static languages.
That said, if you really want to make sure people keep their grubby hands off your references, you can use Object#freeze
. It's still okay to change what a reference points to with this; you just can't change the contents of the reference itself:
irb(main):001:0> class Fruit; attr_accessor :name; end
=> nil
irb(main):002:0> f = Fruit.new
=> #<Fruit:0xb7e06570>
irb(main):003:0> f.name = "apple"
=> "apple"
irb(main):004:0> f.freeze # After freeze, can't touch this Fruit.
=> #<Fruit:0xb7e06570 @name="apple">
irb(main):005:0> f.name = "banana"
TypeError: can't modify frozen object # Kablammo!
from (irb):5:in `name='
from (irb):5
But this is okay:
irb(main):006:0> f = Fruit.new
=> #<Fruit:0xb7dfed84>
irb(main):007:0> f.name = "banana"
=> "banana"