Hello, I''m creating my own Tumblr [tumblr.com] like rails app. It''s like a blog, but in this case a blog post could be of a certain type, i.e. a regular post, a video, a link, a photo, a song(info). Well now, it''s clear that they share a lot of similar functionality: title, created_at/updated_at, commentable, probably has an author_id, etc.. But besides that they are very different: a post has a large text field, a link has an url and a description and a photo a reference to the file in a way. What to choose? Single Table Inheritance? Not really an option since the post types are very different. A polymorphic relation mabye, with a Post; has_one :subtype, :polymorphic => true; And that''s what I did, but soon enough I saw that it gave me a lot of problems. First of all, it''s not really a subtype, in this case :subtype is really a child model. When I have a post of type link, I would access the title through @post.title, but the url and description through @post.subtype.url and @post.subtype.description accordingly. Not really nice, but with some nifty method_missing handler I made it a bit easier. Now when I only want to have posts of type link I could do Link.find and I would have only links. But that one behaves so much different from working from Post as in this case I would read the attributes like @link.url, @link.description, @link.post.title Not very consistent, at all. So I use Post.find :all, :conditions => {:subtype_type (bad naming, I know) => ''Link'' To ease that I made a custom find method to accept Post.find :all, :type => :link and all was happy. Sorry for the long post, it''s been on my mind for such a long time already. Anyways... I was very proud on how I got it to work. Only instead of a Link.find :all I had to do a Post.find :all, :type => :link, and most was based around that. I could accept that, even though it was hard give up to. It required some more hacking to enable easier Post creation of a certain type and made my Post class bits by bits uglier to make it ''easier'' to work with. But then after a while I wanted to add a relationship to Artist with post of type song. But how!?! I couldn''t just link the relationship between Artist and Song, as that would mean would have the same effect as before. That I don''t get posts of type Song, but pure song models instead, with all the incosistent use as before. And a relation between Artist and Post where the foreign key lies in Song is not possible in rails. And I thought by myself "who the fuck wants to make such a complex database model, the eediot!!" At this moment I KNEW this is a flawed model too! And I''ve been thinking and wandering and whining and crying since then. Not knowing how to elegantly solve this stupid problem of mine. STI in rails works really nice! It wouldn''t have any of these problems I just described above, so why can''t I make how STI models in rails work using multiple tables. That would be really nice and I believe this would actually be a feasible. the Post table would be the same as with a STI model (id, title, created_at, updated_at, title, type) but the subtypes with have their own table, the links table would look something like (post_id, url, description) and the songs table something like (post_id, artist_id, ...). The subtypes don''t need an id column, as they don''t, won''t and shouldn''t be models themselves. As with polymorphic relations, eager load is not an option. I can''t load the url and description info from the links table as I don''t know what type the post will be at query time. Well, has_many_polymorphs [blog.evanweaver.com/pages/has_many_polymorphs] has some nice magic on this as long as you know (define) what subtypes there are. But even then, without eager loading I would be quite happy. Quite happy? I will probably jump for joy!! Thank you for reading, how are your thoughts on this? -- Dax Huiberts -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Dax, I am writing something similar (well, its an app using polymorphism whose objective is to have many different objects be published and search consistently). I''m not saying I have an answer for you, but I can describe my approach. In my case the basic objects are Article which is associated with Story, Map, Gallery and Image. I also have a design goal to be able to add new objects easily. I''ve done two things which ease the burden a little: 1. I created a module I mixin to each sub-type object. In this module I have accessor methods for basically all the main object attributes. For example, the module defines article_headline, article_tags, article_author and so on. These now appear as attributes in each sub-type. I order to facilitate publishing i ensure each sub-type has a unique "name" attribute and a "description" attribute. These are the only two assumptions I make but it lets me abstract the publishing model pretty easily. 2. I created a controller called ArticleController which implements the CRUD loop and other common functions. Then I inherit from that controller for the controllers for my objects. It doesn''t solve all problems by any means. But it does mean I can search for Articles by author, name, tags, posting/update dates irrespective of what sub-type. I can invoke a show/edit/new function on any sub-type without knowing its type and get the right behaviour. And I can add a new object in less than an hour (if its a basic object). I create the model and controller as usual and create the views for show and edit. Add the "require" and "include" for the mixin in the model. Change the inheritance in the controller. All done. Probably not general interest to the list, so email me as kipcole9 - at- gm-ail dot com if you''d like to continue the conversation - i''d like to find a more elegant solution to this too. Cheers, --Kip On Aug 3, 6:10 am, Dax Huiberts <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Hello, > > I''m creating my own Tumblr [tumblr.com] like rails app. > It''s like a blog, but in this case a blog post could be of a certain > type, i.e. a regular post, a video, a link, a photo, a song(info). > Well now, it''s clear that they share a lot of similar functionality: > title, created_at/updated_at, commentable, probably has an author_id, > etc.. > But besides that they are very different: a post has a large text field, > a link has an url and a description and a photo a reference to the file > in a way. > > What to choose? Single Table Inheritance? Not really an option since the > post types are very different. > A polymorphic relation mabye, with a Post; has_one :subtype, > :polymorphic => true; > And that''s what I did, but soon enough I saw that it gave me a lot of > problems. > First of all, it''s not really a subtype, in this case :subtype is really > a child model. When I have a post of type link, I would access the title > through @post.title, but the url and description through > @post.subtype.url and @post.subtype.description accordingly. > Not really nice, but with some nifty method_missing handler I made it a > bit easier. > Now when I only want to have posts of type link I could do Link.find and > I would have only links. But that one behaves so much different from > working from Post as in this case I would read the attributes like > @link.url, @link.description, @link.post.title > Not very consistent, at all. > So I use Post.find :all, :conditions => {:subtype_type (bad naming, I > know) => ''Link'' > To ease that I made a custom find method to accept Post.find :all, :type > => :link and all was happy. > > Sorry for the long post, it''s been on my mind for such a long time > already. > Anyways... > > I was very proud on how I got it to work. Only instead of a Link.find > :all I had to do a Post.find :all, :type => :link, and most was based > around that. I could accept that, even though it was hard give up to. It > required some more hacking to enable easier Post creation of a certain > type and made my Post class bits by bits uglier to make it ''easier'' to > work with. > > But then after a while I wanted to add a relationship to Artist with > post of type song. > But how!?! I couldn''t just link the relationship between Artist and > Song, as that would mean would have the same effect as before. That I > don''t get posts of type Song, but pure song models instead, with all the > incosistent use as before. > And a relation between Artist and Post where the foreign key lies in > Song is not possible in rails. And I thought by myself "who the fuck > wants to make such a complex database model, the eediot!!" > At this moment I KNEW this is a flawed model too! And I''ve been thinking > and wandering and whining and crying since then. Not knowing how to > elegantly solve this stupid problem of mine. > > STI in rails works really nice! It wouldn''t have any of these problems I > just described above, so why can''t I make how STI models in rails work > using multiple tables. That would be really nice and I believe this > would actually be a feasible. > the Post table would be the same as with a STI model (id, title, > created_at, updated_at, title, type) but the subtypes with have their > own table, the links table would look something like (post_id, url, > description) and the songs table something like (post_id, artist_id, > ...). > The subtypes don''t need an id column, as they don''t, won''t and shouldn''t > be models themselves. > As with polymorphic relations, eager load is not an option. I can''t load > the url and description info from the links table as I don''t know what > type the post will be at query time. Well, has_many_polymorphs > [blog.evanweaver.com/pages/has_many_polymorphs] has some nice magic on > this as long as you know (define) what subtypes there are. But even > then, without eager loading I would be quite happy. > > Quite happy? I will probably jump for joy!! > Thank you for reading, how are your thoughts on this? > -- > Dax Huiberts > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hey Kip, Yes, I am familiar with this approach too. I use it for a different project and it''s actually the nicest sollution so far. And with the power of has_many_polymorphs I have everything I ever need. One minor detail is that I don''t use a module with the generic functionality, but I use an abstract base class, which eventually works exactly the same. The only one thing I''m missing here is to get the 10 latest posts (like Tumblr again) of each kind. This way I have to do a find 10 on each individual post type, ordered by creation date, concatenade them all, sort them by the same ''order by'', creatoin_date that is, and use only the top 10 of that list. Now imagine this method with pagination and WHAM! It''s not cool anymore. Now get the 20 latest posts of each kind, concatenade them, sort them, and take the 2nd 10 from the beginning. Not cool at all! Not that I want to do pagination all the time, I''d rather make subselections for each month, but even then, pagination is still an option. I don''t have to do this with my other project, so this method works great, but for my Tumblr like project, it doesn''t solve it either. Thanks for reading, Dax. PS: I wonder how 37signals does this with basecamp and backpack, they sorta do the same thing I''d like to do. Kip wrote:> Dax, > > I am writing something similar (well, its an app using polymorphism > whose objective is to have many different objects be published and > search consistently). I''m not saying I have an answer for you, but I > can describe my approach. In my case the basic objects are Article > which is associated with Story, Map, Gallery and Image. I also have a > design goal to be able to add new objects easily. > > ...-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---