新手问题 No route matches {:action=>"update_type", :controller=>"users"}

gechentuo · 2013年09月18日 · 最后由 angelfan 回复于 2015年03月09日 · 4281 次阅读

我想实现的功能是: 一个新用户提交注册表单之后,页面跳转到“类型选择”页。

问题出现在 select_type.html.erb 这个文件的表单中

<%= form_for( @user,url: {action: "update_type"} , html: {method: "patch"}) do |f| %>
       <%= radio_button_tag(:type, 'teacher')%>
   <%= label_tag(:type_teacher, '幼师')%>
   <%= radio_button_tag(:type, 'school') %>
   <%= label_tag(:type_school, '学校')%>
   <%= radio_button_tag(:type, 'parent') %>
   <%= label_tag(:type_parent, '家长')%>
   <%= f.submit "提交选择", class: "btn btn-large btn-primary"%>
  <% end %>

UsersController 中的代码如下:

class UsersController < ApplicationController
  def create
   @user = User.new(user_params)
    if @user.save
    flash[:success] = "Welcome to the Sample App!"
    render 'select_type'
    else
     render 'new'
    end
  end

  def new
   @user = User.new
  end

  def index
  end

  def show
  end

  def update 
  end

  def select_type
   @user= User.find(params[:id])
  end

  def update_type
   @user = User.find(params[:id])
   type = params[:type]

   if type == 'school'
      data = 1
   end

   if type == 'parent'
      data = 2
   end   

   if type == 'teacher' 
      data = 3
   end   

   if @user.update(user_type: data)
      flash[:success] = "您成功开通了服务!"
      redirect_to @user
   else
      render 'select_type'
   end
  end
  private
   def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
   end
end

routes.rb 文件的代码如下:

resources :users do
  member do
    get 'select_type'
    patch 'update_type'
  end
end

执行 rake routes 之后显示的路由为:

select_type_user GET    /users/:id/select_type(.:format) users#select_type
update_type_user PATCH  /users/:id/update_type(.:format) users#update_type
           users GET    /users(.:format)                 users#index
                 POST   /users(.:format)                 users#create
        new_user GET    /users/new(.:format)             users#new
       edit_user GET    /users/:id/edit(.:format)        users#edit
            user GET    /users/:id(.:format)             users#show
                 PATCH  /users/:id(.:format)             users#update
                 PUT    /users/:id(.:format)             users#update
                 DELETE /users/:id(.:format)             users#destroy

当我在地址栏中输入: localhost:3000/users/1/select_type,页面可以成功访问 select_type.html 页面

但当我,先注册用户,提交注册表单之后,就报错 No route matches {:action=>"update_type", :controller=>"users"}

我查过文档之后,发现,把 表单内容改为 <%= form_for( @user,url: update_type_user_path(@user) , html: {method: "patch"}) do |f| %> 就可以在提交注册表单之后,直接跳转到类型选择界面了

这两句到底有什么不同呢?

<%= form_for( @user,url: update_type_user_path(@user) , html: {method: "patch"}) do |f| %> <%= form_for( @user,url: {action: "update_type"} , html: {method: "patch"}) do |f| %>

UsersController 里面

def create
   @user = User.new(user_params)
    if @user.save
    flash[:success] = "Welcome to the Sample App!"
    render 'select_type'
    else
     render 'new'
    end
  end

为什么要 render?render 的话,select_type 和 update_type 都是取不到 params[:id] 的,因为取不到这个值,所以

<%= form_for( @user,url: {action: "update_type"} , html: {method: "patch"}) do |f| %>

这里的 action: "update_type",就会以为你要的 url 是 /users/update_type,很明显,你的 routes 里面没有符合的,于是就报错说

No route matches {:action=>"update_type", :controller=>"users"}

这时候,只需要把 render 'select_type' 改成

redirect_to select_type_user_path(@user)

就好了。 至于你问的下面

<%= form_for( @user,url: update_type_user_path(@user) , html: {method: "patch"}) do |f| %>
<%= form_for( @user,url: {action: "update_type"} , html: {method: "patch"}) do |f| %>

这俩的区别,相信看了我上面说的那么多,你应该已经知道了。

#1 楼 @messiahxu 谢谢!给了我这么漂亮的答案,辛苦了

#1 楼 @messiahxu 一年后看到这样的回复,我只想说这回复太漂亮了,不得不赞

需要 登录 后方可回复, 如果你还没有账号请 注册新账号