The action 'create' could not be found for Admin::UsersController - ruby-on-rails

I am stuck with this issue, and i am not able to identify the problem. I am trying to add a user from admin section. Hence I have created a custom user controller, which calls the devise model. And I am trying to insert and update values using custom forms.
Controller
class Admin::UsersController < ApplicationController
load_and_authorize_resource
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_user!
layout 'admin-layout'
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit({ roles: [] }, :email, :password, :password_confirmation) }
end
def index
#user = User.all
end
def new
#user = User.new
end
def create
#user = User.new
if #user.save
redirect_to :action => "index"
else
render :action => "new"
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes
redirect_to :action => "index"
else
render :Action => "update"
end
end
def destroy
User.find(params[:id]).destroy
redirect_to ::Action => "index"
end
end
View File
<div class="container">
<div class="col-md-6 col-md-offset-2">
<h2>Create New User</h2>
<%= form_for #user, url: {action: "create"} do |f| %>
<%= f.text_field :email, :class=>"form-control", :placeholder => "Enter Email", :required => "true" %>
<%= f.text_field :password, :class=>"form-control", :placeholder => "Enter Password", :required => "true" %>
<%= f.text_field :password_confirmation, :class=>"form-control", :placeholder => "Enter Password Again", :required => "true" %>
<p>Roles:</p>
<% for r in Role.all %>
<%= check_box_tag "user[role_ids][]", r.id %>
<%= r.name %>
<% end %><br/>
<%= f.submit "Create", :class=>"btn btn-primary" %>
<% end %>
</div>
<div>
Routes
admin_users GET /admin/users(.:format) admin/users#index
POST /admin/users(.:format) admin/users#create
Can any1 please point me out where am I making a mistake.

You defined new, create etc. methods as protected, they need to be public if you want them to be recognized as actions.
BTW, in Ruby, if you have collection Role.all, it's much more readable to iterate over this with each instead of for (which is rarely used here):
<% Role.all.each do |r| %>

Related

Adding roles to users in rails app?

So summary: I wanted to have two types of users which are teachers and students. They are all users and therefore inherit from the users controller. The problem is no about the controllers or classes existing, it's how to adapt them through a form and whether or not I'm missing anything. I'm not sure how to do a backend to radio buttons and have tried things from previous answers but they result in errors. Also, how do I change routes based on which role they select? I have a registrations controller to override Devise.
Here is my form:
<div class="authform"> <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
<h2>Sign Up</h2>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<div>
<%= f.radio_button :role, 'student' %>
<%= label :role_student, 'Student' %>
<%= f.radio_button :role, 'teacher' %>
<%= label :role_teacher, 'Teacher' %>
</div>
<%= f.submit 'Sign Up', :class => 'button right' %>
<% end %> </div>
I have a migration to add roles to users right here
class AddRoleToUsers < ActiveRecord::Migration
def change
add_column :users, :role, :integer
end
end
This was my original attempt on changing routes when adding roles (from another stack overflow question)
class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
if params[:user][:role] == 'student'
path_to_route = '/classrooms/index'
elsif [:user][:role] == 'teacher'
path_to_route = '/classrooms/new'
else
path_to_route = '/'
end
redirect_to path_to_route
end
end
Finally, here is my user's controller
class UsersController < ApplicationController
# before_action :authenticate_user!
before_action :logged_in_user, only: [:edit, :update]
before_action :correct_user, only: [:edit, :update]
after_action :verify_authorized
# before_filter :check_role
def show
#user = User.find(params[:id])
authorize #user
#posts = #user.posts
end
def new
#user = User.new
authorize #user
end
#def after_sign_up_path_for(resource)
# if params[:user][:role] == 'student'
# path_to_route = '/classrooms/index'
# elsif [:user][:role] == 'teacher'
# path_to_route = '/classrooms/new'
# else
# path_to_route = '/'
# end
# redirect_to path_to_route
#end
def update
#user = User.find(params[:id])
authorize #user
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
user = User.find(params[:id])
# authorize #user
user.destroy
redirect_to users_path, :notice => "User deleted."
end
def create_user_type
end
private
def secure_params
params.require(:user).permit(:role)
end
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless #user == current_user
end
end
I know this is a bit of a long post, but I'd appreciate any help. Thanks so much! I love the rails community.
If you use simple_form you can use a standard input and assign the options to collection.
with simple_form
<%= f.input :role, collection: [:admin, :subscriber, :poster] %>
without simple_form
<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}) %>
user.rb
enum role: [:admin, :subscriber, :poster]

Issues with redirecting after signup with Devise. What to do?

I added roles to my users and after sign up devise automatically send me back to the homepage. I tried many things from this site and past questions but nothing seems to work. Maybe I'm over thinking it, I'm new here. Essentially I want people who sign up to choose their role, if they're a teacher they go to create a new class ('classrooms#new') and students go to chose their class ('classrooms#index'). I've created a separate registrations controller as suggested and that hasn't worked.
Sign up form (new.html.erb)
<div class="authform">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
<h2>Sign Up</h2>
<%= devise_error_messages! %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<div>
<%= f.radio_button :role, 'student' %>
<%= label :role_student, 'Student' %>
<%= f.radio_button :role, 'teacher' %>
<%= label :role_teacher, 'teacher' %>
</div>
<%= f.submit 'Sign Up', :class => 'button right' %>
<% end %>
</div>
Here is my registrations controller:
class Devise::RegistrationsController < DeviseController
def after_sign_up_path_for(resource)
if params[:user][:role] == 'student'
redirect_to 'classroom#index'
elsif [:user][:role] == 'teacher'
redirect_to 'classroom#new'
end
end
end
Here is my users controller
class UsersController < ApplicationController
before_action :authenticate_user!
after_action :verify_authorized
before_filter :check_role
def show
#user = User.find(params[:id])
authorize #user
#posts = #user.posts
end
def new
#user = User.new
authorize #user
end
def check_role
if params[:user][:role] == 'student'
redirect_to 'classroom#index'
elsif [:user][:role] == 'teacher'
redirect_to 'classroom#new'
end
end
def update
#user = User.find(params[:id])
authorize #user
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
def destroy
user = User.find(params[:id])
# authorize #user
user.destroy
redirect_to users_path, :notice => "User deleted."
end
def create_user_type
end
private
def secure_params
params.require(:user).permit(:role)
end
end
Edit: Here is my routes page
Rails.application.routes.draw do
get 'students/new'
get 'classrooms/new'
get 'teachers/new'
devise_for :users
resources :users
get "edit_profile" => "devise/registrations#edit"
resources :posts
resources :teachers
post 'users/create_user_type' => 'users/create_user_type'
root to: 'visitors#index'
end
I know there is repetitive code with checking roles, I've just been merging answers together (which isn't good I know)
use pry gem with binding.pry to check your code & variable content.
Anyway, I suppose that role is an attribute of user so why aren't you checking
user.teacher?
user.student?
instead of
params['']['']
resource attribute is persistent instead of params content
I think your registrations controller isn't correct.
If you create your own registrations controller, you want it to override the registrations controller from devise:
class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
if params[:user][:role] == 'student'
redirect_to 'classroom#index'
elsif [:user][:role] == 'teacher'
redirect_to 'classroom#new'
end
end
end
Then in your routes you must make sure that it also uses your own registrations controller:
devise_for :users, controllers: {registrations: 'registrations'}
Hope this will help you.

Upon submitting sign up form, ActiveModel::ForbiddenAttributesError

I've created a sign up form on rails, and upon clicking my submit button to save my user details, I get the following error:
ActiveModel::ForbiddenAttributesError
for this line: #user = User.new(params[:user])in my users controller.
See code below:
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
end
render "new"
end
end
new.html.erb
<%= form_for(:user, :url => {:controller => 'users', :action => 'create'}) do |f| %>
</br> <%= f.text_field :firstname, placeholder: 'First Name' %>
</br> <%= f.text_field :lastname, placeholder: 'Last Name' %>
</br> <%= f.text_field :email, placeholder: 'Email' %>
</br> <%= f.password_field :password, placeholder: 'Password' %>
</br> <%= f.password_field :password_confirmation, placeholder: 'Confirm Password' %>
<%= f.submit :Register %>
<% end %>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
routes.rb
Rails.application.routes.draw do
get 'users/new'
get 'pages/home'
get 'pages/howitworks'
get 'pages/about'
get 'pages/contact'
get 'pages/becomeauser'
get 'signup' => 'users#new'
resources :users
The params[:user] hash might have attributes in it that isn't a part of the User model. In your case, i'm guessing its password_confirmation.
Use strong params the next time - here
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "You signed up successfully"
flash[:color]= "valid"
else
flash[:notice] = "Form is invalid"
flash[:color]= "invalid"
end
render "new"
end
end
private:
def user_params
params.require(:user).permit(:first_name, :last_name, :email, : password)
end
This means that you have Strong Parameters enabled. I would encourage you to read at least a part of this Rails Guide. Essentially, instead of using params[] to update or create records, you should use an intermediate method to ensure that users aren't sneaking information into your requests. This is much safer. For instance, someone could submit a "created_at" attribute with your form, and then be modifying fields which are not supposed to be edited. Your approach should instead be as follows:
Create a private user_params method in the controller which permits specified attributes
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
Replace your User.create(), User.new(), and User.update() references to params[:user] with user_params
# Do this instead of #user = User.new(params[:user])
#user = User.new(user_params)

rails blog add comment redirecting to active admin login page

I am creating a blogging application which uses active_admin for admin panel.
When I try to comment on a post it is redirecting me to active_admin login page.
Comment Model:-
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post, :counter_cache => true
attr_accessible :text, :user_id, :post_id
validate :text, :presence => true
end
Active Admin Comment Model:-
ActiveAdmin.register Comment, :as => "PostComment" do
end
Posts Controller:-
def show
#post = Post.find(params[:id])
#showPost = true
respond_with do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
Comments Controller:-
class CommentsController < ApplicationController
before_filter :auth_user
def create
#post = Post.find(params[:post_id])
params[:comment][:user_id] = current_user.id
#comment = #post.comments.create(params[:comment])
redirect_to post_path(#post)
end
end
Comment Form:-
<%= semantic_form_for ([#post, #post.comments.build]), :html => { :id => "comment-form", :class => "metta-form"} do |f| %>
<h5 class="pull-left">Comments</h5>
<div class="clearfix">
</div>
<div class="wrap-comment-form">
<%= f.inputs do %>
<%= f.input :text, :label => false, :input_html => { :class => "comment-text pull-left" } %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :label => "Add Comment", :button_html => { :placeholder => "Enter Your Comment Here", :class => "btn btn-primary btn-metta pull-right" } %>
<% end %>
</div>
<% end %>
When I click on the add comment button it takes me to active admin login page. Can someone help me out here ??
class ApplicationController < ActionController::Base
protect_from_forgery
helper ApplicationHelper
def after_sign_in_path_for(resource)
'/users/home'
end
def after_sign_up_path_for(resource)
'/users/home'
end
def auth_user
redirect_to new_user_path unless user_signed_in?
end
end
Look here: before_filter :auth_user
So the reason you have been redirected to login page is you have not logged in yet.

Can I use my new user form to log in too

This has been asked before to some degree but I couldn't find an actual answer: How can I allow my users to log in via the same form they signup? This is a client request/demand by the way, I realise this is far from ideal...
User
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
render :json => #user.to_json(:only => [:id])
else
render :json => #user.errors, :status => ""
end
end
end
Session
class SessionsController < ApplicationController
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:email])
sign_in user
render :json => #user.to_json(:only => [:id])
else
render :json => #user.errors, :status => ""
end
end
end
Form
<%= form_for(#user, :html => { :class => "access"}) do |f| %>
<%= f.label :firstname, "Firstname" %>
<%= f.text_field :firstname, :placeholder => "Your firstname" %>
<%= f.label :surname, "Surname" %>
<%= f.text_field :surname, :placeholder => "Your surname" %>
<%= f.label :email, "Email Address" %>
<%= f.text_field :email, :placeholder => "Your email address" %>
<%= f.submit "Verify" %>
<% end %>
Emails are validated as unique, could that be an entry point? Eg. If the email is not unique check the name and email or something.
I have no idea how to go about this.
My suggestion is to make another controller which is something like AccessController. It should use a name that means both login and register, Access was just all I could think of. That controller should be able to do a check on the login credentials and either login or register.

Resources