zzx
zzx

Reputation: 171

has one route error message "No route matches [POST] "/users/create""

The error occured after submitting "Create" account, no matter I entered password or not, the error message is below:

No route matches [POST] "/users/create"

I built the page of registration, this is my new.html.erb in users file

<div class="center hero-unit">
  <% @page_title = "Sign up" %>
    <h1>Sign Up</h1>
    <%= form_for(:user, :url => {:controller => 'users', :action => 'create'}) do |f| %>
      <p> First name:</br> <%= f.text_field :first %> </p>
      <p> Last name:</br> <%= f.text_field :last %> </p>
      <p> Email:</br> <%= f.text_field :email %> </p>
      <p> Password:</br> <%= f.password_field :password %></p>
      <p> Password Confirmation:</br> <%= f.password_field :password_confirmation %> </p>
      <%= f.submit :Create, class:"btn btn-large btn-primary" %>
      <%= link_to "Cancel", root_path, class:"btn btn-large btn-primary" %>
    <% 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>

The route.rb is:

Rails.application.routes.draw do
  get 'sessions/login'
  get 'sessions/main'
  get 'sessions/profile'
  get 'sessions/setting'
  get 'users/new'
  get 'home/index'
  root 'home#index'
  match '/about', to: 'home#about', via: 'get'
  match '/signup', to: 'users#new', via: 'get'
  match ':controller(/:action(/:id))(.:format)', via: 'get'
  match '/login', to: 'sessions#login', via: 'get'
  match '/logout', to: 'sessions#logout', via: 'get'
  match '/main', to: 'sessions#main', via: 'get'
  match '/profile', to: 'sessions#profile', via: 'get'
  match '/setting', to: 'sessions#setting', via: 'get'
end

And the users_controller.rb is:

class UsersController < ApplicationController

  before_filter :save_login_state, :only => [:new, :create]

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      flash[:notice] = 'You signed up succefully!'
      flash[:color] = 'valid'
    else
      flash[:notice] = 'Form is invalid.'
      flash[:color] = 'invalid'
      render 'new'
    end
  end
  private
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation)
  end

end

The user.rb in models is:

class User < ActiveRecord::Base
  #attr_accessible :email, :password, :password_confirmation

  attr_accessor :password
  EMAIL_REGEX = /\b[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}\z/
  validates :username, :presence => true, :uniqueness => true, :length => { :in => 3..20 }
  validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
  validates :password, :confirmation => true #password_confirmation attr
  validates_length_of :password, :in => 6..20, :on => :create

  before_save :encrypt_password
  after_save :clear_password

  #attr_accessible :email, :password, :password_confirmation

  def encrypt_password
    if password.present?
      self.salt = BCrypt::Engine.generate_salt
      self.encrypted_password= BCrypt::Engine.hash_secret(password, salt)
    end
  end
  def clear_password
    self.password = nil
  end


  def self.authenticate(email="", login_password="")
    if EMAIL_REGEX.match(email)
      user = User.find_by_email(email)
    end

    if user && user.match_password(login_password)
      return user
    else
      return false
    end
  end
  def match_password(login_password="")
    encrypted_password == BCrypt::Engine.hash_secret(login_password, salt)
  end

  #attr_accessible :email, :password, :password_confirmation
end

I also created a password_hashing.rb in models:

require 'digest/sha1'
encrypted_password= Digest::SHA1.hexdigest(password)

and a password_hasing_with_salt.rb

salt= Digest::SHA1.hexdigest("# We add {email} as unique value and #{Time.now} as random value")
encrypted_password= Digest::SHA1.hexdigest("Adding #{salt} to {password}")

In my migrate, the thing is:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first
      t.string :last
      t.string :email
      t.string :encrypted_password
      t.string :salt

      t.timestamps
    end
  end
end

Also, the error message includes:

Routes

Routes match in priority from top to bottom

Helper  HTTP Verb   Path    Controller#Action
Path / Url          
sessions_login_path      GET     /sessions/login(.:format)   sessions#login
sessions_main_path       GET     /sessions/main(.:format)    sessions#main
sessions_profile_path    GET     /sessions/profile(.:format)     sessions#profile
sessions_setting_path    GET     /sessions/setting(.:format)     sessions#setting
users_new_path           GET     /users/new(.:format)    users#new
home_index_path          GET     /home/index(.:format)   home#index
root_path                GET     /   home#index
courses_path             GET     /courses(.:format)  courses#index
                         POST    /courses(.:format)  courses#create
new_course_path          GET     /courses/new(.:format)  courses#new
edit_course_path         GET     /courses/:id/edit(.:format)     courses#edit
course_path              GET     /courses/:id(.:format)  courses#show
                         PATCH   /courses/:id(.:format)  courses#update
                         PUT     /courses/:id(.:format)  courses#update
                         DELETE  /courses/:id(.:format)  courses#destroy
about_path               GET     /about(.:format)    home#about
signup_path              GET     /signup(.:format)   users#new
                         GET     /:controller(/:action(/:id))(.:format)  :controller#:action
login_path               GET     /login(.:format)    sessions#login
logout_path              GET     /logout(.:format)   sessions#logout
main_path                GET     /main(.:format)     sessions#main
profile_path             GET     /profile(.:format)  sessions#profile
setting_path             GET     /setting(.:format)  sessions#setting

How can I solve this problem please? Thank you for your time!

Upvotes: 2

Views: 1596

Answers (1)

Benjamin Bouchet
Benjamin Bouchet

Reputation: 13181

form_for accept several types of argument to cover different scenario, but in your case you want to pass your @user model to it, so the form_for know how to set a correct path and how to give the correct values to your text_fields

Bottom line, instead of

form_for(:user, :url => {:controller => 'users', :action => 'create'}) do 
  ...

You must use

form_for(@user) do
  ...

Additionally, when @user is a new object (i.e created in your controller by User.new) form_for will automatically POST to your create action. And when @user is an existing record (i.e loaded from the database by User.find(params[:id]) form_for will PATCH to your update action. It's automatic


Second point, it seems you have an incorrect route configuration as seen by the output of your rake routes in your question. can you post your route.rb so we can advise?

So you need to remove get 'users/new' from your route, and add resources :users on top of your routes.rb file

And also this is not very clean: match ':controller(/:action(/:id))(.:format)', via: 'get' I don't know what is the reason why you had to add it but I advise you to find an alternative and remove it.

Upvotes: 1

Related Questions