提交表格后没有与[POST]"/story/new"匹配的路线



我刚刚开始"Build Your Own Ruby on Rails",我不得不经常使用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

new story_controller的东西直接来自书中。我想我可能在这里有一个解决方案,但没有骰子。任何帮助将不胜感激。

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

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

这可能会解决您的路由问题,但正如 John 提到的,您的控制器操作也有点偏差。 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

首先,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.rb具有 resources :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,因为它会再次困扰您。

这是

您(和我)从指南中遗漏的部分:

不过,这种形式有一个问题。如果您检查 HTML生成后,通过查看页面的源代码,您将看到表单的操作属性指向/articles/new。这是一个问题,因为此路由会转到您所在的页面此刻在右侧,该路线应仅用于显示新文章的表单。

表单需要使用不同的 URL 才能转到其他地方。这可以通过 form_for 的 :url 选项非常简单地完成。通常在 Rails 中,用于新表单提交的操作像这样被称为"创建",所以形式应该指向那个动作。

编辑 app/views/articles/new.html.erb 中的form_for行

,如下所示:

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

最新更新