提交表单后,没有路由匹配[POST]“/ story / new”

时间:2012-06-10 15:20:54

标签: ruby ruby-on-rails-3 rails-routing

我刚刚开始“在Rails上构建你自己的Ruby”并且我不得不经常使用Google,因为这本书似乎有很多代码不起作用的地方。这一次,我找不到答案。好的,所以这是交易。我的表格看起来像这样:

new.html.erb

<%= form_for :story do |f| %>
<p>
    name:<br />
    <%= f.text_field :name %>
</p>

<p>
    link: <br />
    <%= f.text_field :link %>
</p>

<p>
    <%= submit_tag %>
</p>

<% end %>

当我去localhost:3000/story/new时显示正常。问题是,当我尝试在表单中键入内容并按“提交”时,我收到此错误:

Routing Error

No route matches [POST] "/story/new"

我的routes.rb看起来像这样:

FirstApp::Application.routes.draw do
    resources :story 

story_controller看起来像这样:

  def new
    @story = Story.new(params[:story])
    if request.post?
      @story.save
    end
  end

story_controller的{​​{1}}内容完全出自本书。我以为我可能有一个解决方案here,但没有骰子。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

我猜你的意思(请注意at符号):

<%= form_for @story do |f| %>

这可能会解决您的路由问题,但正如John所提到的,您的控制器操作也有点过时了。 new操作应仅加载虚拟模型并显示new.html.erb页面 - 保存应在单独的操作中进行,名为create

希望这有帮助!

编辑:最少的控制器代码:

class StoriesController < ApplicationController
    def new
        #Make a dummy story so any default fields are filled correctly...
        @story = Story.new
    end

    def create
        @story = Story.new(params[:story])
        if(@story.save)
            #Saved successfully; go to the index (or wherever)...
            redirect_to :action => :index
        else
            #Validation failed; show the "new" form again...
            render :action => :new
        end
    end
end

答案 1 :(得分:1)

首先,当使用单数和复数名称时,Rails依赖于约定优于配置。如果您想遵守惯例,则必须将routes.rb中的行更改为resources :stories,这会产生以下路线:

   stories GET    /stories(.:format)          stories#index
           POST   /stories(.:format)          stories#create
 new_story GET    /stories/new(.:format)      stories#new
edit_story GET    /stories/:id/edit(.:format) stories#edit
     story GET    /stories/:id(.:format)      stories#show
           PUT    /stories/:id(.:format)      stories#update
           DELETE /stories/:id(.:format)      stories#destroy

请注意,在这种情况下,您必须将控制器重命名为StoriesController。但是,您的routes.rbresources :story,会产生以下路线:

story_index GET    /story(.:format)          story#index
            POST   /story(.:format)          story#create
  new_story GET    /story/new(.:format)      story#new
 edit_story GET    /story/:id/edit(.:format) story#edit
      story GET    /story/:id(.:format)      story#show
            PUT    /story/:id(.:format)      story#update
            DELETE /story/:id(.:format)      story#destroy

正如您所看到的,确实没有POST /story/new的路线。我想,你得到的错误是由控制器中的以下代码触发的:

if request.post?
  @story.save
end

这是非常错误的,因为您尝试在POST路由到的操作中检查GET请求。只需从new操作中删除此代码,然后将create操作添加到StoryController,就像这样:

def create
  @story = params[:story]
  if @story.save
    redirect_to @story, notice: "Story created"
  else
    render action: "new"
  end
end

这应该暂时解决您的问题。但我强烈建议您使用复数stories作为资源,因为它会再次困扰您。

答案 2 :(得分:1)

这是你(和我)错过指南的部分:

  

但这种形式存在一个问题。如果您检查HTML   通过查看页面来源生成的,您将看到   表单的action属性指向/ articles / new。   这是一个问题,因为这条路线会转到你所在的页面   此时此刻,该路线应仅用于展示   新文章的形式。

     

表单需要使用其他网址才能转到其他地方。   这可以通过form_for的   通常在Rails中,用于新表单提交的操作   像这样称为&#34;创建&#34;,因此应该指出表单   那个动作。

     

编辑app / views / articles / new.html.erb中的form_for行,如下所示:


<%= form_for :story, url: stories_path do |f| %>