Only one "initialize" method allowed on AR objects?


#1

I’m having some trouble with some seemingly basic OO stuff with one of
my AR::Base descendants.

I ended up creating a custom initialize method that takes two parameters

  • an integer and the standard AR attributes hash, like so:

    def initialize(user_id, attributes = nil)

In another part of my application, I was calling “clone” on one of these
objects and it gave me an incorrect number of arguments error. I
figured out it was because of the fact that my initialize expects 1
argument no matter what.

As soon as I provided a default value for user_id in the argument list
above, the call to clone was fine - I assume since now my initialization
didn’t require any arguments at all.

But this is somewhat disturbing. I was under the impression that I
would still have access to the regular initialize(attributes = nil)
method that I get from ActiveRecord::Base. Why is it not available?

Doesn’t this imply that I can’t have multiple constructors for an AR
object?

I tried to add

def initialize(attributes = nil)
super
end

to my object and I still can’t instantiate it just running “new” (no
arguments).

What gives?

Thanks for any help.

Wes


#2

Use the :after_initialize callback (or one of the other AR callbacks)
rather than trying to override the initialize method. This is the
recommended Rails approach.


#3

Thanks Mick.

I’m aware of the after_initialize method, but I just keep forgetting
that ActiveRecord objects don’t behave like normal objects.

“Least surprise” my a** :). Strictly speaking, I suppose, Ruby is
“least surprise”, Rails is “opinionated.” :slight_smile: But don’t get me wrong, I
really dig ActiveRecord.

Still, it’s weird to me that the existence of a method (initialize in
this case) seem to preclude any polymorphism on that method.

Wes


#4

Alex W. wrote:

You can also use super

def initialize(foo, *args)
@foo = foo
super(*args)
end

This is what I was doing. If you do this and then attempt to call clone
on your AR::Base descendant, it will complain.

Wes


#5

Mick S. wrote:

Use the :after_initialize callback (or one of the other AR callbacks)
rather than trying to override the initialize method. This is the
recommended Rails approach.

You can also use super

def initialize(foo, *args)
@foo = foo
super(*args)
end

The super method calls the same method as defined in the parent class.
This let’s you override a method, and still call the original method.


#6

I now know that there is no method overloading within the context of one
class due to the dynamic nature of Ruby. So I get it.

Wes


#7

Just a quick glance as I’m out the door, but don’t you mean this to be a
class method IE self.initialize?
Jason