2

I have User model and Role model.

class User < ActiveRecord::Base # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable has_one :role def has_role?(role_name) self.role == Role.where(name: role_name).first end def add_role(role_name) role = Role.where(name: role_name).first self.role = role unless role.blank? end end class Role < ActiveRecord::Base belongs_to :user end 

For now, my app have 2 user roles; Admin & Member.

What I'm trying to do now is, giving ability to the Admin to change the member's role (from Admin to Member OR from Member to Admin) using select tag.

I have this inside my views/users/_form.html.erb

<div class="col-md-4"> <%= form_for(@user) do |f| %> <% if @user.errors.any? %> <div id="error_explanation"> <p><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</p> <ul> <% @user.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="form-group"> <%= f.label :email %><br> <%= f.text_field :email, class: "form-control" %> <%= f.label :role %> <%= f.select :role_id, options_for_select(Role.all.map{|c| [c.name, c.id]}, f.object.role_id)%> </div> <%= f.submit 'Save user', :class => 'btn btn-primary' %> <%= link_to 'Back', users_path, class: "btn btn-primary" %> <% end %> </div> 

This is my User controller:

class UsersController < ApplicationController before_action :authenticate_user! before_action :set_user, only: [:show, :edit, :update, :destroy] # GET /users # GET /users.json def index @users = User.all end # GET /users/1 # GET /users/1.json def show end # GET /users/1/edit def edit end # PATCH/PUT /users/1 # PATCH/PUT /users/1.json def update respond_to do |format| if @user.update(user_params) format.html { redirect_to users_path, notice: 'user was successfully updated.' } format.json { render :show, status: :ok, location: @user } else format.html { render :edit } format.json { render json: @user.errors, status: :unprocessable_entity } end end end # DELETE /users/1 # DELETE /users/1.json def destroy @user.destroy respond_to do |format| format.html { redirect_to users_url, notice: 'user was successfully destroyed.' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_user @user = User.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def user_params params.require(:user).permit(:email, :encrypted_password) end end 

And this is my routes.rb:

Rails.application.routes.draw do devise_for :users root "orders#index" resources :orders resources :drinks resources :foods # link to change foods/drinks status from 0 (processing) to 1 (done) get '/orders/:id/update_foods_status', to: 'orders#update_foods_status', as: :update_foods_status get '/orders/:id/update_drinks_status', to: 'orders#update_drinks_status', as: :update_drinks_status # kitchen foods orders get 'kitchen_foods', to: 'kitchen_foods#index' # kitchen drinks orders get 'kitchen_drinks', to: 'kitchen_drinks#index' # list of all users get 'users', to: 'users#index', as: :all_users # single user get 'users/:id', to: 'users#show', as: :single_user # edit user get 'users/:id/edit', to: 'users#edit', as: :edit_user end 

UPDATE: This is what I get after run rake routes

Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy root GET / orders#index orders GET /orders(.:format) orders#index POST /orders(.:format) orders#create new_order GET /orders/new(.:format) orders#new edit_order GET /orders/:id/edit(.:format) orders#edit order GET /orders/:id(.:format) orders#show PATCH /orders/:id(.:format) orders#update PUT /orders/:id(.:format) orders#update DELETE /orders/:id(.:format) orders#destroy drinks GET /drinks(.:format) drinks#index POST /drinks(.:format) drinks#create new_drink GET /drinks/new(.:format) drinks#new edit_drink GET /drinks/:id/edit(.:format) drinks#edit drink GET /drinks/:id(.:format) drinks#show PATCH /drinks/:id(.:format) drinks#update PUT /drinks/:id(.:format) drinks#update DELETE /drinks/:id(.:format) drinks#destroy foods GET /foods(.:format) foods#index POST /foods(.:format) foods#create new_food GET /foods/new(.:format) foods#new edit_food GET /foods/:id/edit(.:format) foods#edit food GET /foods/:id(.:format) foods#show PATCH /foods/:id(.:format) foods#update PUT /foods/:id(.:format) foods#update DELETE /foods/:id(.:format) foods#destroy update_foods_status GET /orders/:id/update_foods_status(.:format) orders#update_foods_status update_drinks_status GET /orders/:id/update_drinks_status(.:format) orders#update_drinks_status kitchen_foods GET /kitchen_foods(.:format) kitchen_foods#index kitchen_drinks GET /kitchen_drinks(.:format) kitchen_drinks#index all_users GET /users(.:format) users#index single_user GET /users/:id(.:format) users#show edit_user GET /users/:id/edit(.:format) users#edit 

My problem:

When I navigate to /users/1/edit, I get this error:

NoMethodError in Users#edit undefined method `user_path' for #<#<Class:0x007fb702901c88>:0x007fb70098aaf8> 

How do I fix this problem?

I found this answer but I couldn't understand it very clearly. Would appreciate a better explaination and answer.

Note: I'm using Devise gem.

3
  • Based on your routes.rb file, you should be using all_users_path. Run rake routes in your console and post its results. Commented Aug 5, 2015 at 19:15
  • Just updated my questions with rake routes result. Commented Aug 5, 2015 at 19:20
  • There isn't a users_path specific. Furthermore, there is not a post, put, or patch route either, so the form is looking for a non-existent path. Commented Aug 5, 2015 at 19:25

2 Answers 2

4

You have in your routes file:

devise_for :users 

which adds:

 new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PATCH /users(.:format) devise/registrations#update PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy 

Now what you want to do is allow admin to edit the users. For this you have defined:

 # list of all users get 'users', to: 'users#index', as: :all_users # single user get 'users/:id', to: 'users#show', as: :single_user # edit user get 'users/:id/edit', to: 'users#edit', as: :edit_user 

which generates:

 all_users GET /users(.:format) users#index single_user GET /users/:id(.:format) users#show edit_user GET /users/:id/edit(.:format) users#edit 

Now in the form you are writing <%= form_for(@user) do |f| %> which by default is searching for user_path. So instead of the different routes you are defining just add:

resources :users 

which will generate all the necessary routes you require and map the form to the correct path. This will save a lot of overhead like using only this <%= form_for(@user) do |f| %> will take you to the create action when the user is a new object and it will take you to the update action if the user is a persisted object.

Or if you need to user your routes then you need to do:

<%= form_for(@user, url: edit_user_path, method: :get) do |f| %> 

But it always a bad idea to use GET method in form submission. These links might help you:

When should I use GET or POST method? What's the difference between them?

When do you use POST and when do you use GET?

Update:

As you need to assign a single role to the user from multiple it is better to use a select box like this:

f.collection_select(:role_id, Role.all, :id, :name) 

Assuming that the user table has attribute role_id and the role table has attribute name. So this will allow you to assign a role to user. What you are printing is user.role which will always print the association instead of the role name.

Hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

Worth mentioning that using a GET request for your edit form is a bad idea.
Yup that is, but it all depends on the user who needs to use it. The best option is using the resources, it saves a lot of overhead (convention over configuration).
@Deep thanks. Now I use resources. But why I couldn't print the user role? Screenshot: i.imgur.com/h6K77j1.png Form code: gist.github.com/anonymous/4261cc34b2844fb05da0
0

Try using edit_user_path instead of user_path if you want to link to the edit page. If you take a look at your routes.rb file there is no route for user_path.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.