Sounds logical. The only concern I'd have is that it would be
'implicit' and so you wouldn't know whether using person.address was its
'existing' address or its 'auto-magically created' address. Leaving it
explicit helps you have more understanding of which is new, which isn't.
It just doesn't feel right. What I'd rather write is this
class Person < ActiveRecord::Base
belongs_to :address, :default => true
end
That would be reasonable, though I'd probably not use it as I for some
reason love explicitness
-R
There really doesn't seem to be a *declarative* way to define a default
value for belongs_to and has_one associations
class Person < ActiveRecord::Base
belongs_to :address
end
p = Person.new
p.address.city = 'Atlantis' # Bummer!
Hmm, I sniff the code smell of a violation of the /law|strong
suggestion/ of Demeter here.
Better to define a city= method on Person (if this is what you really
want) which hides the implementation.
Of course, there's an easy way to avoid this
class Person < ActiveRecord::Base
belongs_to :address
def after_initialize
self.address ||= Address.new
end
end
It just doesn't feel right. What I'd rather write is this
class Person < ActiveRecord::Base
belongs_to :address, :default => true
end
and alternatively
class Person < ActiveRecord::Base
belongs_to :address,
:default => proc { |record| record.address ||= Address.new }
end
Are there any reasons why ActiveRecord should *not* do something like
this?
Well, I have to ask, presumably Person belongs_to Address (rather than
the other way around) because more than one person can have the same
Address. The normal relationship on the other side of belongs_to is
has_many. Whenever I see has_one (unless it uses :conditions/:order
or the like to pick out one of a has_many) I wonder why the two models
aren't combined, either directly or via STI.
> There really doesn't seem to be a *declarative* way to define a
> default value for belongs_to and has_one associations
>
> class Person < ActiveRecord::Base
> belongs_to :address
> end
>
> p = Person.new
> p.address.city = 'Atlantis' # Bummer!
Hmm, I sniff the code smell of a violation of the /law|strong
suggestion/ of Demeter here.
I don't. That law doesn't say only a single dot is allowed, does it?
Apart from being called a law, I'd like to see exactly what improvement
following that rule would effect in this particular case.
In my rails code I very rarely have assignments like the one above. What
I do have is views and particularly forms where I show and edit objects
and related objects, such as a person and their address. Partials lend
themselves to this and in such a case, I want to pass a valid object,
say an address, into the partial. In a sense I'm even following the Law
of Demeter in that way. Anyway, whenever person.address gets passed
into the address partial, I want it to be initialized with an
appropriate address object.
Better to define a city= method on Person (if this is what you really
want) which hides the implementation.
Even if I did that -- which I won't without positive indication --, it
would not remove the original problem. As a negative indication I'd
like to point out that adding #city=, #zip= etc. to Person dilutes the
responsibility of that model class. These attributes belong on an
Address model class. Now, if we take presenters into consideration,
there I'd be inclined to put all relevant accessors directly on the
presenter. But at any rate, that wouldn't touch the original issue.