Rails, models, and “scoping” access question

I am working on a toy application and I feel like my models are getting a little unwieldy. I'm looking for some advice on model organization.

The app: basically, users can highlight lines of a text article. They are first presented with a view of the article’s contents (i.e., all its lines). They select a line to highlight. When a line has been highlighted, any user can click on it to bring up a comments section for that line.

So far, I’ve organized my models like this:

Article has_many Lines
Line has_many Highlights
Highlight has_many Comments
User has_many Highlights
User has_many Comments

Highlight belongs_to User
Comments belongs_to Highlight
Comments belongs_to User

I don’t see anything necessarily wrong with this approach, though there is perhaps a more efficient way to do things (isn’t there always?). However, now I want to add the functionality of a “Group Project”, which is private to selected users. Basically, a user can choose an article to use in a Group Project. He invites other users to this project. Invited users can highlight, leave comments, etc., but all the highlights and comments are only visible to users of that project.

My idea was to create a ‘scope’. By default, for all articles, highlights, and comments, the scope is ‘public’. Any user can log in and view those articles, highlights, comments. But a user can also access one of his Group Projects and see (possibly the same) articles with ‘privately’ scoped highlights, comments, etc. This brings up the problem that a single Line can have multiple highlights and comments with different scopes.

I’m wondering what is the best way of dealing with all these multiple instances? How can I effectively organize them to avoid duplication in the database? Am I on the right track with my model organization? Should I create new instances of the Lines for each project? For example, when a user creates a project, create a new copy of the Article (and all its Lines) so they have new ids in the database. Is there a better, Rails-way of doing all this that I’m missing?

Leave a Comment