views:

146

answers:

1

Considering the following resources with their corresponding relationships:

Site 
 has_many :page
 has_many :groups
 has_many :projects

Group
 belongs_to :site
 has_many :pages

Project
 belongs_to :site
 has_many :pages

Is it good to make Page model polymorphic or leave individual foreign keys?

**Scenario 1 (Polymorphic)**
Page
 pageable_id
 pageable_type
 title
 body
 ....
 ....


**Scenario 2 (Non Polymorphic)**
Page 
 site_id (always filled)
 group_id (may be empty)
 project_id (may be empty)
 title
 body
 ....
 ....


**Scenario 3 (Combination)**
Page
 site_id
 pageable_id (may be empty, if page belongs only to site)
 pageable_type (may be empty, if page belongs only to site)
 title
 body
 .....
 .....

Which one of the above 3 scenarios would you prefer? And Why (in terms of efficiency, etc..)

Note: In my views, I will be traversing through all the possible relationships of the page to show the relevant links (for example: if the page belongs to group, I show the back to group link, ...)

A: 

I think including the site_id in the model is not such a good idea, because it might break when the site_id of a page belonging to a group doesn't match the site_id of that group.

That would leave just scenario 1...

If you want to have the possibility to do a site.pages and get all the pages belonging to that site (also pages belonging to a group belonging to that site) you could ofcourse write your own function:

class Site
  def all_pages
    Page.find_by_sql(["SELECT p.* FROM pages p, sites s, groups g, projects j WHERE (p.pageable_type='Site' AND p.pageable_id=?) OR (p.pageable_type='Group' AND p.pageable_id=g.id AND g.site_id=?) OR (p.pageable_type='Project' AND p.pageable_id=j.id AND j.site_id=?, self.id, self.id, self.id])
  end
end

(Also, I would name the pageable_id column 'parent_id' and pageable_type 'parent_type' in this case. That seems more logical to me...)

Jongsma
I like your approach on selecting the all the pages, but how is it going to break - "I think including the site_id in the model is not such a good idea, because it might break when the site_id of a page belonging to a group doesn't match the site_id of that group." A group has to be in a site and it cannot change from site to site.
satynos
Jongsma
@Jongsma - thanks for the prompt feedback.
satynos