What's "new" in Ruby
While updating Delayed Job’s YAML parser compatibility last week, Steve and I came across a Ruby method that neither of us had seen before, Class.allocate. Given that we were in the trenches of serializing and deserializing objects, this method caught our attention.
So, what’s it do? It allocates space for a new object of the class, but doesn’t call the initialize
method on that new instance. Whoa… wait, what? You can create an object that skips the initialization of that object? Yes… but don’t think you’re going to go off and start using allocate
willy nilly. In my eyes, it’s main use is in serialization, where you may want to split the allocation and initialization of the object in two steps.
Nonetheless, here’s a quick example showing the difference between new
and allocate
.
class Person
def initialize(*args)
@name = "Brian"
@loves_coffee = true
end
def loves_coffee?
@loves_coffee || false
end
def name
@name
end
end
> brian = Person.new
# => #
> brian.name
# => "Brian"
> brian.loves_coffee?
# => true
> b = Person.allocate
# => #
> b.name
# => nil
> b.loves_coffee?
# => false
As you can see in the second group of results, when calling Person.allocate
we’re given back a new instance of Person
but without the initialized attributes. What’s interesting, though, is under the hood Ruby’s Class.new
first calls allocate
, then initialize
.
What are some other lesser known ways of creating or initializing objects?
Comments
#inspect might call allocate on some objects (ActiveRecord, amongst others).
See this (closed) rails bug : https://github.com/rails/rails/pull/1297
*
Damien*: Fascinating. Looks like ActiveRecord also makes use of
allocate@ for STI.Interesting, thank you Brian.
another bit of ruby knowledge to my little brain. Thank you.
it could be very interesting to use for factories and programming using factory patterns or delegation patterns. having an object in a state where usually no default values are stored in could also be used as fake lazy loading.
This is very similar to how it is done in Objective-C, where the allocation and initialization of objects are separated, but some classes offer a “new” method which combines the alloc and init into a single call. I’ve never fully understood why they do this, but I think it has something to do with garbage collection.
Here is a cool stuff you can do with allocate in order to have a nice factory: https://gist.github.com/270744
*
Nuwan Chaturanga*: Your welcome! I don't know how long
allocate@ has been around, but in the nearly 5 years of programming Ruby, it was the first I’ve seen it. Love coming across stuff like this.