I am building an app right now that needs to grant access to three levels of members right now - each will have their own table in the DB. When creating the add_user action I am converting the password into a hashed password through the model. The way I am doing this right now, I will inevitably end up with repeated code in three different models. Is there a way I can define this code in one single place and simply reference it from the models? Sorry if this is a real newbie question - this is my first solo Ruby app... -- Posted via http://www.ruby-forum.com/.
Mark ~ You can do this with One Table in your database using Single Table Inheritance (STI). You will have 4 models in the end, the base member class, and then the 3 types of members which inherit from the member class. You can do this in Rails by adding a field named "type" to your member table. I believe the Wiki has more information on STI. ~ Ben On 1/25/06, Mark Daoust <mark@site-reference.com> wrote:> > I am building an app right now that needs to grant access to three > levels of members right now - each will have their own table in the DB. > When creating the add_user action I am converting the password into a > hashed password through the model. > > The way I am doing this right now, I will inevitably end up with > repeated code in three different models. Is there a way I can define > this code in one single place and simply reference it from the models? > > Sorry if this is a real newbie question - this is my first solo Ruby > app... > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Ben Reubenstein http://www.benr75.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060125/eac05f46/attachment.html
Ben Reubenstien wrote:> Mark ~ > > You can do this with One Table in your database using Single Table > Inheritance (STI). You will have 4 models in the end, the base member > class, and then the 3 types of members which inherit from the member > class. You can do this in Rails by adding a field named "type" to your > member table. I believe the Wiki has more information on STI.Really? Sounded more like a modules question to me... Mark, try this (with your own class names, of course): module MyUser def hash_password do_stuff_here end end (you can put that in a file in lib/, and require it in environment.rb) class User < ActiveRecord::Base include MyUser # User-specific methods go here end (this should be app/user.rb) class Admin < ActiveRecord::Base include MyUser # Admin-specific methods go here end (this should be app/admin.rb) class Member < ActiveRecord::Base include MyUser # Member-specific methods go here end (this should be app/member.rb) That way there''s no restriction on the differences in table schema between the user classes. -- Alex> On 1/25/06, *Mark Daoust* <mark@site-reference.com > <mailto:mark@site-reference.com>> wrote: > > I am building an app right now that needs to grant access to three > levels of members right now - each will have their own table in the DB. > When creating the add_user action I am converting the password into a > hashed password through the model. > > The way I am doing this right now, I will inevitably end up with > repeated code in three different models. Is there a way I can define > this code in one single place and simply reference it from the models? > > Sorry if this is a real newbie question - this is my first solo Ruby > app... > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org <mailto:Rails@lists.rubyonrails.org> > http://lists.rubyonrails.org/mailman/listinfo/rails > > > > > -- > Ben Reubenstein > http://www.benr75.com > > > ------------------------------------------------------------------------ > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Ben Reubenstien wrote:> Mark ~ > > You can do this with One Table in your database using Single Table > Inheritance (STI). You will have 4 models in the end, the base member > class, and then the 3 types of members which inherit from the member > class. > You can do this in Rails by adding a field named "type" to your member > table. I believe the Wiki has more information on STI. > > ~ BenIsn''t there a way to do it using three models and three tables? I''d like to keep the data separate as I am holding different information about each - I''d rather not have one table that asks for the address of the admin (eventually me) - kind of pointless... I''ll look into STI - that seems close to what I am looking for. I guess ultimately what I am looking for is the equivalent of application.rb, but for models rather than a controller... -- Posted via http://www.ruby-forum.com/.
Take a look at Single Table Inheritance especially if your members are very similar ... STI has some limitations so you should check to make sure that it won''t adversely affect you. See http://www.ruby-forum.com/topic/51386 http://wiki.rubyonrails.com/rails/pages/SingleTableInheritance If you''re feeling adventurous, you may want to check out Class Table Inheritance ... http://johnwilger.com/articles/2005/09/29/class-table-inheritance-in- rails-with-postgresql but it seems a little too much trouble for me right now. I like things to be as simple as possible. -- G. On Jan 25, 2006, at 3:50 PM, Mark Daoust wrote:> I am building an app right now that needs to grant access to three > levels of members right now - each will have their own table in the > DB. > When creating the add_user action I am converting the password into a > hashed password through the model. > > The way I am doing this right now, I will inevitably end up with > repeated code in three different models. Is there a way I can define > this code in one single place and simply reference it from the models? > > Sorry if this is a real newbie question - this is my first solo Ruby > app... > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Mark Daoust wrote:>The way I am doing this right now, I will inevitably end up with >repeated code in three different models. Is there a way I can define >this code in one single place and simply reference it from the models? >Sounds like that code should be in a helper... --
Alex Young wrote:> Ben Reubenstien wrote: >> Mark ~ >> >> You can do this with One Table in your database using Single Table >> Inheritance (STI). You will have 4 models in the end, the base member >> class, and then the 3 types of members which inherit from the member >> class. You can do this in Rails by adding a field named "type" to your >> member table. I believe the Wiki has more information on STI. > > Really? Sounded more like a modules question to me... > > Mark, try this (with your own class names, of course): > > module MyUser > def hash_password > do_stuff_here > end > end > (you can put that in a file in lib/, and require it in environment.rb) > > class User < ActiveRecord::Base > include MyUser > # User-specific methods go here > end > (this should be app/user.rb) > > class Admin < ActiveRecord::Base > include MyUser > # Admin-specific methods go here > end > (this should be app/admin.rb) > > class Member < ActiveRecord::Base > include MyUser > # Member-specific methods go here > end > (this should be app/member.rb) > > That way there''s no restriction on the differences in table schema > between the user classes. > > -- > AlexAlex, I think that was exactly what I was looking for! I''ll give that a try. I''m working with the first table right now (trying to get everything working correctly), but will let you know if this worked. Thank you everyone for your responses so far. -- Posted via http://www.ruby-forum.com/.
Hi Mark ~ Yep it is a model question, but in the end the models will relate to some physical database table. I guess it depends on how different the 3 membership tables are to decide if they need their own tables. I would say the DRYest (spelling?) way to do this would be with one table, STI, and then have support tables for different member types. Just my two cents, your method works as well and does focus on the models. ~ Ben On 1/25/06, Alex Young < alex@blackkettle.org> wrote:> > Ben Reubenstien wrote: > > Mark ~ > > > > You can do this with One Table in your database using Single Table > > Inheritance (STI). You will have 4 models in the end, the base member > > class, and then the 3 types of members which inherit from the member > > class. You can do this in Rails by adding a field named "type" to your > > member table. I believe the Wiki has more information on STI. > > Really? Sounded more like a modules question to me... > > Mark, try this (with your own class names, of course): > > module MyUser > def hash_password > do_stuff_here > end > end > (you can put that in a file in lib/, and require it in environment.rb) > > class User < ActiveRecord::Base > include MyUser > # User-specific methods go here > end > (this should be app/user.rb) > > class Admin < ActiveRecord::Base > include MyUser > # Admin-specific methods go here > end > (this should be app/admin.rb) > > class Member < ActiveRecord::Base > include MyUser > # Member-specific methods go here > end > (this should be app/member.rb) > > That way there''s no restriction on the differences in table schema > between the user classes. > > -- > Alex > > > On 1/25/06, *Mark Daoust* <mark@site-reference.com > > <mailto:mark@site-reference.com>> wrote: > > > > I am building an app right now that needs to grant access to three > > levels of members right now - each will have their own table in the > DB. > > When creating the add_user action I am converting the password into > a > > hashed password through the model. > > > > The way I am doing this right now, I will inevitably end up with > > repeated code in three different models. Is there a way I can > define > > this code in one single place and simply reference it from the > models? > > > > Sorry if this is a real newbie question - this is my first solo Ruby > > app... > > > > -- > > Posted via http://www.ruby-forum.com/ . > > _______________________________________________ > > Rails mailing list > > Rails@lists.rubyonrails.org <mailto: Rails@lists.rubyonrails.org> > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > > > > > > > > -- > > Ben Reubenstein > > http://www.benr75.com > > > > > > ------------------------------------------------------------------------ > > > > _______________________________________________ > > Rails mailing list > > Rails@lists.rubyonrails.org > > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Ben Reubenstein http://www.benr75.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060125/942fbb56/attachment.html
Perhaps you want something like this? In my STI, I have entities, all of which have an address as well as a contact person. class Entity < ActiveRecord::Base composed_of :address, :class_name => Address, :mapping => [ # database # ruby [ :primary_address, :primary ], [ :secondary_address, :secondary ], [ :city, :city ], [ :region, :region ], [ :postal_code, :postcode ], ] composed_of :contact, :class_name => Contact, :mapping => [ # database # ruby [ :phone_number, :phone ], [ :mobile_number, :mobile ], [ :fax_number, :fax ], [ :email_address, :email ] ] end Then I use aggregations to ''wrap'' some of the columns into something that makes more sense within the application domain ... class Address attr_reader :primary, :secondary, :city, :region, :postcode def initialize(primary, secondary, city, region, postcode) @primary = primary @secondary = secondary @city = city @region = region @postcode = postcode end def to_s "#{@primary}, @ #{@city}" end end class Contact attr_reader :phone, :mobile, :fax, :email def initialize(phone, mobile, fax, email) @phone = phone @mobile = mobile @fax = fax @email = email end def to_s "M: #{@mobile} T: #{@phone} F: #{@fax} E: #{@email}" end end And the human class, gets everything defined in Entity for free ... class Human < Entity composed_of :name, :class_name => Name, :mapping => [ # database # ruby [ :first_name, :first ], [ :middle_name, :middle ], [ :last_name, :last ], [ :description, :descr ] ] end As does each Organization class Organization < Entity def location "#{self.city}, #{self.region}" end end Hope this helps ... -- G. On Jan 25, 2006, at 4:10 PM, Mark Daoust wrote:> Ben Reubenstien wrote: >> Mark ~ >> >> You can do this with One Table in your database using Single Table >> Inheritance (STI). You will have 4 models in the end, the base >> member >> class, and then the 3 types of members which inherit from the member >> class. >> You can do this in Rails by adding a field named "type" to your >> member >> table. I believe the Wiki has more information on STI. >> >> ~ Ben > > Isn''t there a way to do it using three models and three tables? I''d > like to keep the data separate as I am holding different information > about each - I''d rather not have one table that asks for the > address of > the admin (eventually me) - kind of pointless... > > I''ll look into STI - that seems close to what I am looking for. I > guess > ultimately what I am looking for is the equivalent of application.rb, > but for models rather than a controller... > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
I have something similar setup, and since the data the users contain is so unique, I opted for three tables. Also, I have a login page for each of these users, that need to be accessed by different URL''s. I end up having to use similar code for each of the login pages, views, controllers.... I know this is a prime candidite for refactoring to adhere to the DRY principles... however, I''m more of a IRM kind of guy now. ( I Repeat Myself). On 1/25/06, Ajai Khattri <ajai@bitblit.net> wrote:> > Mark Daoust wrote: > > >The way I am doing this right now, I will inevitably end up with > >repeated code in three different models. Is there a way I can define > >this code in one single place and simply reference it from the models? > > > > Sounds like that code should be in a helper... > > > -- > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060125/4851d248/attachment-0001.html
Mark, I''ll go ahead and throw in my two cents on this discussion as well. ;-) I feel that the two questions that needs to be answered when deciding whether to use STI or a library when DRYing up your models are: 1. How similar are the models that are going to use the STI functionality? 2. How reusable is the functionality that is going into a library in terms of your entire application? So, to relate this back to your current situation, I think you have to decide if your "members" are similar enough objects to warrant STI, and you also have to decide if the encryption method that is similar to your "members" might also be used elsewhere in your application.> Isn''t there a way to do it using three models and three tables? I''d > like to keep the data separate as I am holding different information > about each - I''d rather not have one table that asks for the address of > the admin (eventually me) - kind of pointless...I would first ask: how different is this information from member to member? Are we talking lots of similar attributes (like username, password, email, etc) and then a handful of dis-similar attributes (like address for some not for others, salary for some and not for others, etc.)? Or do you have a situation where the different members might only share a handful of similar items and then have a multitude of dis-similar ones? I have little mantra that I try to remind myself with whenever I''m dealing with users in an application and that is:"a User is a User is a User". In my experience I have found that when dealing with users, you usually have a common set of data that you are collecting for each user regardless of their type or role in the application. Because of this I usually create a common users table and then use STI to create the different "types" of user. Then, for the types that require dis-similar attributes I create tables to store that information and then use a belongs_to relationship. This ensures that I don''t add unnecessary attributes to tables that might not get used with all my users while giving me the flexibility to "extend" my user whenever I need to collect additional information about a different type of user by simply creating a new table. One thing you have to keep in mind when creating multiple tables for similar objects is that every time you have to add an attribute to your many objects you''ll have to add it in multiple tables instead of only having to add it to one table. All that said, maybe you might need the ability to "encrpt" attributes of other objects in a similar fashion somewhere else in your application. If this is the case, then adding that method to a library and then including it in whatever models might need it is definitely the way to go. You could even do a combination of the two and do STI for the members/users stuff and still pull the encryption method out into a library and then include it into your base member/user object and whatever other objects might need that functionality in your application. Sorry for the long winded post, but hopefully this adds a bit of perspective to the two approaches listed. -- DeLynn Berry delynn@gmail.com http://www.delynnberry.com
DeLynn, Thank you for your response...definitely some food for thought. The code that I want shared across the models is nothing more than a password encrypting code. I think using a library for this might be the way to go ultimately. The idea of extending dis-similar attributes of a user into a new table is interesting - I''ve never thought of doing it this way before. I''m not sure how much I would like that, though. I tend to be a bit of a simpleton, and having well-defined tables that say what they are and are self-contained just seems a bit easier to me. I definitely agree, however, with the idea that if the users are similar, a single table would be the best way to go. Unfortunately, with the three types of users, the only thing that they share is an id, username, and password. Beyond that, I am collecting different information... Mark Daoust -- Posted via http://www.ruby-forum.com/.
> Thank you for your response...definitely some food for thought. > The idea of extending dis-similar attributes of a user into a new table > is interesting - I''ve never thought of doing it this way before.Not a problem. Glad I could provide you with some brain food! :-)> I''m not sure how much I would like that, though. I tend to be a bit of a > simpleton, and having well-defined tables that say what they are and are > self-contained just seems a bit easier to me.There is definitely something to be said for keeping something simple when simple will do. My experience is mostly with internal, large scale, multi-user applications where I am collecting lots of similar things for my users (like > 30 pieces of data) and then also have other belongs_to attributes for the multitudes of other data I need to keep track of (multiple addresses, multiple phone numbers, multiple email addresses, etc). Personally I''ve found that managing small packaged tables is easier on my brain (I really hate to hoziontally scroll my tables ;-).> Unfortunately, with the three types of users, the only > thing that they share is an id, username, and password. > Beyond that, I am collecting different information...If this is the case, then using the library is probably a much easier route to take. You''re absolutely making the right decision. -- DeLynn Berry delynn@gmail.com http://www.delynnberry.com