Hey I hope you can help me:
I was going through this tutorial
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/ and I did every step by step.
I wasnt quite sure where to put the role?-method from the tutorial, because it doesnt say where to place it.
Now it gives me this error when I want to sign_up or Sign_in
Many thanks
You need to add it in the user model (app/models/user.rb)
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
devise :database_authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
def role?(role)
return !!self.roles.find_by_name(role.to_s.camelize)
end
end
You should refer to this:
https://github.com/ryanb/cancan/wiki/Role-Based-Authorization
I think it'll be really helpful..
Related
I'm new to Rails 5 and I'm trying to model the following scenario using Devise and CanCanCan: a store application.
Relevant figures are: Admin, StoreManager, StoreOfficer, Customer, Technician.
Admin creates StoreManager.
StoreOfficer can create Customer's information to register new Customers.
StoreOfficer can see the complete list of all Customers with relative information
StoreOfficer can see the complete list of all Technicians with relative information
StoreManager can see the complete list of all StoreOfficers with relative information
StoreManager can enable StoreOfficers to use the system and edit their information
StoreManager can enable Customers created by StoreOfficers to use the system
StoreManager can see the complete list of all Customers with relative information
There are also some other paths, but it's possible for me to develop them as these presented cases are done.
Any help/tutorial please?
Thanks,
FZ
After trying some different things, I created the following satisfying schema, which I post here for others so that they can use something solid:
Class User<ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :userable, polymorphic: true
end
Then all the other roles classes similar to the following one:
class Customer < ApplicationRecord
belongs_to :technician
belongs_to :store_officer
has_one :user, as: :userable, dependent: :destroy
has_one :address, as: :addressable, dependent: :destroy
accepts_nested_attributes_for :user, :address
end
Accordingly, I created all the needed fields using migrations in the database.
Then I put in every controller the code before_action :authenticate_user!.
After populating the db a bit, I can now login with different users inserted using rake db:seed.
This is my routes.rb file:
Rails.application.routes.draw do
devise_for :users
resources :store_managers
resources :store_officers
resources :items
resources :technicians
resources :customers
resources :addresses
resources :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
What do you all think about this setup?
Now I want to introduce CanCanCan to my project. Please validate the following steps I'm going to do:
Run rails g cancan:ability
Put all the rules in the ability.rb file:
if user.admin?
can :manage, :all
elsif user.store_manager?
can :read, Customer
can :create, Customer
can :update, Item do |item|
item.try(:user) == user
end
can :destroy, Item do |item|
item.try(:user) == user
end
elsif user.store_officer?
can :read, Customer
end
.
.
.
Create the methods in user.rb model to check roles:
def customer?
self.userable_type == Customer
end
Put load_and_authorize_resource in every controller
Do you think this approach is the correct one? Or maybe I should put methods/definitions in other files?
Thanks,
FZ
I'm using Devise to manage user model.
Here's the User model, user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
acts_as_voter
has_many :topics
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Here's the Topics model, topic.rb
class Topic < ActiveRecord::Base
acts_as_voteable
belongs_to :user
end
When I create a post, the user ID is stored in the "user_id" column of Topics. I want to a User profile page, which should display all the posts he has made. In my User profile page view, I have,
<%= Topic.find_by_user_id(#user.id) %>
I have two posts made by the same user,
But when I try fetch all the posts made by the user, the SQL command automatically queries with a LIMIT of 1. Like this,
And because of this, the view is fetching only 1 post made by the user. How do I fetch all the posts?
find_by_attribute will always return only one result. You need to change your code to:
Topic.where(user_id: #user.id)
or even better:
#user.topics
I am attempting to create a rails 3.2.13 app where when the user is created a password is auto generated for that user. Right now I am using a before_validate to generate and assign the password to the password and password_confirmation fields on the user object before it is creates but devise still complains that the password is still blank.
What is the best approach to get devise to accept the password that I have generated for my user object? It would be nice to be able to do this without having to overwriting the internal validation if possible.
I don't known what you are doing wrong... Tried quickly here and everything turned out ok.
Here is my model
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
before_validation :set_user_password
def set_user_password
#password = Devise.friendly_token
end
end
I didn't even had to set password_confirmation just password and it saved without errors at the rails console.
The previous solution is awesome. But you can not reset your password. set_user_password should only execute when creating account.
before_validation :set_user_password, :on => :create
def set_user_password
#password = Devise.friendly_token
end
I'm using Devise for authentication with two custom fields added = :organization_id and :username. I also generated a scaffold for the Organization which simply consists of Name.
Currently when users sign up they can type in an Organization ID (integer) and a username (string).
Users belong_to organizations, and organizations has_many users.
Here's what my models look like (I left everything else untouched except for the files inside app/views/devise/registrations to add organization_id and username):
#user.rb
class User < ActiveRecord::Base
belongs_to :organization
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :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, :organization_id, :username
end
#organization.rb
class Organization < ActiveRecord::Base
has_many :users
end
What I would like is for an organization to be automatically created when a user signs up without the user having to specify the organization_id.
Also, ideally the #organization.name would be exactly the same as :username
How would I go about doing this?
I've seen the Railscast on nested model forms but he's creating a question inside the survey form, and questions belong to a survey. I need to do it the other way around (create an organization inside the user form, where users belong to a survey.)
Any help and suggestions would be greatly appreciated..
class User < ActiveRecord::Base
before_create :create_organization
private
def create_organization
self.organization = Organization.create :name => self.username
end
end
The create_organization method will be executed right before the sql query which creates the user. It'll create a new organization and assign it to the user.
First here's my current setup:
models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_many :events
end
models/event.rb
class Event < ActiveRecord::Base
belongs_to :user
end
So, this works in the sense that a user have many events that s/he can CRUD. Anyone that is not logged in can only view and list all the events.
From this initial setup, I now have another set of users that are attendees and the current users are now actually event managers instead of just a generic user. Essentially, I now have two models that are both users (since they can both log in/sign up and have the same fields) and I was thinking that event should read something like:
models/event.rb
class Event < ActiveRecord::Base
belongs_to :manager
has_many :attendees, :through => :attendance # attendance is a join model
end
but I don't want to create a separate table for managers and attendees and I was thinking of sub classing the user model but I'm not particularly sure about how to go about it. I was looking into the :as and :polymorphic parameters in AR but I'm still not quite sure on how to do it. Help?
What you are looking for is called Single Table Inheritance. Here is one resource on the subject. There are many more. Just google for "Rails Single Table Inheritance".