markds75
2007-Sep-30 22:39 UTC
How to deal with one user-visible object stored as two logical objects
I''m not sure the Subject really captures what I''m trying to figure out how to do, so bear with me while I describe what I''m doing. I''ve got two classes that I''m trying to figure out how best to structure. One of the classes contains data that is shared by 1 or more instances of the other class. However the user only ever sees the non-sharable class. A more concrete example might help... consider the case of a catalog of CDs. Each user has their own private catalog with a list of CDs. When the add a CD, not only do they add the CD instance to their collection, but they also create a shared CD_Info instance that other users are able to see. Most of the attributes of a user''s CD are stored in the CD_Info instance, but a few (like purchase_price, and date_purchased, and was_gift?) are stored in the user''s CD object. Also worth noting is that multiple user''s CD objects can share a CD_Info instance... there''s no point in duplicating all that data. So there''s a few things I''d like to do. 1) Whenever an object of type CD is retrieved from the database, the CD_Info object associated with it is loaded too. I know I can use the :include attribute, but I''d like to make that the default for loading instances of this type. 2) I want to create a form for adding an object of type CD and, since most of that metadata is stored in the CD_Info object, have those fields automatically routed there. 3) Find a CD object based on attributes of CD_Info. 4) Not have to update or add a bunch of helper functions in the CD class whenever I add another attribute to the CD_Info class. Any suggestions would be very welcome. Thank you! --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Mark Slater
2007-Oct-01 16:25 UTC
Re: How to deal with one user-visible object stored as two logical objects
So I''ve been thinking about this more and I may have a solution to my problem. I''m hoping people with more Rails experience than I have might sanity-check this idea. The point of the "shared" metadata is to avoid duplication of data, partly to keep the DB smaller, but mostly to facilitate returning a list of "potential matches" to users entering new data... they can click a "Use This Data" (or some such) button and get all the fields filled in, except for the ones that are related to their particular instance (created_at, modified_at, etc.). It hit me this morning that a self-referential table might be a better way to manage this (at least within the context of a Rails app) than to separate tables. The way it would work is to have a parent_id (or whatever its supposed to be called for the Rails Magic to work) which, if non-nil, refers to the instance with the metadata in it, and if nil, means that the current instance has the metadata in it. I''d probably add a count of how many children refer to each parent and use that to order the "potential match" list returned to the user. This would only be allowed to go 2 levels: parent and child. I think this solution addresses two of the needs I mentioned before (a single form that has all the fields necessary, and not having to add a bunch of helper functions to make it look like the user''s object has all the same attributes as the shared object). I''m not sure it handles automatic loading of the parent by default or finding a child based on the attributes in the parent. Am I off track here? Is there a better way to handle these issues? Thanks! Mark On Sep 30, 2007, at 3:39 PM, markds75 wrote:> > I''m not sure the Subject really captures what I''m trying to figure out > how to do, so bear with me while I describe what I''m doing. > > I''ve got two classes that I''m trying to figure out how best to > structure. One of the classes contains data that is shared by 1 or > more instances of the other class. However the user only ever sees the > non-sharable class. A more concrete example might help... consider the > case of a catalog of CDs. Each user has their own private catalog with > a list of CDs. When the add a CD, not only do they add the CD instance > to their collection, but they also create a shared CD_Info instance > that other users are able to see. Most of the attributes of a user''s > CD are stored in the CD_Info instance, but a few (like purchase_price, > and date_purchased, and was_gift?) are stored in the user''s CD object. > Also worth noting is that multiple user''s CD objects can share a > CD_Info instance... there''s no point in duplicating all that data. > > So there''s a few things I''d like to do. > > 1) Whenever an object of type CD is retrieved from the database, the > CD_Info object associated with it is loaded too. I know I can use > the :include attribute, but I''d like to make that the default for > loading instances of this type. > > 2) I want to create a form for adding an object of type CD and, since > most of that metadata is stored in the CD_Info object, have those > fields automatically routed there. > > 3) Find a CD object based on attributes of CD_Info. > > 4) Not have to update or add a bunch of helper functions in the CD > class whenever I add another attribute to the CD_Info class. > > Any suggestions would be very welcome. Thank you! > > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
IndyCodeWarrior
2007-Oct-02 01:29 UTC
Re: How to deal with one user-visible object stored as two logical objects
>From a database normalization point of view, take a look at this:Class CdInfo (this would be the shared one, right?) has_many :cds has_many :tracks def name Class Track belongs_to :cd_info def sequence def name Class Cd belongs_to :cd_info belongs_to :user Class User had_many :cds Cd contains foreign_keys cd_info_id and user_id Track contains foreign_key cd_info_id dutchess_track_3 User.find_by_id(whatever).cds.cd_info.find_by_name("The Duchess").tracks.find_by_sequence(3).name => "London Bridge" Sorry if I''ve butchered the syntax. Still know SQL better than rails. -Mack On Oct 1, 12:25 pm, Mark Slater <markd...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> So I''ve been thinking about this more and I may have a solution to my > problem. I''m hoping people with more Rails experience than I have > might sanity-check this idea. > > The point of the "shared" metadata is to avoid duplication of data, > partly to keep the DB smaller, but mostly to facilitate returning a > list of "potential matches" to users entering new data... they can > click a "Use This Data" (or some such) button and get all the fields > filled in, except for the ones that are related to their particular > instance (created_at, modified_at, etc.). It hit me this morning that > a self-referential table might be a better way to manage this (at > least within the context of a Rails app) than to separate tables. The > way it would work is to have a parent_id (or whatever its supposed to > be called for the Rails Magic to work) which, if non-nil, refers to > the instance with the metadata in it, and if nil, means that the > current instance has the metadata in it. I''d probably add a count of > how many children refer to each parent and use that to order the > "potential match" list returned to the user. This would only be > allowed to go 2 levels: parent and child. > > I think this solution addresses two of the needs I mentioned before > (a single form that has all the fields necessary, and not having to > add a bunch of helper functions to make it look like the user''s > object has all the same attributes as the shared object). I''m not > sure it handles automatic loading of the parent by default or finding > a child based on the attributes in the parent. > > Am I off track here? Is there a better way to handle these issues? > > Thanks! > > Mark > > On Sep 30, 2007, at 3:39 PM, markds75 wrote: > > > > > I''m not sure the Subject really captures what I''m trying to figure out > > how to do, so bear with me while I describe what I''m doing. > > > I''ve got two classes that I''m trying to figure out how best to > > structure. One of the classes contains data that is shared by 1 or > > more instances of the other class. However the user only ever sees the > > non-sharable class. A more concrete example might help... consider the > > case of a catalog of CDs. Each user has their own private catalog with > > a list of CDs. When the add a CD, not only do they add the CD instance > > to their collection, but they also create a shared CD_Info instance > > that other users are able to see. Most of the attributes of a user''s > > CD are stored in the CD_Info instance, but a few (like purchase_price, > > and date_purchased, and was_gift?) are stored in the user''s CD object. > > Also worth noting is that multiple user''s CD objects can share a > > CD_Info instance... there''s no point in duplicating all that data. > > > So there''s a few things I''d like to do. > > > 1) Whenever an object of type CD is retrieved from the database, the > > CD_Info object associated with it is loaded too. I know I can use > > the :include attribute, but I''d like to make that the default for > > loading instances of this type. > > > 2) I want to create a form for adding an object of type CD and, since > > most of that metadata is stored in the CD_Info object, have those > > fields automatically routed there. > > > 3) Find a CD object based on attributes of CD_Info. > > > 4) Not have to update or add a bunch of helper functions in the CD > > class whenever I add another attribute to the CD_Info class. > > > Any suggestions would be very welcome. Thank you!--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
markds75
2007-Oct-02 02:22 UTC
Re: How to deal with one user-visible object stored as two logical objects
That''s basically what I''m starting with. Well, sorta (not bothering with the tracks just yet). But what I''d like to be able to do is say>> Cd.find_by_name("The Duchess")and have rails know that the Name property is actually an attribute of the CDInfo object that each CD is required to have. And also be able to say: <% form_for( :cd, :url => cd_path ) -%> ... <% end -%> and have the fields for the CDInfo object show up there too. My problem isn''t so much with the DB and SQL as making sure I''m doing this in the Rails best-practice way. I''m sure others have had similar problems and it wouldn''t surprise me if there''s an elegant way of handling it (by passing some kind of parameter/flag to the belongs_to declaration or whatever). I just haven''t been able to find such a way. Mark On Oct 1, 6:29 pm, IndyCodeWarrior <m...-yGXRaSYFwudM9OxnJa7udtBPR1lH4CV8@public.gmane.org> wrote:> >From a database normalization point of view, take a look at this: > > Class CdInfo (this would be the shared one, right?) > has_many :cds > has_many :tracks > > def name > > Class Track > belongs_to :cd_info > > def sequence > def name > > Class Cd > belongs_to :cd_info > belongs_to :user > > Class User > had_many :cds > > Cd contains foreign_keys cd_info_id and user_id > Track contains foreign_key cd_info_id > > dutchess_track_3 > User.find_by_id(whatever).cds.cd_info.find_by_name("The > Duchess").tracks.find_by_sequence(3).name > => "London Bridge" > > Sorry if I''ve butchered the syntax. Still know SQL better than rails. > > -Mack > > On Oct 1, 12:25 pm, Mark Slater <markd...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > So I''ve been thinking about this more and I may have a solution to my > > problem. I''m hoping people with more Rails experience than I have > > might sanity-check this idea. > > > The point of the "shared" metadata is to avoid duplication of data, > > partly to keep the DB smaller, but mostly to facilitate returning a > > list of "potential matches" to users entering new data... they can > > click a "Use This Data" (or some such) button and get all the fields > > filled in, except for the ones that are related to their particular > > instance (created_at, modified_at, etc.). It hit me this morning that > > a self-referential table might be a better way to manage this (at > > least within the context of a Rails app) than to separate tables. The > > way it would work is to have a parent_id (or whatever its supposed to > > be called for the Rails Magic to work) which, if non-nil, refers to > > the instance with the metadata in it, and if nil, means that the > > current instance has the metadata in it. I''d probably add a count of > > how many children refer to each parent and use that to order the > > "potential match" list returned to the user. This would only be > > allowed to go 2 levels: parent and child. > > > I think this solution addresses two of the needs I mentioned before > > (a single form that has all the fields necessary, and not having to > > add a bunch of helper functions to make it look like the user''s > > object has all the same attributes as the shared object). I''m not > > sure it handles automatic loading of the parent by default or finding > > a child based on the attributes in the parent. > > > Am I off track here? Is there a better way to handle these issues? > > > Thanks! > > > Mark > > > On Sep 30, 2007, at 3:39 PM, markds75 wrote: > > > > I''m not sure the Subject really captures what I''m trying to figure out > > > how to do, so bear with me while I describe what I''m doing. > > > > I''ve got two classes that I''m trying to figure out how best to > > > structure. One of the classes contains data that is shared by 1 or > > > more instances of the other class. However the user only ever sees the > > > non-sharable class. A more concrete example might help... consider the > > > case of a catalog of CDs. Each user has their own private catalog with > > > a list of CDs. When the add a CD, not only do they add the CD instance > > > to their collection, but they also create a shared CD_Info instance > > > that other users are able to see. Most of the attributes of a user''s > > > CD are stored in the CD_Info instance, but a few (like purchase_price, > > > and date_purchased, and was_gift?) are stored in the user''s CD object. > > > Also worth noting is that multiple user''s CD objects can share a > > > CD_Info instance... there''s no point in duplicating all that data. > > > > So there''s a few things I''d like to do. > > > > 1) Whenever an object of type CD is retrieved from the database, the > > > CD_Info object associated with it is loaded too. I know I can use > > > the :include attribute, but I''d like to make that the default for > > > loading instances of this type. > > > > 2) I want to create a form for adding an object of type CD and, since > > > most of that metadata is stored in the CD_Info object, have those > > > fields automatically routed there. > > > > 3) Find a CD object based on attributes of CD_Info. > > > > 4) Not have to update or add a bunch of helper functions in the CD > > > class whenever I add another attribute to the CD_Info class. > > > > Any suggestions would be very welcome. Thank you!--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Roderick van Domburg
2007-Oct-02 09:25 UTC
Re: How to deal with one user-visible object stored as two l
I''ve found self-referentiality in Rails models to hit me in the back at some point in time, requiring me to implement all sorts of workarounds to make them happy. Rails and especially plugins don''t really like them, so I''d stay clear of ''em. I think you can compare your use case with that of tagging. You''ve got tags, which is a list of all unique tags ever created, and you''ve got taggings, which are made by a user and refer to a unique tag do avoid duplication. This has been done before many times as all the acts_as_taggable type of plugins can attest to, and is the way I''d go. You can use callbacks in your "non-shared" model to look up or create the shared object as needed. -- Roderick van Domburg http://www.nedforce.com -- 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 -~----------~----~----~----~------~----~------~--~---
markds75
2007-Oct-02 22:59 UTC
Re: How to deal with one user-visible object stored as two l
I see the similarities there. I''m just not sure that really captures the form use-case, as tags would be added one at a time, or a list of them all at once from a single form field... all the work is done in the controller. Also, since tags are a one to many mapping (one object having many tags), it doesn''t address the ability to do a find on one object using fields in a related object it has a one to one mapping with. Being able to use the "form_for( :cd, :url => cd_path )" construct is key to what I''m trying to accomplish. So far, I still haven''t heard of any way to have a single form where you can specify fields that are in the object in the form_for() method *and* another object linked by that one. That''s why I''m still thinking the self-referential way may be what I''m looking for... at least that way I get all the fields for the form, and only have to do a bit more work in the controller (which I assume I''d have to be doing anyway). Mark On Oct 2, 2:25 am, Roderick van Domburg <rails-mailing-l...@andreas- s.net> wrote:> I''ve found self-referentiality in Rails models to hit me in the back at > some point in time, requiring me to implement all sorts of workarounds > to make them happy. Rails and especially plugins don''t really like them, > so I''d stay clear of ''em. > > I think you can compare your use case with that of tagging. You''ve got > tags, which is a list of all unique tags ever created, and you''ve got > taggings, which are made by a user and refer to a unique tag do avoid > duplication. > > This has been done before many times as all the acts_as_taggable type of > plugins can attest to, and is the way I''d go. You can use callbacks in > your "non-shared" model to look up or create the shared object as > needed. > > -- > Roderick van Domburghttp://www.nedforce.com > -- > 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 -~----------~----~----~----~------~----~------~--~---