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?
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
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
Related
I have a rails app where users can sign up and create posts, now what i want to achieve is that i want to give users option to create pages and those pages will be able to create post, what i have done till now is i have generated another controller called pages i have added users to that pages by doing a migration.
Relationship between modals look like:
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,
:omniauthable, :omniauth_providers => [:facebook, :twitter, :google_oauth2]
act_as_mentionee
validates :username, presence: true
validate :avatar_image_size
has_many :posts, dependent: :destroy
has_many :pages, dependent: :destroy
end
pages.rb
class Page < ActiveRecord::Base
validates :name, :description, :user_id, presence: true
belongs_to :user
has_many :posts, dependent: :destroy
delegate :username, to: :user
end
posts.rb
class Post < ActiveRecord::Base
act_as_mentioner
validates :title, :body, :user_id, presence: true
belongs_to :user
belongs_to :channel
end
Now i want to add posts to pages and i really don't know how to do that, i want to add posts in pages so pages can create post.
what will be the best way to go around this?
and if you know some kind of tutorial or gem for this please tell me.
First you need add a controller for User Model
to add a controller you can refer this rails guide
http://guides.rubyonrails.org/layouts_and_rendering.html
once controller is added you need to add your routes in routes.rb
resources :users
You need to add the corresponding views for each action in controller
In user model you can add
nested attributes for the :pages and :posts
see the below help document for nested attributes
https://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
Hope this answer gives you some idea on how to proceed further
I got a problem with my rails app. Here is my code in my Model:
class User < ApplicationRecord
has_many :assistants, class_name: User, foreign_key: :manager_id
belongs_to :manager, class_name: User
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
#validation
validates :first_name, :middle_name, :last_name, :birth_date, presence: true
end
Here is my Migration:
class AddReferenceToUserTable < ActiveRecord::Migration[5.0]
def change
add_column :users, :manager_id, :integer
end
end
BUT here is the error in my VIEW:
Sign up
1 error prohibited this user from being saved:
Manager must exist
May I know what wrong with my code?
Thanks,
Randz
If this is a rails 5 application belongs to is by default required. If a user will not always have a manager then you want
belongs_to :manager, class_name: User, required: false
i'm writing my first rails application using active_record-acts_as and devise. I have an User (devise authentication and actable) , Client (act_as) and Owner (act_as).I overrided the registration_controller to add some extra fields in the devise form, fields like name, surname etc. that i need for Client and Owner. I'm trying to sign up both Client and Owner using the devise authentication of the User but adding other fields. I thought to define the authentication on the User to avoid duplicates in the schema. Is it possible to do this without define the devise controller of both Client and Owner?
client.rb
class Client < ActiveRecord::Base
acts_as :user
end
owner.rb
class Owner < ActiveRecord::Base
acts_as :user
end
user.rb
class Utente < ActiveRecord::Base
actable
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { registrations: 'registrations' }
resources :clients
resources :users
resources :owners
end
I think what you should understand about the gem you are using is that, it buys you the idea of having empty columns. However it is necessary you note that, each details goes to its respective table.
Having said that, you can use rails authentication on any table where you hope to set authentication on.
Now based on the later part of your question, where you asked to avoid duplicates on your table, you set validation in your model, such that any of your model becomes:
class Utente < ActiveRecord::Base
actable
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :email, :uniqueness => true
end
You could see documentation of how you set validations on active_record-acts_as here
Since its MTI with Devise, respective data goes to where it's suppose to be right out of the box, then I will suggest you set validations on other tables that acts_as :user, but on attributes that are not on the actable devise table. For example:
class Client < ActiveRecord::Base
acts_as :user
validates :school, :uniqueness => true
end
How do you use User(devise which store email and password) to belong_to Profile and Profile has_one User? When I looked up the database profile_int is still nil hmmm... not sure where did I do wrong?
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :profile_id
# attr_accessible :title, :body
belongs_to :profile
end
class Profile < ActiveRecord::Base
attr_accessible :dob, :firstName, :lastName, :school_id, :schYear, :user_attributes
belongs_to :school
has_one :user
accepts_nested_attributes_for :user
end
I know usually I should do something like this Profile.create(.......) but I am not sure where to do this if I am doing it with a devise
Should :schoolstrong text be ':schoolstrong_text'? Did you run rake db:migrate ?
Also, checking your schema could be helpful too.
A common practice in associating a Devise User with a Profile model is making the profile the child of the user:
# app/models/user.rb
class User < ActiveRecord::Base
has_one :profile
end
# app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
Then, within your User model, you'd create an after_create hook to create a new Profile model and associate it with the newly created user:
# app/models/user.rb
after_create :create_profile
def create_profile
profile = Profile.create
self.profile = profile
self.save
end
I am using devise and I want create a polymorphic relationship, I added the columns to table users 'usersable_type' and 'usersable_id'
This is my code
Model >> User
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
# attr_accessible :title, :body
attr_accessible :email, :password, :password_confirmation, :remember_me
#usarsable
belongs_to :usersable, :polymorphic => true, :autosave => true, :dependent => :destroy
accepts_nested_attributes_for :usersable
end
Model >> Medic
class Medic < ActiveRecord::Base
attr_accessible :license_number, :specialty
has_one :user, as: :usersable, dependent: :destroy
has_and_belongs_to_many :patients
end
Model >> Patient
class Patient < ActiveRecord::Base
belongs_to :socialsecurity
attr_accessible :birthday, :blood_type
has_one :user, as: :usersable, dependent: :destroy
has_many :contacts
has_and_belongs_to_many :medics
end
Override Devise Controller
class RegistrationsController < Devise::RegistrationsController
def new
super
#user.build_usersable # I had problem in this line
end
def create
end
def update
super
end
end
Those are all the models I have for the moment, but I still have the same problem, I dont know how create and save the polymorphic object.
The error still is the same
ERROR: undefined method `build_usersable' for "<#User:"
Is anyone can help me I would be grateful
Regards and thanks in advance
Juli.
Based on the conversation in the comments this is the kind of scheme i think you need.
I am going to use the concept of Aspect, that is a user can have many aspects, the aspect might be a medic, a content detail etc; an Aspect can have only one user.
First you need a UserAspect model which has a user_id and a aspect_type and aspect_id
class UserAspect < ActiveRecord::Base
belongs_to :user
belongs_to :aspect, :polymorphic => true
end
Now your user model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
# attr_accessible :title, :body
attr_accessible :email, :password, :password_confirmation, :remember_me
#aspects
has_many :user_aspects
has_many :aspects, :through => :user_aspects
end
And now your medic
class Medic < ActiveRecord::Base
attr_accessible :license_number, :specialty
has_one :user_aspect, as: :aspect, dependent: :destroy
has_one :user, :through => :user_aspect
end
Now you can do things like
user.aspects
medic.user
etc