Tough modeling problem

I have what I think is a fairly complex modeling problem for you guys.

So I have a user class. There are three link type classes: picture, video, and story. A user can vote, bookmark, and add any of those types. Essentially I want to be able to say: user.stories and get the stories the user has uploaded user.votes.stories and get the votes that are stories user.votes.videos and get the votes that are videos user.bookmarks.videos and get the bookmarks for the videos

So these are essentially join tables, but I can't seem to get them to go properly, have tried polymorphism and has_many_polymorphs, limited success, limited knowledge.

Now I also want to be able to go the other way:

story.votes story.user story.bookmarks

Well a user has_many :videos (and the story :belongs_to :user) which
takes care of who uploaded what A user has_many votes, has_many bookmarks, again that's not the
complicated bit. From now on lets just think about bookmarks since
it's basically the same think at this point.

The bookmark model could belong_to :user, and belongs_to :
bookmark_content, :polymorphic => true Over on video, we can say video has_many :bookmarks, :as =>
bookmark_content

This takes care of video.bookmarks.

The only remaining bit is user.bookmarks.videos

off the top of my head you could solve it like this: replace the
has_many :bookmarks on user with

has_many :bookmarks do    def videos      Video.find :all, :joins => :bookmarks, :conditions =>
['bookmarks.user_id = ?', proxy_owner.id]    end end

you can define bookmarks.stories, bookmarks.pictures in a similar way

Fred

Thanks guys, it is becoming clear to me that I may have overcomplicated the issue.

Jables,

Fred's suggestion is an excellent one: defining additional hooks right off the has_many line. I've used that. In my case, I had: "user has_many profiles" and then defined a "default" as an accessor off of that (using almost exactly the code Fred posted). Then, I could do: User.find(:first).profiles.default # => the profile flagged as "default" for that user.

You should be able to do exactly the same thing. So kudos to Fred.

Oh, and if you are really wanting the full association goodness, look at Nested "has_many_through": http://agilewebdevelopment.com/plugins/nested_has_many_through

As that may do what you need.

Oh, and I also suggest rethinking. If you can capture your requirements with simpler associations, it'll be much, much better in the long run.

Maybe stack different vote types using STI. I.e.: Vote (abstract class, even), VideoVote < Vote, StoryVote < Vote, etc.

Then you could say on the User class:   has_many :video_votes   has_many :story_votes etc.

Of course I could also envision trying to architect this using polymorphism and declaring a "votable" class, but that might overcomplicate things.

KISS (Keep It Simple, Sir!)

-Danimal

Thanks guys, great advice.