No route matches {:action=>“show”, :controller=>“u

2019-06-24 12:22发布

问题:

Hello everybody, I have this problem (title of the post).

Failure/Error: get :create, :user => { :email => 'foo@example.com', :name => 'userexample' }
ActionController::RoutingError:No route matches {:action=>"show", :controller=>"user", :id=>nil}

Here is my UserController.

class UserController < ApplicationController

  def new
  end

  def create
    @user = User.new(params[:user])
    @user.save
    redirect_to :action => :show, :id => @user.id
  end

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

Here is my routes.rb

::Application.routes.draw do

  devise_for :users
  root :to => "user#index"
  resources :user
  #match "newuser" => "user#new"
  get "user/new"
  post "user/create"
  get "user/:id" => "user#show"

And here is my rspec test

require 'spec/spec_helper'

describe UserController do
  it "create new user" do
    get :create, :user => { :email => 'foo@example.com', :name => 'userexample' }
      flash[:notice] = 'new user was successfully created.'
    end
  end
end

回答1:

if @user.save
   redirect_to :action => :show, :id => @user.id
else
 ...
end


回答2:

Most Rails apps use this type of content block for creating and updating records.

def create
  @user = User.new(params[:user])

  if @user.save
    redirect_to @user, :notice => "User was created successfully."
  else
    render :new
  end
end

Basically, when the create action is run it creates a new record, or a new instance of the User model.

When .save is called it checks all the validations. If the validations pass then it returns true, else it returns false.

If it returns false, then you need to render the :new template again so person has a chance to fix any validation errors.

If it returns true, then you want to redirect to the show action. The cool thing about rails is that it can automatically figure that out by just passing the instance @user.


Ryan Bates has a tutorial on testing controllers with RSpec. Based on what he does, this is how I would test your controller.

require 'spec/spec_helper'

describe UserController do

  describe "POST 'create'" do

    it "should redirect to user on successful save" do
      User.any_instance.stub(:valid?) { true }
      post :user
      flash[:notice].should_not be_nil
      assigns(:user).should_not be_a_new_record
      response.should redirect_to(assigns(:user))
    end

    it "should render new template on failed save" do
      User.any_instance.stub(:valid?) { false }
      post :user
      flash[:notice].should be_nil
      assigns(:user).should be_a_new_record
      response.should render_template(:new)
    end

    it "should pass params" do
      User.any_instance.stub(:valid?) { true }
      post :user, :user => { email_address: "baylor@example.com" }
      assigns(:user).email_address.should == "baylor@example.com"
    end
  end
end