Hi, My application has a table of People that has information about them, and I want to have a subset of those people as Users - people that can login to the application. What is the best way to do this? Add columns to People that only Users would use? I''ve read the threads on single table inheritance, but it seemed a little bit wasteful: 10,000 people vs 50 users For those more experienced, is it more of a pain to create a Users table that has a foreign key to a Person_id, and then try to bring up this data? There are instances where I would want to display information about a User that has data contained in a Person. Hope this makes sense, -- - Nic
On 1/5/06, Nic Werner <nicwerner@gmail.com> wrote:> Hi, > My application has a table of People that has information about > them, and I want to have a subset of those people as Users - people > that can login to the application. > > What is the best way to do this? Add columns to People that only > Users would use? I''ve read the threads on single table inheritance, > but it seemed a little bit wasteful: 10,000 people vs 50 usersI would just make an association between User and Person.> For those more experienced, is it more of a pain to create a Users > table that has a foreign key to a Person_id, and then try to bring up > this data? There are instances where I would want to display > information about a User that has data contained in a Person.If you have users with person_id, the code to get the person associated with the User stored in @my_user is: @my_user.person. So to answer your question, no. -Steven
I''m dealing with the same issue. I don''t much like STI, though it may be my lack of experience with using it. I wish Rails supported Class Table Inheritance - create a table for each inheritance level and tie rows in different tables together by giving them the same ''id'' value. Maybe I''ll go nuts someday and create a patch. I''m not very database savvy, so there may be good reasons for avoiding CTI, like causing too many queries or reads/writes. In the mean time, I rolled my own CTI using standard Rails features. I have a User superclass and several subclasses for types of users (eg Admin). I have a UserMixin class that I include in each subclass that provides easy access to the user fields as if they were part of that class. For example def name return user.name end That keeps all my references to functionality in user.rb abstracted away from the inheritance model and will make it easy to change the implementation in the future if I decide to move back to STI or if Rails suddenly gets support for CTI. I''m finding it very easy to deal with things using this approach, and haven''t missed using STI at all. Nic Werner wrote:> Hi, > My application has a table of People that has information about > them, and I want to have a subset of those people as Users - people > that can login to the application.-- Posted via http://www.ruby-forum.com/.
Nuby alert. I''m more steeped in OOP than I am yet in Ruby and Rails. As with so many things, there are lots of ways of doing this. My personal preference is to take advantage of the OO nature of Ruby and just create subclass of People called User, then add whatever attributes and methods the User class needs to differentiate from the People class. Presumably, all Users are People, so this is not, as you seem to conclude, wasteful at all. On the contrary; adding attributes to the People class (with potentially thousands of instantiations) to handle the relatively smaller number of Users would be much more wasteful/ less efficient. On Jan 5, 2006, at 9:36 AM, Nic Werner wrote:> Hi, > My application has a table of People that has information about > them, and I want to have a subset of those people as Users - people > that can login to the application. > > What is the best way to do this? Add columns to People that only-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. -.-.-.-.-.-.-.-.-.-.-.-.-.-.- Dan Shafer Technology Visionary - Technology Assessment - Documentation "Looking at technology from every angle" http://www.eclecticity.com
Thanks for all the responses, its a little clearer in my head now. I think my problem is that I''m trying to think in OOP and DB models at the same time, wondering how my subclass is actually going to created in the DB and if it is ''efficient''. - Nic. On 1/5/06, Dan Shafer <dan@danshafer.com> wrote:> Nuby alert. I''m more steeped in OOP than I am yet in Ruby and Rails. > > As with so many things, there are lots of ways of doing this. My > personal preference is to take advantage of the OO nature of Ruby and > just create subclass of People called User, then add whatever > attributes and methods the User class needs to differentiate from the > People class. > > Presumably, all Users are People, so this is not, as you seem to > conclude, wasteful at all. On the contrary; adding attributes to the > People class (with potentially thousands of instantiations) to handle > the relatively smaller number of Users would be much more wasteful/ > less efficient. > > > On Jan 5, 2006, at 9:36 AM, Nic Werner wrote: > > > Hi, > > My application has a table of People that has information about > > them, and I want to have a subset of those people as Users - people > > that can login to the application. > > > > What is the best way to do this? Add columns to People that only > > > -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. > -.-.-.-.-.-.-.-.-.-.-.-.-.-.- > Dan Shafer > Technology Visionary - Technology Assessment - Documentation > "Looking at technology from every angle" > http://www.eclecticity.com > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- - Nic
Hi Nic, Regular relational databases are not object-oriented, so yes, thinking in terms of RDBMS structure *and* and object-oriented language like Ruby at the same time can cause dizzyness, and occasionally nausea. In the OO-world relationships are frequently established with inheritance; in the RDBMS world they are established with *associations*. There are some new-fangled object-oriented database management systems coming on the market these days (OODBMS), mostly for java, that make the mapping between objects in your app and objects in the db straightforward. I still miss the fast, simple object db in Frontier.... Like Dan said, there are a few ways of cutting the pie. One option is to have separate tables for users vs. people. This would be a good choice if there''s little overlap between the two tables. But fetching from a join between users and people is an expensive process (relative to fetching from a single table). So, if there''s a fair bit of overlap in the attributes (name, age, hair_color, ss_number, favorite_continental_philosopher, etc.) then it makes sense to structure the db with single table inheritance. How do you do that? Setting up single table inheritance in a db is pretty common, the Type-of-Person < Person subclassing is perhaps the most typical. You can probably get some info on this for your db of choice pretty easily on-line. Typically, you just set up the db with all the columns that you''ll need for all classes. This means there will be many object "closer" to the parent class that won''t be used. A person might only have a name and id, for example. But an angry spear-fisherman native whose good with poison darts will use a lot more attributes (mood, source_of_food, good_with_poison_darts, etc.). So, you''ve got to make sure that the columns that aren''t used by every class are nullable (i.e., *don''t* set the column to ''not null''). That''s the first thing to remember. The second thing involves tracking in the non-object-oriented db table what class each person-row falls under. So, just add a column called something like, ''person_type''. Even though you''ve only got one table in your db you want to set up your class structure in rails so that you can make use of the inheritance structure in your app. That just means you define your model objects with the hierarchy that you want: class Person < ActiveRecord::Base end class SpearFisherman < Person end class User < Person end class DODEmployee < Person end class AngrySpearFisherman <SpearFisherman end You can then create objects of any of the above classes and they''ll have access to any of the attributes in the entire table. It''s up to you, in your code, to make sure that the angry spear-fisherman doesn''t get assigned a DOD clearance number ... well, wasn''t there that picture of Rumsfield.... O.k., nevermind, you get the idea. You can use that ''person_type'' column to help keep track of what your code should be doing to any otherwise unknown row it pulls from the db. A couple of last things: you can''t have two objects that have an attribute with the same name but are supposed to be different, e.g,. you can''t have a ''fish'' column that represents the type of fish speared for the fisherman (varchar) but the number (int) of fish eaten at the DOD press dinner since, obviously, you can''t have one column with different types. You *can* use that same column to represent semantically different things (number of fish eaten by that person vs. number of types of fish that person can identify) but you''ll eventually confuse yourself if you do this. Lastly, don''t name that ''person_type'' column something like ''type'' (or if you do, change the mapping from the Ruby class to the column so that it''s something else) because that''s the name of a Ruby method. Sheesh, I really rambled. Anyway, the Agile book covers this same material pretty well in ch. 15, I think. Best, Russ>Thanks for all the responses, its a little clearer in my head now. I >think my problem is that I''m trying to think in OOP and DB models at >the same time, wondering how my subclass is actually going to created >in the DB and if it is ''efficient''. >[snip] > > > Hi, >> > My application has a table of People that has information about >> > them, and I want to have a subset of those people as Users - people >> > that can login to the application. >> > > > > What is the best way to do this? Add columns to People that only
That explanation sealed it for me, thanks Russ! - Nic On 1/5/06, Russ McBride <Russ@psyex.com> wrote:> Hi Nic, > > Regular relational databases are not object-oriented, so yes, > thinking in terms of RDBMS structure *and* and object-oriented > language like Ruby at the same time can cause dizzyness, and > occasionally nausea. In the OO-world relationships are frequently > established with inheritance; in the RDBMS world they are established > with *associations*. There are some new-fangled object-oriented > database management systems coming on the market these days (OODBMS), > mostly for java, that make the mapping between objects in your app > and objects in the db straightforward. I still miss the fast, simple > object db in Frontier.... > > Like Dan said, there are a few ways of cutting the pie. One option > is to have separate tables for users vs. people. This would be a > good choice if there''s little overlap between the two tables. But > fetching from a join between users and people is an expensive process > (relative to fetching from a single table). So, if there''s a fair > bit of overlap in the attributes (name, age, hair_color, ss_number, > favorite_continental_philosopher, etc.) then it makes sense to > structure the db with single table inheritance. > > How do you do that? Setting up single table inheritance in a db is > pretty common, the Type-of-Person < Person subclassing is perhaps the > most typical. You can probably get some info on this for your db of > choice pretty easily on-line. Typically, you just set up the db with > all the columns that you''ll need for all classes. This means there > will be many object "closer" to the parent class that won''t be used. > A person might only have a name and id, for example. But an angry > spear-fisherman native whose good with poison darts will use a lot > more attributes (mood, source_of_food, good_with_poison_darts, etc.). > So, you''ve got to make sure that the columns that aren''t used by > every class are nullable (i.e., *don''t* set the column to ''not > null''). That''s the first thing to remember. The second thing > involves tracking in the non-object-oriented db table what class each > person-row falls under. So, just add a column called something like, > ''person_type''. > > Even though you''ve only got one table in your db you want to set up > your class structure in rails so that you can make use of the > inheritance structure in your app. That just means you define your > model objects with the hierarchy that you want: > > class Person < ActiveRecord::Base > end > > class SpearFisherman < Person > end > > class User < Person > end > > class DODEmployee < Person > end > > class AngrySpearFisherman <SpearFisherman > end > > You can then create objects of any of the above classes and they''ll > have access to any of the attributes in the entire table. It''s up to > you, in your code, to make sure that the angry spear-fisherman > doesn''t get assigned a DOD clearance number ... well, wasn''t there > that picture of Rumsfield.... O.k., nevermind, you get the idea. You > can use that ''person_type'' column to help keep track of what your > code should be doing to any otherwise unknown row it pulls from the > db. > > A couple of last things: you can''t have two objects that have an > attribute with the same name but are supposed to be different, e.g,. > you can''t have a ''fish'' column that represents the type of fish > speared for the fisherman (varchar) but the number (int) of fish > eaten at the DOD press dinner since, obviously, you can''t have one > column with different types. You *can* use that same column to > represent semantically different things (number of fish eaten by that > person vs. number of types of fish that person can identify) but > you''ll eventually confuse yourself if you do this. > > Lastly, don''t name that ''person_type'' column something like ''type'' > (or if you do, change the mapping from the Ruby class to the column > so that it''s something else) because that''s the name of a Ruby method. > > Sheesh, I really rambled. Anyway, the Agile book covers this same > material pretty well in ch. 15, I think. > > Best, > > Russ > > > > > > > >Thanks for all the responses, its a little clearer in my head now. I > >think my problem is that I''m trying to think in OOP and DB models at > >the same time, wondering how my subclass is actually going to created > >in the DB and if it is ''efficient''. > >[snip] > > > > Hi, > >> > My application has a table of People that has information about > >> > them, and I want to have a subset of those people as Users - people > >> > that can login to the application. > >> > > > > > What is the best way to do this? Add columns to People that only > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >--