0

I have three models as follows:

user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  belongs_to :role, polymorphic: true

  validates_presence_of :first_name, :last_name, :email, :password,
    :password_confirmation
end

student.rb

class Student < ActiveRecord::Base
  has_one :user, as: :role, dependent: :destroy

  accepts_nested_attributes_for :user
end

teacher.rb

class Teacher < ActiveRecord::Base
  has_one :user, as: :role, dependent: :destroy

  accepts_nested_attributes_for :user
end

I have user registration and login working as expected. However, I cannot figure out how to direct users to the appropriate homepage when they're logged in.

I handle routing for authenticated users as follows:

authenticated :user do
  root to: "students#home", as: :user_root
end

Ideally if current user's role attribute is a student, then it sets students#home as :user_root. If it's a teacher, then it sets teachers#home as :user_root. Is there any way to handle this purely in routes?

Zach Latta
  • 3,251
  • 5
  • 26
  • 40

2 Answers2

1

They way you've structured it seems confusing to me. How much do teachers and students really have in common? Won't students and teachers need different associations, fields, and everything?

Why not have completely separate Student and Teacher models with different devise scopes? See devise wiki configuring multiple models: https://github.com/plataformatec/devise#configuring-multiple-models

For shared functionality you can have both inherit from an abstract model or use concerns / modules for shared functionality.

module DeviseConcern
  extend ActiveSupport::Concern

  included do
    devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :trackable, :validatable

    validates_presence_of :first_name, :last_name, :email, :password,
      :password_confirmation
  end
end
AJcodez
  • 31,780
  • 20
  • 84
  • 118
  • I primarily opted for a polymorphic user because teachers and students should log in and register through the same forms and because they behave very similarly, but not similarly enough for STI. We previously had two separate models and found we were writing duplicate code and introducing potential bugs (what if a teacher has the same email as a student? how do we handle login then?). My implementation is heavily inspired by http://stackoverflow.com/questions/7299618/multiple-user-models-with-ruby-on-rails-and-devise-to-have-seperate-registration – Zach Latta Dec 18 '13 at 07:47
  • Do you think two separate models would still make the most sense when they share most functionality and log in through the same forms? – Zach Latta Dec 18 '13 at 07:48
  • No code duplication if you use concerns and rspec shared examples. Devise doesn't use scoped views by default, so that's not a problem. And how would that be possible that a user and teacher have the same email? – AJcodez Dec 18 '13 at 07:56
1

While playing around with AJcodez's solution, some things like user authentication were less than pleasant to implement. I ended up opting for my original implementation.

One lesser known things about routes is that they can have lambas in them. Our routes ended up looking like the following:

authenticated :user, lambda { |u| u.role_type == "Student" } do
  root to: "students#home", as: :student_root
end

authenticated :user, lambda { |u| u.role_type == "Teacher" } do
  root to: "teachers#home", as: :teacher_root
end
Zach Latta
  • 3,251
  • 5
  • 26
  • 40