# Multiple user types. Polymorphism Devise

**URL:** <https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016>\
**Category:** rubyonrails-talk\
**Created:** [June 22, 2016, 9:41am UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016 "2016-06-22T09:41:14Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [June 22, 2016, 9:41am UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/1 "2016-06-22T09:41:14Z")

</div>

A few months ago I decided to learn how to use Ruby on Rails, and after learn some Ruby and do some projects by videotutoriales decided to start my own project. Once I made a diagram of classes and relationships that I need, I find my first problem: I need multiple user profiles where to some types of users require more information than others. In addition to each type of user, once registered, will have different home pages with different functions. My intention is to make a polymorphic association from the User model, generate by devise, containing the common attributes of all types of users (email, name, password) to the models user types (chef, singer, athlete, ...):

class User \< ActiveRecord::Base ... belongs\_to :meta, :polymorphic =\> true end

class Chef \< ActiveRecord::Base has\_one :user, :as =\> :meta ... end (more models)

According thought, the class of each user would be recorded at the time of the registration, from the form devise registration view, by adding a dropdown selector to choose a single type of user. And to log in, only will be necessary the password and email, without the selector. But I really have no idea of ​​how to do this ( i don't know how enable the selector to record the user class and do the appropriate modifications to the controller Registrations devise or as a redirect to different pages depending on the type of user who logs). I ask for help if you have dealt with a similar problem, if you know some way to do this, or if there is another easier way and efficient. Sorry if I said a bad concept, but have little time using ruby ​​on rails and I'm a little lost and for my bad english!. Thank you very much in advance and regards!

PS: I would avoid using gems, as camcam, for the many conditionals that is necessary, that in my opinion, overload the system. I also read concepts such as STI (singular table inheritance), but I thought it would not be applicable here to store variable information for each type of user.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 1, 2016, 8:40pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/2 "2016-07-01T20:40:16Z")

</div>

I don't think you need to use polymorphism for this.

I'd use STI for users and just keep the very basics in the user table(profile name, email address, type etc). Then have something like chef\_info and athlete\_info tables which contain the rest of the differing information for each user type. This way you don't have a lot of nil values in columns in your user table.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 11, 2016, 9:06am UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/3 "2016-07-11T09:06:36Z")

</div>

Johnny Stewart wrote in post #1184402:

> I don't think you need to use polymorphism for this.
> 
> I'd use STI for users and just keep the very basics in the user table(profile name, email address, type etc). Then have something like chef\_info and athlete\_info tables which contain the rest of the differing information for each user type. This way you don't have a lot of null values in columns in your user table.

Thanks for your response. i understood STI is applicable when save the same information for all the user types. you know some tutorial page about this?. Regards.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 11, 2016, 6:41pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/4 "2016-07-11T18:41:51Z")

</div>

No tutorial that I know of..

You have the same information for all user types, namely just the important information for users. So - you keep password, username, first name, last name, email address etc in the User table.

Stuff like sport, training ground, weight, height, body-fat etc would go in a table like AthleticInfo

stuff like restaurant, food speciality, chef qualifications etc would go in a table like ChefInfo

then if user1 is a chef, he would have all the user info + type Chef and he would have an entry in the chef table

user2 if she was a footballer would have all the user info + type Athlete and she would have an entry in the athlete table

So, you don't need to keep all the chef or athlete data in the user table - you just have a reference to that info in the relevant table..

---

<div class="post-metadata">

**Author:** ![Colin\_Law](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@Colin\_Law](https://discuss.rubyonrails.org/u/Colin_Law)\
**Post date:** [July 11, 2016, 8:31pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/5 "2016-07-11T20:31:21Z")

</div>

That does not sound like STI, STI is where you \*do\* store all the information in one table (Single Table Inheritance), but ignore the irrelevant parts dependent on the type.

Colin

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 11, 2016, 9:55pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/6 "2016-07-11T21:55:46Z")

</div>

Johnny Stewart wrote in post #1184570:

> No tutorial that I know of..
> 
> You have the same information for all user types, namely just the important information for users. So - you keep password, username, first name, last name, email address etc in the User table.
> 
> Stuff like sport, training ground, weight, height, body-fat etc would go in a table like AthleticInfo
> 
> stuff like restaurant, food speciality, chef qualifications etc would go in a table like ChefInfo
> 
> then if user1 is a chef, he would have all the user info + type Chef and he would have an entry in the chef table
> 
> user2 if she was a footballer would have all the user info + type Athlete and she would have an entry in the athlete table
> 
> So, you don't need to keep all the chef or athlete data in the user table - you just have a reference to that info in the relevant table..

Thanks for your response. But isn't this a polymorphic association?. I'am trying to do exactly that with a polymorphic association, that is, create the user table with all the common information, and with meta\_type:string (that saves the type of user) and meta\_id:integer (that saves the id of the user on his type of user table), and implement the associations y the models after, like this: class User \< ActiveRecord::Base ... belongs\_to :meta, :polymorphic =\> true end

class Chef \< ActiveRecord::Base has\_one :user, :as =\> :meta ... end (more models)

So , each register user will have an entry in the user table, and on his user type table. The problem is that i don't know to modify the Registration controller of Devise to do that. Regards!

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 13, 2016, 3:00pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/7 "2016-07-13T15:00:07Z")

</div>

> Thanks for your response. But isn't this a polymorphic association?. I'am trying to do exactly that with a polymorphic association, that is, create the user table with all the common information, and with meta\_type:string (that saves the type of user) and meta\_id:integer (that saves the id of the user on his type of user table), and implement the associations y the models after, like this: class User \< ActiveRecord::Base ... belongs\_to :meta, :polymorphic =\> true end
> 
> class Chef \< ActiveRecord::Base has\_one :user, :as =\> :meta ... end (more models)
> 
> So , each register user will have an entry in the user table, and on his user type table. The problem is that i don't know to modify the Registration controller of Devise to do that. Regards!

No - its not polymorphic at all. The type column is there due to STI.

class User \< ActiveRecord::Base end

class Athlete \< User &nbsp;&nbsp;has\_one :athlete\_info, dependent: :destroy end

class Chef \< User &nbsp;&nbsp;has\_one :chef\_info, dependent: :destroy end

class AthleteInfo \< ActiveRecord::Base &nbsp;&nbsp;belongs\_to :athlete end

class ChefInfo \< ActiveRecord::Base &nbsp;&nbsp;belongs\_to :chef end

chef\_info table is where the chef specific information is held, same for athlete. No complication of polymorphism required..

J.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 13, 2016, 3:14pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/8 "2016-07-13T15:14:54Z")

</div>

Colin Law wrote in post #1184575:

> > in a table like ChefInfo
> > 
> > then if user1 is a chef, he would have all the user info + type Chef and he would have an entry in the chef table
> > 
> > user2 if she was a footballer would have all the user info + type Athlete and she would have an entry in the athlete table
> > 
> > So, you don't need to keep all the chef or athlete data in the user table - you just have a reference to that info in the relevant table..
> 
> That does not sound like STI, STI is where you \*do\* store all the information in one table (Single Table Inheritance), but ignore the irrelevant parts dependent on the type.
> 
> Colin

As I understand it STI is best suited to situations where the data is the same but the behaviour is different. For the User model it really only has to handle registrations etc. I don't think there is any need to hold data pertaining to that user being a chef.

All it needs is maybe profile name, email address, password etc. That needn't change here.

Using STI we store that one extra column of type - then use that to see what table that user's extra info is held in (chef\_info, athlete\_info etc).

J.

---

<div class="post-metadata">

**Author:** ![Colin\_Law](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@Colin\_Law](https://discuss.rubyonrails.org/u/Colin_Law)\
**Post date:** [July 13, 2016, 3:20pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/9 "2016-07-13T15:20:00Z")

</div>

I do not believe that is the usual use case for STI. See [0] for a good description of the use of STI.

Colin

[0] [How (and When) to Use Single Table Inheritance in Rails - eugenius](http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/)

Colin

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 13, 2016, 3:45pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/10 "2016-07-13T15:45:05Z")

</div>

Colin Law wrote in post #1184606:

> > > > So, you don't need to keep all the chef or athlete data in the user
> > 
> > only has to handle registrations etc. I don't think there is any need to hold data pertaining to that user being a chef.
> > 
> > All it needs is maybe profile name, email address, password etc. That needn't change here.
> > 
> > Using STI we store that one extra column of type - then use that to see what table that user's extra info is held in (chef\_info, athlete\_info etc).
> 
> I do not believe that is the usual use case for STI. See [0] for a good description of the use of STI.
> 
> Colin
> 
> [0]

> **[How (and When) to Use Single Table Inheritance in Rails - eugenius](http://eewang.github.io/blog/2013/03/12/how-and-when-to-use-single-table-inheritance-in-rails/)**
>
> Last week as I was developing an application to track and analyze ticket and event postings, I came across a design problem. I had first started …

> Colin

Hi Colin,

Maybe not, however, I still think adding in a lot of nullable columns into the User table when they don't need to be there doesn't make sense.

From the blog post you cite above:

"If sub-classes that you intend to use for STI have many different data fields, then including them all in the same table would result in a lot of null values and make it difficult to scale over time."

So, I think that there is no real need to have things like food-speciality and training-ground-address in the User table. These are better moved into other tables. Also - as regards the OP it removes the need to bring in polymorphism and messing about with Devise's registrations controller.

J.

---

<div class="post-metadata">

**Author:** ![Colin\_Law](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@Colin\_Law](https://discuss.rubyonrails.org/u/Colin_Law)\
**Post date:** [July 13, 2016, 4:12pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/11 "2016-07-13T16:12:51Z")

</div>

Agreed if there are "many different data fields". As is always the case I advise using the KISS principle. Do it the easy way first (easy code has fewer lines and therefore fewer bugs) and only if proven necessary then add complexity to improve efficiency. Nine times out of ten (probably more) it will not be necessary.

Possibly an even better solution to the OPs problem would be to use roles for different user types and not even have the complexity of STI. It depends how much role specific data and behaviour there is. My advice would be to start with just roles and move to STI if necessary.

Colin

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 13, 2016, 4:36pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/12 "2016-07-13T16:36:27Z")

</div>

Thanks so much for you help and advices J. and Colin. I have much clearer ideas about this. Regards.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 13, 2016, 4:37pm UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/13 "2016-07-13T16:37:07Z")

</div>

Thanks so much for you help and advice J. and Colin. I have much clearer ideas about this. Regards.

---

<div class="post-metadata">

**Author:** ![11155](https://avatars.discourse-cdn.com/v4/letter/1/d26b3c/32.png) [@11155](https://discuss.rubyonrails.org/u/11155)\
**Post date:** [July 14, 2016, 9:12am UTC](https://discuss.rubyonrails.org/t/multiple-user-types-polymorphism-devise/72016/14 "2016-07-14T09:12:12Z")

</div>

Colin Law wrote in post #1184608:

> Possibly an even better solution to the OPs problem would be to use roles for different user types and not even have the complexity of STI. It depends how much role specific data and behaviour there is. My advice would be to start with just roles and move to STI if necessary.
> 
> Colin

Interesting, I hadn't thought of that - I'm going to have a root round in this area and a read up..

J.
