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

I will be seriously impressed if anyone can tackle this

Thanks for the help,
JB

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jables wrote:
| 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
|
| I will be seriously impressed if anyone can tackle this
|
| Thanks for the help,
| JB

class Story < ActiveRecord::Base
~ has_many :votes
~ belongs_to :user

~ end
end

class User < ActiveRecord::Base
~ has_many :stories
~ has_many :votes
~ has_many :stories_voted_on, :through => :votes, :source => :story
end

class Vote < ActiveRecord::Base
~ belongs_to :story, :counter_cache => true
~ belongs_to :user

end

belongs_to and has_many and their friends are what you seek.


Phillip G.
Twitter: twitter.com/cynicalryan

~ - You know you’ve been hacking too long when…
…your children do something they shouldn’t do, you tell them to stop,
they
do it just once more anyway, so you think “Well, they prefetched the
instruction and are executing it in the delay slot.”
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgFHF8ACgkQbtAgaoJTgL+mOgCfbK0+naAuxc/btwkgbMCzUWWM
wCcAn39aIRWnty2MugMBQM6GsaFeUiSB
=KiQM
-----END PGP SIGNATURE-----

On 15 Apr 2008, at 22:13, Jables wrote:

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.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs