Devise authentication gem: How to save the logged in user id? - ruby-on-rails

I'm using the Devise Ruby gem in my Ruby on Rails 3 application. When a logged in user creates one of my models, I want to save their user id as the person who created it. What should I do?

Create a migration file with a column of type integer named user_id, this is where the association will be stored. (see the migration guide for details on how to do this).
in your model, add: belongs_to :user (see the associations guide for more details)
in the controller for your model, add #your_model.user = current_user in the create action. This will do the association you're looking for. (current_user is a method provided by devise that returns the User ActiveRecord for the currently logged in user)
Note: there are more than one way of doing the actual association. I'm suggesting to do it in the controller but it could be done in the model or elsewhere.

Related

How to invite a user with devise_invitable directly from within Rails_Admin?

I have a Rails 5 application with a Rails_Admin installation. I work with a AdminUser model and a User model, both based on Devise.
I've also installed devise_invitable on the User model and used the AdminUser model for the invited_by reference.
I would like to add a 'invite user' action to the users collection (next to 'Add new') within Rails_Admin. I tried to figure out how to create a custom action, but I'm stuck.
Any ideas how I can solve this?

Programmatically creating User with devise and first_or_create

I've got to programmatically create users via an api -- I'm able to create users passing in the proper params ie:
x={"email"=>"kid#kid.com", "username"=>"levi", "password"=>"password","password_confirmation" => "password", "firstname"=>"Bob", "lastname"=>"Smith"}
u=User.new(x)
u.valid?
And able to check if this is a valid user before saving, etc. But the problem is that if params such as username or email already already exist for another user I'll get an error on save.
Now I can check if a user exists already (ie u=User.where(username: x['username']) or u=User.where(email: x['email']) -- and that might be enough but I'm wondering if there's a way of doing u=User.where(x).first_or_create with devise? Works generally with other models but not devise.
The problem with find_or_create_by (http://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_create_by) is that it will try to find a user matching all of the attributes you pass in as criteria. It is rarely a useful method. Instead, wrap it in your model:
class User < ActiveRecord::Base
def self.username_find_or_create(attributes = {})
User.create(attributes) unless User.exists?(attributes.slice(:username, :email))
end
end
(Exists is faster than where)

Tying rails account to scaffold

I have a rails application built on top of the Devise cancan bootstrap repo.
I am trying to make a page for employee's to log hours. I set up a scaffold, and it generates a view with the form on that scaffold, but my question is how do I link to that page from the menu, and how can I make it so those logged hours are tied to whichever employee is logged in.
My scaffold is
rails g scaffold hours email:string day:date hours:integer
So besides user creation and authentication Devise has added the following
User model (backed by a users table in the database)
current_user method available in your controller code and in your views
You want to use a foreign_key user_id instead of email in all related models, your scaffold generation would be something like this (I've changed the naming slightly from yours, but you get the idea)
rails g scaffold TimeSheet user_id:integer day:date hours_worked:integer minutes_worked:integer
Then you need to update your User model and the newly created TimeSheet model to create the associations between the two models
See rails guides for more information: http://guides.rubyonrails.org/association_basics.html
class User
# ...
has_many :time_sheets
end
class TimeSheet
belongs_to :user
end
You will need to remove the user_id from the scaffold generated views and set it in the controller during create and update actions
def create
#time_sheet = TimeSheet.new(params[:time_sheet])
#time_sheet.user = current_user
# ....

Devise with multiple models & multiple login forms

I'm using rails 3.2 and devise 2.1 to create a multi-site CMS
Requirements
Sites based Basecamp subdomains.
Have 3 "user" models. 1. Admin(superuser) 2. Authors(each have their own site on subdomain) & Subscribers(read the sites ).
Authors: registration is normal username/password combo but needs to be approved by admin. their registration form will have subdomain field.
Subscribers: registration happens by invitation email.
need separate login & registration forms
Possible Solutions
I have been searching & found few solutions
3 Separate models in devise:
$ rails generate devise admin
$ rails generate devise author
$ rails generate devise subscriber
but this gives the following error
$ rails generate devise author
/home/gaurish/.rvm/gems/ruby-1.9.3-p286-perf/gems/devise-2.1.2/lib/devise/rails/routes.rb:443:in 'raise_no_devise_method_error!': Admin does not respond to 'devise' method. This usually means you haven't loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb' (RuntimeError)
STI: single table in the database and for each user type create a model
class Admin < User; end
class Author < User; end
class Subscriber < User; end
Here, I am not sure how this would handle different login/registration workflows. example for subscriber I am planning on using devise_invitable for creating invitations. Admin doesn't need to scoped on basis of subdomains unlike authors & subscribers.
Does this seem complicated? I hope I was able to explain well.
You don't need to have three separate models to build this functionality. What you want to look at is the concept of Roles which are applied to one User model.
There is a Gem which provides this capability called Rolify and can be found at https://github.com/EppO/rolify
This would allow you to specify which users are in which Roles and change them as you see fit, all from one existing model.
Once you have Roles attached to the User model, you can override Devise's registration controllers to detect the Role and render different templates etc. You would do this by:
Running rails generate devise:views to unpack the views from the Devise gem into your project
Create your own Registrations controller:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
super
# Add logic here to detect Role and display different forms
end
def create
super
end
def update
super
end
end
Add the correct settings in your routes.rb file to tell Devise to use your new controller:
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
Admin does not respond to 'devise' method.
This may be cos you're also using the activeadmin gem, or something that uses a module called Admin, which causes a name conflict. Try renaming the model to AdminUser

whats the difference between these create methods

Hey I am stuck with my orientation in rails.
I got a User model, a Course Model and a CourseEnrollment Model.
When I want to add a link in my Course Index View like
link_to 'join' CourseEnrollment.create(:course_id => course.id, :user_id => current_user)
Does this create method belong to my Model? I am confused because in my User Model I defined a method that uses role_assignments.create(.....). What is the difference between these 2 create methods? I cant use course_enrollments.create by the way. Thx for your time
I'm a bit confused as to what you're asking, but I'll try my best.
(First of all, in your example, current_user should probably be current_user.id.)
When you call CourseEnrollment.create, you are simply creating a new CourseEntrollment model with the specified attributes.
Assuming that your User model has_many :role_assignments:
When you call #role_assignments.create from within your User model, Rails automatically creates the association for you (e.g. sets the user_id to the id of the user). This doesn't have to be done within the model itself, though:
current_user.role_assignments.create(...) # automatically sets the association
Assuming that your User model also has_many :course_enrollments, the following will create a CourseEnrollment model and automatically associate it with the current user:
current_user.course_enrollments.create(...)

Resources