Creating a `Users` show page using Devise - ruby-on-rails

I'm trying to create a User show page (that will function as a profile page) but am confused about how to do this with Devise. It doesn't seem as though Devise comes with any sort of show definition - is there any way I can access the controllers Devise is implementing in order to make one or do I have to override them?

You should generate a users_controller which inherits from application_controller and define there your custom show method. Don't forget to create a view and routes for it.
Ex:
#users_controller.rb
def show
#user = User.find(params[:id])
end
#in your view
<%= #user.name %>
#routes.rb
match 'users/:id' => 'users#show', via: :get
# or
get 'users/:id' => 'users#show'
# or
resources :users, only: [:show]

Don't forget that your users routes should be below the devise_for users routes, like this:
#routes.rb
devise_for :users
resources :users, :only => [:show]
Also, if you are using a username or an email as the primary key instead of the usual id, you should avoid routing conflicts by declaring your routes as follow:
#routes.rb
devise_for :users, :path_prefix => 'd'
resources :users, :only => [:show]

showing current_user/ other_user profiles with devise:
After installing devise
Create a Users controller:
rails generate controller Users
Then create a show action and find the user with params id:
def show
#user = User.find(params[:id])
end
Create a show.html.erb file in the User view folder:
<%= #user.email %>
Linking to users show page:
<%= link_to "current_user_show", current_user %>
Now if you want to view other profiles create a index action in the users controller:
def index #users = User.all end
Create an index.html.erb in the User view folder then:
<% #users.each do |user| %>
<%= link_to user.username, user %>
<%= user.email %>
<% end %>
The link for this will be:
<%= link_to "show_index_of_users", users_path %>
This will link you to the users index.html.erb file there you will create a loop and link to users profile:
<% #users.each do |user| %>
<%= link_to user.username, user %>
<%= user.email %>
<% end %>
This should work!

you can generate the views used by devise, so you can change it as you want to.
rails g devise:views

Related

Devise update password route

On a rails app setup with Devise, i am trying to provide users with a form to change passwords.
i have followed the solution 3 from the Devise wiki:https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-edit-their-password
and accordingly have in a user controller
class UsersController < Devise::RegistrationsController
def update_password
#user = current_user
if #user.update(user_params)
# Sign in the user by passing validation in case their password changed
bypass_sign_in(#user)
redirect_to root_path
else
render "edit"
end
end
end
routes.rb
devise_for :users,
path: "", path_names: {
sign_in: "login",
sign_out: "logout",
sign_up: "register",
edit: "settings"
},
controllers: {
registrations: "users",
sessions: "users/sessions"
}
resources :users do
patch 'update_password'
end
Rake routes gives me :
user_update_password_path POST (/:locale)/users/:user_id/update_password(.:format)
users#update_password {:locale=>/fr|en|de/}
the link to access the menu is the following:
<%= link_to user_update_password_path(current_user) %>
in browser, that links directs me to :
http://localhost:3000/en/users/1/update_password
but I receive a Routing error
No route matches [GET] "/en/users/1/update_password"
When I wrap the
resources :users do
resources :wishlists
collection do
patch 'update_password'
end
end
the link_to send to
http://localhost:3000/1/password
Which results in the error
undefined local variable or method `user_update_password_path' for
<#:0x00007f86cfe48f10> Did you mean? user_password_path
however, rails routes shows:
update_password_users PATCH (/:locale)/users/update_password(.:format) users#update_password {:locale=>/fr|en|de/}
but a link_to
update_password_users_path
results in an error
Could not find devise mapping for path "/en/users/update_password".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller" end
2) You are testing a Devise controller bypassing the router. If so,
you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
What have I missed ?
First of all in the solution 3 it says resource not resources. Watch the differences carefully between yours and the below one -
resource :user, only: [:edit] do
collection do
patch 'update_password'
end
end
Second the like should direct to edit_user_path not update_password_user as that is the patch route.
Third, you have to add a edit action to your controller as the wiki suggests. And also a form for the action.
before_action :authenticate_user!
def edit
#user = current_user
end
and in app/views/users/edit.html.erb
<%= form_for(#user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="action_container">
<%= f.submit %>
</div>
<% end %>
You missed lots of things. Try reading the wiki again.

Why can't I route the patch method of one controller to the show method of another rails 5

I'm receiving this error message:
No route matches [POST] "/users/9"
I'm trying to figure out a way to have the update method of one controller and use it in the view of a show method of another controller. This is what my route file looks like.
routes.rb
Rails.application.routes.draw do
root 'dashboards#index'
devise_for :users
resources :users, only: [:show]
patch '/users/:id' => 'companyinfos#update'
put '/users/:id' => 'companyinfos#update'
resources :dashboards, only: [:index]
end
I'm finding the correct companyinfo through the users controller
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#companyinfo = Companyinfo.find(current_user.id)
end
end
and I'm saying to use this method inside of my company_info controller
companyinfos_controller.rb
class CompanyinfosController < ApplicationController
def update
#companyinfo = Companyinfo.find(current_user.id)
if #companyinfo.update(companyinfo_params)
flash[:notice] = "Saved ..."
else
flash[:alert] = "cannot save"
end
render 'edit'
end
private
def companyinfo_params
params.require(:companyinfo).permit(:CompanyStage)
end
end
and finally I'm using form_for to update it on users_path
show.html.erb
<%= form_for :companyinfo do |f| %>
<%= f.text_field :CompanyStage %>
<%= f.submit "save", class: "btn btn-success" %>
<% end %>
Updating the information in the database works fine when I update it through companyinfo/:id/edit but if I try to update it on another view such as users/:id I'm getting the error message above. What is the proper way to go about this?
UPDATE
Actually if I just do what the error message is telling me it works. Miracle right? Another question. Is there another way to have multiple routes from different controllers pointing to the same location? Or is this the best way?
Error says: No route matches [POST]
Update routes:
post '/users/:id' => 'companyinfos#update'
Or form method:
<%= form_for :companyinfo, method: :patch do |f| %>

Custom user page for rails using devise - Using Rails 4 and Ruby - 2.2

I am currently using devise for authentication which generates user.rb and controller for user, Welcome page(root page after authentication) which is main page of application where I need to show the total number of user created account in application, number of subject opted by current user and other details of current user. I am unable to route to user page when I am using the same user.rb and user_controller.rb.
routes.rb
root "welcome_pages#home"
devise_for :users
resources :subjects
resources :books
application.html.erb
<%= link_to "Home", root_path %></li>
<li><%= link_to "Books", books_path %></li>
<li><%= link_to "Subjects", subjects_path %></li>
<li><%= link_to "Users", users_path %></li>
What am I missing ? I am getting the following errors
No route matches [GET] "/users_path"
Let me know if I need to provide more informations.
Thanks in advance.
You gotta add user resource separately, something like:
devise_for :users
resources :users, only: [:index, :show] do
.....
end
users controller
def index
#users = User.all
end
preferred version since _user.html.erb will be reusable
views/users/index.html.erb
<%= render #users %> #this iterates thru all users and invokes _user partial
views/users/_user.html.erb
<%= user.name %> #in this case you don't need # since you used this rails shortcut #user.each do |user|.
version
views views/users/index.html.erb
<% #users.each |user| do %>
<%= user.name %>
....
<% end %>

How can I implement a 'create' action without 'new' action

How can I best implement this feature: As an admin, I can assign a Resident Manager to a Hall.
I have a User model with a namespace routing for the admin -I intend on having another namespace routing that would hold the functions of the RM-
I have a Hall model.
Since its a many-many relationship between the above to models, I have a Management join model which contains only user_id and hall_id columns.
I know implementing the above feature, entails creating a new record in the management table but I don't know how to do it. I didn't think using a form (management#new) would solve this because the admin should not know the user_ids/hall_ids...
BELOW IS WHAT I HAVE TRIED TO DO BUT I CAN'T GET IT RIGHT
When the admin gets to the user index page, s/he should see a link for Hall Assignment for each user. This link leads to the management show page for that particular user, which would show the list of halls assigned to that user and also the show all the other remaining halls that isn't assigned to the user. So, either clicking an ADD button or on the hall's name should add it to that user's assigned halls list which is on the same page.
Management#show page
<h2><%= #user.email %>'s assigned halls</h2>
<% #user.managements.each do |management| %>
<%= management.hall.name %>
<% end %>
<p> HALL LISTS </p>
<ul>
<% #halls.each do |hall| %>
<li><%= hall.name %> <%= button_to "Add" %> </li>
<% end %>
</ul>
Here's is my Management controller
class Admin::ManagementsController < ApplicationController
def index
#managements = Management.all
end
def show
#user = User.find(params[:id])
#halls = Hall.all
end
def create
#management = Management.create(managements_params)
redirect_to admin_management_path
end
private
def managements_params
params.
require(:management).
permit(user_id: params[:user_id], hall_id: params[:hall_id])
end
end
And here's a piece of what my routes file looks like:
namespace :admin do
resources :users, only: [:index, :update]
resources :halls, only: [:index, :new, :create]
resources :managements, only: [:index, :new, :create, :show] do
resources :halls, only: [:index]
end
end
Your "add" button is just a mini form (with mostly hidden fields). You can instead just make it an actual form (with the submit-button having the text "Add") and the id-values filled in from the item on the page... it just points to the same routes that you'd normally point the form that you'd find in the new template.
if you want more detail, then show us the code that you have written (rather than a verbal description of it).
Edit:
Ok, so you'd put a button on the page like this
<ul>
<% #halls.each do |hall| %>
<li><%= hall.name %> <%= button_to "Add", managements_path(management: {user_id: #user.id, hall_id: hall.id}, method: :put ) %> </li>
<% end %>
</ul>
Notice the managements_path - you might need to check that that routing is correct (check it against what is in rake routes). Note that you're passing in the user id and the hall id, and that you must set the method to "put" on the button.
First things first -
How can I implement a 'create' action without 'new' action
It's relatively simple to do - you will need a create action somewhere, but a new action is just a way to build the respective ActiveRecord object for your controller.
If you do this in another action, you just have to make sure you point the form to the correct create action (and that create action to redirect back to
--
New / Create
Here's how you could handle the new / create actions in different controllers, as an example for you:
#app/controllers/users_controller.rb
Class UsersController < ApplicationController
def index
#hall = Hall.new
end
end
#app/controllers/halls_controller.rb
Class HallsController < ApplicationController
def create
#hall = Hall.new hall_params
redirect_to users_path if #hall.save
end
private
def hall_params
params.require(:hall).(:hall, :attributes, :user_id)
end
end
This will allow you to show the following:
#app/views/users/index.html.erb
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%= form_for #hall, url: hall_path do |f| %>
<%= f.hidden_field :user_id, value: user.id %>
<%= f.text_field :x %>
<%= f.submit %>
<% end %>
<% end %>
--
Fix
ADD button or on the hall's name should add it to that user's assigned halls list
For this, I don't think you'd need a create action in the "traditional" sense - it will be more about adding new halls to a user's current halls. This is much different than creating a new hall itself:
#config/routes.rb
namespace :admin do
resources :users do
post "hall/:id", to: :add_all #=> domain.com/admin/users/:user_id/hall/:id
end
end
#app/controllers/admin/users_controller.rb
Class UsersController < ApplicationController
def add_hall
#user = User.find params[:user_id]
#hall = Hall.find params[:id]
#user.halls << #hall
end
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :user_halls
has_many :halls, through: :user_halls
end
#app/models/hall.rb
Class Hall < ActiveRecord::Base
has_many :user_halls
has_many :users, through: :user_halls
end
#app/models/user_hall.rb
Class UserHall < ActiveRecord::Base
belongs_to :user
belongs_to :hall
end
This uses the ActiveRecord collection methods to make this work, to which you'll be able to provide the following:
#app/views/users/index.html.erb
<% #users.each do |user| %>
<%= link_to user.name, user %>
<%= button_to "Add Hall Test", user_add_hall_path(user, 1) %>
<% end %>

Rails Devise: How to access sign up page after signed in?

I am new with rails and i am using "devise" gem for authentication purposes.
At first i add a new user through default sign up page (E.g./users/sign_up)
Then, i made "sign_up" page only available to signed_in users by following instructions from
Devise before filter that prevents access to "new_user_registration_path" unless user is signed-in
Now, after sign in process when i try open sign up page it always directs me to root_path! How can i access sign up page?
My "roots.rb" file as follows:
Example::Application.routes.draw do
devise_for :users, :controllers => { :registrations => 'registrations'}
resources :companies
resources :orders
resources :customers
root :to => "welcome#index"
end
Thank you all!
I have other decision. Bitterzoet said
As you can see in the devise source if you navigate to the sign_up it executes the before_filter require_no_authentication and this redirects to the root path which you can find here.
You don't need override registration_controller, you can change only your custom registration_controller that echo original registration_controller.
class Admin::RegistrationsController < Devise::RegistrationsController
layout 'admin'
prepend_before_filter :require_no_authentication, :only => []
prepend_before_filter :authenticate_scope!
end
If you are getting redirected it probably means you are not properly authenticated when you navigate to that page, seeing as it requires a valid user session.
Please post your Registrations controller file as well.
If you are getting redirected it probably means you are not properly authenticated when you navigate to that page, seeing as it requires a valid user session.
Please post your Registrations controller file as well.
Addition:
As you can see in the devise source if you navigate to the sign_up it executes the before_filter require_no_authentication and this redirects to the root path which you can find here.
I think you will have to explicitly override the registrations_controller that I linked first if you really want to override this behaviour :-)
The way I handled the scenario of being able to create New Users if you are signed in was by generating a User controller and having new and create action methods that would save to the User model. (This was stripped from a current app I'm working on so hopefully I didn't miss anything)
user_controller.rb
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Successfully created User."
redirect_to root_path
else
render :action => 'new'
end
end
views/user/new.html.erb
<%= form_for #user, :url => user_index_path do |f| %>
<p><%= f.label :email %>
<%= f.text_field :email %></p>
<p><%= f.label :password %>
<%= f.password_field :password %></p>
<p><%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %></p>
<p><%= f.submit "Save" %></p>
<% end %>
config/routes.rb (Rails 3)
resources :user, :controller => "user"
Link to the New User page
<%= link_to 'New User', new_user_path %>

Resources