I’m building a page layout application that has spreads and pages. Each spread contains two pages (a left page and a right page).
The database looks like this:
create_table :spreads do |t|
...
t.references :left_page
t.references :right_page
...
end
create_table :pages do |t|
# No foreign keys
end
Semantically, two pages belong to a spread, so it would make sense to set up the models as follows:
class Spread < ActiveRecord::Base
has_one :left_page, :class_name => 'Page'
has_one :right_page, :class_name => 'Page'
end
class Page < ActiveRecord::Base
belongs_to :spread
end
But, since the foreign keys live in the spreads table, Rails seems to demand the reverse:
class Spread < ActiveRecord::Base
belongs_to :left_page, :class_name => 'Page'
belongs_to :right_page, :class_name => 'Page'
end
class Page < ActiveRecord::Base
has_one :spread
end
Whenever I run into something like this in Rails, it makes me think I’m approaching the problem in the wrong way. Is that the case or do I just live with code that doesn’t quite read clearly?
short answer:
it depends on your business rules.
longer answer:
It is a schema design issue, not really a rails issue…
Since you already decided that the foreign keys MUST be in the
spreadstable, it means you had good reasons to do so (right ?).belongs_toonly reflects this structure.Sure, you could have placed those FKS on the
pagestable. Functionaly, it (more or less) changes nothing… for now. But how will it work when you implement callbacks? How easy will it be to manipulate your objects ?This is an architecture decision, and only you can decide.
Now, IMHO, it seems that your design is right. This structure holds more information in itself that would the other solution : your
spreadobject will always have 0-1 left page and 0-1 right page; not only the fact that a spread has at most 2 pages is reflected in this structure, but each FK also reflects a quality of the association (left or right page). So i would stick with this solution, even if it “reads weird”.