|
From: David Heinemeier Hansson <david.heinemeier@...>
Subject: Re: HABTM and extra attributes Newsgroups: gmane.comp.lang.ruby.rails Date: 2005-12-02 21:27:20 GMT (2 years, 23 weeks, 4 days, 1 hour and 4 minutes ago)
> With the current version of Rails, Chris' approach works just fine in
> this scenario, and the code required in the view is fairly
> straightforward to write and maintain. Peter's right in that it just
> seems like HABTM isn't "meant to" support this level of complexity;
> I'm concerned that a later Rails update could break it.
HABTM is indeed not well suited for complexity. It's pushing back
because it wants you to discover the implicit model object that's
missing from the equation. In the author/book example that model is
Authorship. So you would have:
class Author
has_many :authorships
end
class Book
has_many :authorships
end
class Authorship
belongs_to :author
belongs_to :book
end
Now the domain is explicit, but we're still in a bit of trouble. Since
this pretty domain will force us to write SQL by hand to get
performant access. So you'd probably have:
class Author
has_many :authorships
def books
find_by_sql(
"SELECT books.* " +
"FROM books, authors, authorships " +
"WHERE authorships.book_id = books.id AND + "
"authorships.author_id = #{id}"
)
end
end
And you would create new relationships by doing
b = Book.create :title => "Agile Web Development with Rails"
david = Author.create :name => "David Heinemeier Hansson"
dave = Author.create :name => "Dave Thomas"
Authorship.create([
{ :book => b, :author => david },
{ :book => b, :author => dave }
])
Now this is actually a lot less painful than one could imagine. But
its still not painless enough. So we're currently working on allowing:
class Author
has_many :authorships
has_many :books, :through => :authorships
end
This would expose both the join model (authorship) and allow
convenient access to the model on the other side of that join model.
One could even imagine:
class Author
has_many :authorships
has_many :books, :through => :authorships
has_many :agents, :through => :authorships
end
class Authorship
belongs_to :agent
belongs_to :author
belongs_to :book
end
So if I was having pushback from HABTM today, I would try to discover
which implicit domain model I hadn't revealed yet. Then I'd spend the
few minutes making the manual accessors for that join model. And I
would then look forward to the day where I could remove my manual
access as :through materializes.
--
David Heinemeier Hansson
http://www.loudthinking.com -- Broadcasting Brain
http://www.basecamphq.com -- Online project management
http://www.backpackit.com -- Personal information manager
http://www.rubyonrails.com -- Web-application framework
|
|
|