How to create an admin user with Ruby on Rails - ruby-on-rails

I'm new to ruby on rails, and so far, I have created the user login, signup, signout, but I wanna create an admin user, and I have no idea how to do this.
route.rb is:
Rails.application.routes.draw do
get 'courses/index'
get 'courses/new'
get 'courses/edit'
get 'courses/show'
get 'course/index'
get 'course/new'
get 'course/edit'
get 'course/show'
get 'sessions/signin'
get 'sessions/main'
get 'sessions/profile'
get 'sessions/setting'
get 'users/new'
get 'home/index'
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout"} do
collection do
get :signin
get :main
get :profile
get :setting
end
end
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
#resources :course, only: [:index, :new, :edit, :show]
resources :courses
resources :course_groups
patch 'course_groups/:id/add_course', to: 'course_groups#add_course', as: 'course_group_add_course'
delete 'course_groups/:id/delete_course', to: 'course_groups#destory_course', as: 'course_group_destory_course'
resources :rules
patch 'rules/:id/add_group', to: 'rules#add_group', as: 'rule_add_course_group'
delete 'rules/:id/delete_group', to: 'rules#destroy_group', as: 'rule_destroy_course_group'
resources :requirements
patch 'requirements/:id/add_rule', to: 'requirements#add_rule', as: 'requirement_add_rules'
delete 'requirements/:id/delete_rule', to: 'requirements#destroy_rule', as: 'requirement_destroy_rules'
#resources :plans
resources :users do
resources :plans
end
patch 'users/:user_id/plans/:id/add_course', to: 'plans#add_course', as: 'plan_add_course'
delete 'users/:user_id/plans/:id/delete_course', to: 'plans#destory_course', as: 'plan_destory_course'
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
#match '/profile', to: 'sessions#profile', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
match '/show', to: 'users#show', via: 'get'
match '/profile', to: 'users#profile', via: 'get'
#match '/info', to: 'users#info', via: 'get'
#match '/changepass', to: 'users#edit', via: 'get'
end
and my users_controller.rb is:
class UsersController < ApplicationController
before_filter :check_if_signned_in, only: [:show, :edit, :update, :delete]
before_filter :signed_in_user, only: [:edit, :update]
before_filter :skip_password_attribute, only: :update
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to #user, notice: 'User was sucessfully created!'
else
render action: "new"
end
end
#if current user exits, then it can get back to the main page of user
def show
if current_user.nil?
#user = User.find(params[:id])
else
#user = User.find(current_user)
end
end
def edit
##user = User.find(params[:id])
##user = User.find(current_user)
#user = current_user
#user.save
#title = "Edit profile"
end
def update
#user = User.find(params[:id])
##user = User.find(current_user)
#if #user.update_attributes(user_params)
if #user.update_attributes(user_params)
flash[:success] = "Profile updated."
#sign_in #user_params
redirect_to #user
else
#title = "Edit profile"
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def signed_in_user
redirect_to signin_path, notice: "Please sign in." unless signed_in?
end
def edit_user
params.require(:user).permit(:name)
end
def skip_password_attribute
if params[:password].blank? && params[:password_confirmation].blank?
params.except!(:password, :password_confirmation)
end
end
end
the application_controller.rb is:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
#protect_from_forgery with: :exception
protect_from_forgery
#before_filter :session_expire
#before_filter :update_active_time
include SessionsHelper
def check_if_signned_in
deny_access unless signed_in?
end
#def update_active_time
# session[:expires_at] = default_expire
#end
def is_owner
current_user.id == params[:id]
end
#private
# def get_session_time_left
# expire_time = session[:expires_at] #|| default_expire
# a = expire_time
# b = Time.now
# #session_time_left = (a - b).do_i
##session_time_left = (expire_time - Time.now).do_i
# end
end
Anyone can teach me how to create an admin user please? When the admin user logins, it will go to another different page.
Thank you in advance!

Without being rude, your code really needs to be cleaned up.
Your routes alone are a mess - I think I remember giving you some code to help them the other day, and it appears you've used it! However, you've left the other routes in there still - which is likely going to cause big issues down the line
Routes
Firstly, you need to get your routes in order:
#config/routes.rb
resources :courses
resources :users, path_names: {new: "signup"} do
collection do
get "main", action: :new
end
end
resources :sessions, path_names: {new: "signin", destroy: "signout", index: "main", edit: "profile", update: "setting"}
resources :home, only: [], path: "" do
get :about
end
root 'home#index'
resources :courses, only: [:index, :new, :edit, :show]
resources :course_groups do
patch :add_course
delete :delete_course
end
resources :rules do
patch :add_group
delete :delete_group
end
resources :requirements do
patch :add_rule
delete :delete_rule
end
resources :users do
resources :plans do
patch :add_course
delete :delete_course
end
end
match '/about', to: 'home#about', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match ':controller(/:action(/:id))(.:format)', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
match '/main', to: 'users#new', via: 'get'
match '/setting', to: 'sessions#setting', via: 'get'
match '/editname', to: 'users#edit', via: 'get'
Simply, everything in Rails is resource / object - orientated. This includes the routes, and you should therefore make sure that every route you have is constructed around a resource (that's why you can define routes as resources etc)
--
Admin
To create an admin user, there are several options available to you:
Have a separate admin model
Create an admin attribute in your User model
I would strongly recommend including an admin attribute in your User model - make it a boolean column like this:
#new migration
add_column :users, :admin, :boolean
This will allow you to call the following
#user = User.find params[:id]
#user.admin? #-> true / false
This will allow you to use several conditional statements in both the controllers & views of your application, to determine if the user had admin privileges or not

Related

Admin function in rails: Error: Couldn't find User with 'id'=

I am trying to write an update function, which allows to pick a user in a list of users and update that user to make it an admin. The important function in the controller should be def change_admin.
Thanks for your help!
I tried several options, but I run into that error:
Couldn't find User with 'id'=
My Controller:
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def new
#user = User.new
end
def index
#users = User.where(activated: true).paginate(page: params[:page])
end
def show
#user = User.find(params[:id])
redirect_to root_url and return unless #user.activated
end
def edit
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "Der Nutzer wurde gelöscht"
redirect_to users_url
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
redirect_to root_path
else
render 'edit'
end
end
def create
#user = User.new(user_params)
if #user.save
#user.send_activation_email
flash[:info] = "Bitte öffnen Sie Ihr E-Mail Postfach, um den Account zu aktivieren."
redirect_to root_url
else
render 'new'
end
end
def admin
#users = User.where(activated: true).paginate(page: params[:page])
end
def change_admin
#user = User.find(params[:id])
#user.update_attribute(:admin,true)
respond_to do |format|
format.html { redirect_to admin_path }
end
end
# Before filters
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation,
:mat_number, :ects, :grade_avg, :enrolled, :matched_institute)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
I also tried to delete the user.find line, but that gives me another error:
undefined method `update_attribute' for nil:NilClass
My routes file:
Rails.application.routes.draw do
resources :preferences
resources :institutes
get 'password_resets/new'
get 'password_resets/edit'
get '/users_show', to: 'users#show'
get '/users/new'
root 'static_pages#home'
get '/home', to: 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/matching', to: 'static_pages#matching'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get '/admin', to: 'users#admin'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
get '/performance_show', to: 'users#performance_show'
get '/performance_update', to: 'users#performance_update'
post 'preferences/create_all', :to => 'preferences#create_all'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
post 'preferences/delete_matching', :to => 'preferences#delete_matching'
post 'preferences/read_and_show_ofv', :to => 'preferences#read_and_show_ofv'
post 'preferences/read_matching', :to => 'preferences#read_matching'
post 'preferences/optimize_matching', :to => 'preferences#optimize_matching'
post 'preferences/optimize', to: 'preferences#optimize'
end
Your routes are in pretty bad shape. You have tons of duplication as well as routes that are missing the :id segment to make them work:
get '/users_show', to: 'users#show'
get '/users/new'
post '/change_admin', :to => 'users#change_admin', as: 'change_admin'
resources :users already declares a proper show route as GET /users/:id and new as /users/new.
To add additional RESTful routes you should instead pass a block to resources:
resources :users do
# this should be PATCH not POST
patch :change_admin
end
This will create the proper route as /users/:id/change_admin.
You are also using the wrong HTTP verb in many places like for example get '/performance_update', to: 'users#performance_update'. Never use GET for actions that create or alter a resource as the call ends up in the browsers history and may be cached.
Adding update, change, create in the path of your route should be a big red flag that you´re doing it wrong.
I would recommend that you read the guides thoroughly before adding more cruft.

Following and unfollowing events

I've done Michael Hartl Ruby on Rails 5 tutorial and am now trying to apply the code to my own app.
What I'm trying to do is:
Follow/Unfollow an event
Display total count of users following this event
Users can see all the events that they are following
The current error appears when I try to render the conferences that current user is following.
The error that I get is:
ActionController::UrlGenerationError in Users#show
No route matches {:action=>"followers", :controller=>"conferences", :id=>nil} missing required keys: [:id]
The line that causes the problem is:
<a href="<%= followers_conference_path(#conference) %>">
Now obviously their is something wrong in my routing and I assume the following problem states that conferences is missing a required id?
Does anyone know the solution to my problem? Which is getting allowing users to follow events and see what events they are following
USER CONTROLLER SHOW
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
#managments = #user.managments.paginate(page: params[:page])
#conference = Conference.find(params[:id])
end
ROUTES.RB
Rails.application.routes.draw do
root 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/my_conference', to: 'my_conference#show'
get '/conferences', to: 'conferences#index'
get '/conferences_list', to: 'conferences#index_admin'
get '/my_employees', to: 'employees#index'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/login', to: 'sessions#new'
put 'activate/:id(.:format)', :to => 'users#activate', :as => :activate_user
put 'deactivate/:id(.:format)', :to => 'users#deactivate', :as => :deactivate_user
put 'activate_employee/:id(.:format)', :to => 'employees#activate', :as => :activate_employee
put 'deactivate_employee/:id(.:format)', :to => 'employees#deactivate', :as => :deactivate_employee
resources :users do
member do
get :following
end
end
resources :conferences do
member do
get :followers
end
end
resources :articles
resources :users
resources :employees
resources :account_activations, only: [:edit]
resources :activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
resources :managments
resources :conferences
resources :relationships, only: [:create, :destroy]
end
CONFERENCES_CONTROLLER.RB
class ConferencesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
before_action :admin_user, only: :destroy
def index
#conferences = Conference.paginate(page: params[:page])
if params[:search]
#conferences = Conference.search(params[:search]).order("created_at DESC").paginate(page: params[:page])
else
#conferences = Conference.all.order('created_at DESC').paginate(page: params[:page])
end
end
def new
#user = User.new
#conference = Conference.new
end
def create
#conference = current_user.conferences.build(conference_params)
if #conference.save
flash[:success] = "conference created!"
redirect_to conferences_path
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'new'
end
end
def destroy
#conference.destroy
flash[:success] = "conference deleted"
redirect_to request.referrer || root_url
end
def following
#title = "Following"
#conference = Conference.find(params[:id])
#conferences = #conference.following.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
private
def conference_params
params.require(:conference).permit(:conference,:country , :month, :presence, :audience, :cost ,:picture)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
def correct_user
#conference = current_user.conferences.find_by(id: params[:id])
redirect_to root_url if #conference.nil?
end
end
Ahh, i see the issue.
Check your UsersController#show to see if #conference is being set anywhere.
If not try: <a href="<%= followers_conference_path(current_user.id) %>">
You don't want to use the user id to get the #conference object, I'm sure. Instead, you are probably generating a list of conferences the user is following. In that case, you'd use something like this
<% #user.conferences.each do |conference| %>
<%= conference.name %>
<% end %>
And, in Rails, you would usually use the link_to helper, and maybe include a count to show how many followers the conference has.
<% #user.conferences.each do |conference| %>
<%= link_to conference.name, followers_conference_path(conference) %>
(<%= pluralize conference.users.count, 'follower' %>)
<% end %>

Can not get param by json method

http://localhost:3000/users.json?q=lala
I want to get json by sending some string,
But I can not get the expected string 'lala' in params[:q]
p(params) `{"action"=>"index", "controller"=>"users", "locale"=>"en"}`
controller.rb
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
# #users = User.all
#users = User.order(:name)
(1..100).each {p(params)}
respond_to do |format|
format.html
format.json {render json: #users.where("name like ?", "%#{params[:q]}%")}
end
end
This is my route.rb
scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
resources :articles
resources :users
root to: 'articles#index'
end
match '*path', to: redirect("/#{I18n.default_locale}/%{path}"), constraints: lambda { |req| !req.path.starts_with? "/#{I18n.default_locale}/" }, :via => [:get]
match '', to: redirect("/#{I18n.default_locale}"), :via => [:get]
match '', to: redirect("/#{I18n.default_locale}"), :via => [:get]
if you put resources :users outside the scope ":locale",then the routes will generate normal routes like
GET /users users#index users_path
RESTful routing creates by default.
Please see this

Rails Routing Error? 'No route matches'

So I keep running into the following error:
No route matches {:action=>"show", :controller=>"users"}
I tried running rake routes and I can see that the route exists:
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
But every time I try visiting the page "/users/1" (1 being the user id), I get the above error. Any ideas? Thanks!
Here's my routes.rb:
SampleApp::Application.routes.draw do
root to: 'static_pages#home'
resources :users
resource :sessions, only: [:new, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
Here's my users_controller.rb:
class UsersController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
before_filter :correct_user, only: [:edit, :update]
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Paper Piazza!"
redirect_to #user
else
render 'new'
end
end
def edit
#user = User.find(params[:id])
end
def update
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to #user
else
render 'edit'
end
end
def index
#users = User.paginate(page: params[:page])
end
private
def signed_in_user
unless signed_in?
store_location
redirect_to signin_path, notice: "Please sign in."
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_path) unless current_user?(#user)
end
end
Try fixing the typo:
root :to 'static_pages#home'
(rather than root to:), and moving it to the last line of the block. And let me know if that makes a difference!
What's odd is that I built a fresh project with a routing file that simply reads:
RoutingTest::Application.routes.draw do
resources :users
root :to => "static_pages#home"
end
When I ran this in the console, I got the same error you're seeing:
>> r = Rails.application.routes ; true
=> true
>> r.recognize_path("/users/1")
=> ActionController::RoutingError: No route matches "/users"
... but when I run the same thing in a slightly older project, I get:
>> r = Rails.application.routes ; true
=> true
>> r.recognize_path("/users/1")
=> {:action=>"show", :controller=>"users", :id=>"1"}
So I have little confidence that what I'm telling you will make a difference. (Aside from that, the Rails.application.routes trick is useful for verifying paths in the console!)
I had a similar problem, I had routes that would just return the root page, but would show up in rake routes. According to a fellow developer for a specific namespace and for all routes the root to: (routing) must always be last. This is in contradiction to the Rails guide on routing (see http://guides.rubyonrails.org/routing.html#using-root) which says that any call to root should be at the top of your file. That was definitely not working for me. Interesting...

Routing Error in Topics

I am writing an application , which User can create Topics and others can make posts on that topic.
I am stuck with this error :
No route matches {:action=>"show", :controller=>"topics", :id=>nil}
my route.rb :
MyPedia2::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :topics, only: [:show, :create, :destroy]
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
root to: 'static_pages#home'
match '/topics/:id', to: 'topics#show'
my rake route shows :
topics POST /topics(.:format) topics#create
topic GET /topics/:id(.:format) topics#show
DELETE /topics/:id(.:format) topics#destroy
root / static_pages#home
/topics/:id(.:format) topics#show
and my topics controller is:
# encoding: utf-8
class TopicsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def show
#topic = Topic.find_by_id(params[:id])
end
def create
#topic = current_user.topics.build(params[:topic])
if #topic.save
flash[:success] = "Konu oluşturuldu!"
redirect_to root_path
else
render 'static_pages/home'
end
end
def destroy
#topic.destroy
redirect_to root_path
end
private
def correct_user
#topic = current_user.topics.find_by_id(params[:id])
redirect_to root_path if #topic.nil?
end
end
Is there a fix for this ?
EDIT : I found that _topics.html.erb fails
I found what breakes the code :
<% for topic in #topics do %>
<li><%=link_to topic.title, topic_path(#topic) %></li>
<%= will_paginate #topics %>
<% end %>
topic_path(#topic] part is wrong. How can i make it to use id?
It's not working because your collection is '#topics', and each element is 'topic', not '#topic'. But you're close. Try this:
<li><%=link_to topic.title, topic_path(topic) %></li>
Try this:
<li><%=link_to topic.title, topic_path(:id => #topic.id) %></li>
I think your routes should probably read:
resources :sessions, :only => [:new, :create, :destroy]
resources :topics, :only => [:show, :create, :destroy]
After hours of thinking , now i can see my mistake. I used show method in my topics controller but i did not have show.html.erb in my views/topics.
If you want to show your topics you must use these methods:
1) in config/routes.rb use :
match '/topics/:id', to: 'topics#show'
2) in the model i used
belongs_to :user,:foreign_key => "user_id"
3) link as :
<li><%=link_to topic.title, **topic_path(topic)** %></li>
4) and prepare the template you mentioned in the route.
I hope this help anyone.

Resources