【问题标题】:Rails 4: ActiveRecord::RecordNotFound in PostsController#editRails 4: ActiveRecord::RecordNotFound in PostsController#edit
【发布时间】:2015-11-29 21:39:26
【问题描述】:

这是一个基本错误,很多人都问过类似的问题,例如:

但是,它们都没有真正帮助我解决我现在面临的问题。

在我的 Rails 4 应用程序中,我有四个模型:

class User < ActiveRecord::Base
  has_many :administrations
  has_many :calendars, through: :administrations
end

class Calendar < ActiveRecord::Base
  has_many :administrations
  has_many :users, through: :administrations
  has_many: :posts
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Post < ActiveRecord::Base
  belongs_to :calendar
end

这是我的路线:

Rails.application.routes.draw do

  root to: 'pages#home'

  devise_for :users, :path => 'account'

  resources :calendars do
    resources :posts, shallow: true
  end

end

问题是:当我在日历上时,例如http://localhost:3000/calendars/11,我显示了属于此日历的所有帖子,每个帖子旁边都有ShowEditDestroy 链接。

当我点击Edit 链接时,我被带到http://localhost:3000/posts/11/edit.5* 并收到以下错误:

ActiveRecord::RecordNotFound in PostsController#edit
Couldn't find Post with 'id'=11

# Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.

注意:我不知道为什么我总是收到这个奇怪的网址,最后是.5

这是我PostsController的内容:

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
    @calendar = Calendar.find(params[:calendar_id])
  end

  # POST /posts
  # POST /posts.json
  def create
    @calendar = Calendar.find(params[:calendar_id])
    @post = @calendar.posts.create(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    @calendar = Calendar.find(params[:calendar_id])
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @calendar = Calendar.find(params[:calendar_id])
    @post.destroy
    respond_to do |format|
      format.html { redirect_to calendar_path(@calendar), notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def post_params
      params.require(:post).permit(:date, :time, :subject, :format, :copy, :media)
    end
end

更新:根据@Nathan 的评论,这里是edit.html.erb 视图:

<h1>Editing Post</h1>

<%= render 'form' %>

<%= link_to 'Show', @post %> |
<%= link_to 'Back', posts_path %>

这是其中使用的_form.html.erb 部分:

<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <p>
      <%= f.label :date %><br>
      <%= f.date_select :date %>
    </p>
    <p>
      <%= f.label :time %><br>
      <%= f.time_select :time %>
    </p>
    <p>
      <%= f.label :subject %><br>
      <%= f.text_field :subject %>
    </p>
    <p>
      <%= f.label :format %><br>
      <%= f.text_field :format %>
    </p>
    <p>
      <%= f.label :copy %><br>
      <%= f.text_area :copy %>
    </p>
    <p>
      <%= f.label :media %><br>
      <%= f.text_field :media %>
    </p>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

更新 2:根据 @danielricecodes 的回答,这是在终端中运行 rake routes 的结果:

Prefix Verb   URI Pattern                                 Controller#Action
                   posts GET    /posts(.:format)                            posts#index
                         POST   /posts(.:format)                            posts#create
                new_post GET    /posts/new(.:format)                        posts#new
               edit_post GET    /posts/:id/edit(.:format)                   posts#edit
                    post GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
                    root GET    /                                           pages#home
        new_user_session GET    /account/sign_in(.:format)                  devise/sessions#new
            user_session POST   /account/sign_in(.:format)                  devise/sessions#create
    destroy_user_session DELETE /account/sign_out(.:format)                 devise/sessions#destroy
           user_password POST   /account/password(.:format)                 devise/passwords#create
       new_user_password GET    /account/password/new(.:format)             devise/passwords#new
      edit_user_password GET    /account/password/edit(.:format)            devise/passwords#edit
                         PATCH  /account/password(.:format)                 devise/passwords#update
                         PUT    /account/password(.:format)                 devise/passwords#update
cancel_user_registration GET    /account/cancel(.:format)                   devise/registrations#cancel
       user_registration POST   /account(.:format)                          devise/registrations#create
   new_user_registration GET    /account/sign_up(.:format)                  devise/registrations#new
  edit_user_registration GET    /account/edit(.:format)                     devise/registrations#edit
                         PATCH  /account(.:format)                          devise/registrations#update
                         PUT    /account(.:format)                          devise/registrations#update
                         DELETE /account(.:format)                          devise/registrations#destroy
       user_confirmation POST   /account/confirmation(.:format)             devise/confirmations#create
   new_user_confirmation GET    /account/confirmation/new(.:format)         devise/confirmations#new
                         GET    /account/confirmation(.:format)             devise/confirmations#show
             user_unlock POST   /account/unlock(.:format)                   devise/unlocks#create
         new_user_unlock GET    /account/unlock/new(.:format)               devise/unlocks#new
                         GET    /account/unlock(.:format)                   devise/unlocks#show
          calendar_posts GET    /calendars/:calendar_id/posts(.:format)     posts#index
                         POST   /calendars/:calendar_id/posts(.:format)     posts#create
       new_calendar_post GET    /calendars/:calendar_id/posts/new(.:format) posts#new
                         GET    /posts/:id/edit(.:format)                   posts#edit
                         GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
               calendars GET    /calendars(.:format)                        calendars#index
                         POST   /calendars(.:format)                        calendars#create
            new_calendar GET    /calendars/new(.:format)                    calendars#new
           edit_calendar GET    /calendars/:id/edit(.:format)               calendars#edit
                calendar GET    /calendars/:id(.:format)                    calendars#show
                         PATCH  /calendars/:id(.:format)                    calendars#update
                         PUT    /calendars/:id(.:format)                    calendars#update
                         DELETE /calendars/:id(.:format)                    calendars#destroy

更新 3:根据 @Nathan 的第二条评论,这是我的 show.html.erb 日历视图的内容:

<h2><%= @calendar.name %> Calendar</h2>

<h3>Posts</h3>
<% if @calendar.posts.any? %>
    <table>
        <tr>
            <th>Date</th>
            <th>Time</th>
            <th>Subject</th>
            <th>Format</th>
            <th>Copy</th>
            <th>Media</th>
        </tr>
  <% @calendar.posts.each do |post| %>
        <tr>
        <td><%= post.date %></td>
            <td><%= post.time %></td>
            <td><%= post.subject %></td>
            <td><%= post.format %></td>
            <td><%= post.copy %></td>
            <td><%= post.media %></td>
        <td><%= link_to 'View', post %></td>
        <td><%= link_to 'Update', edit_post_path(@calendar, post) %></td>
        <td><%= link_to 'Delete', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
        </tr>
    </table>
  <% end %>
<% else %>
<p>This calendar does not contain any post yet: just create one with the form below.</p>
<% end %>

<h3>Add a post to <%= @calendar.name %> Calendar:</h3>
<%= form_for([@calendar, @calendar.posts.build]) do |f| %>
  <p>
    <%= f.label :date %><br>
    <%= f.date_select :date %>
  </p>
  <p>
    <%= f.label :time %><br>
    <%= f.time_select :time %>
  </p>
  <p>
    <%= f.label :subject %><br>
    <%= f.text_field :subject %>
  </p>
  <p>
    <%= f.label :format %><br>
    <%= f.text_field :format %>
  </p>
  <p>
    <%= f.label :copy %><br>
    <%= f.text_area :copy %>
  </p>
  <p>
    <%= f.label :media %><br>
    <%= f.text_field :media %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>


<%= link_to 'Edit', edit_calendar_path %> |
<%= link_to 'Back', calendars_path %>

更新 4:以下是我从帖子资源中删除 shallow 选项时的路线:

Prefix Verb   URI Pattern                                 Controller#Action
                   posts GET    /posts(.:format)                            posts#index
                         POST   /posts(.:format)                            posts#create
                new_post GET    /posts/new(.:format)                        posts#new
               edit_post GET    /posts/:id/edit(.:format)                   posts#edit
                    post GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
                    root GET    /                                           pages#home
        new_user_session GET    /account/sign_in(.:format)                  devise/sessions#new
            user_session POST   /account/sign_in(.:format)                  devise/sessions#create
    destroy_user_session DELETE /account/sign_out(.:format)                 devise/sessions#destroy
           user_password POST   /account/password(.:format)                 devise/passwords#create
       new_user_password GET    /account/password/new(.:format)             devise/passwords#new
      edit_user_password GET    /account/password/edit(.:format)            devise/passwords#edit
                         PATCH  /account/password(.:format)                 devise/passwords#update
                         PUT    /account/password(.:format)                 devise/passwords#update
cancel_user_registration GET    /account/cancel(.:format)                   devise/registrations#cancel
       user_registration POST   /account(.:format)                          devise/registrations#create
   new_user_registration GET    /account/sign_up(.:format)                  devise/registrations#new
  edit_user_registration GET    /account/edit(.:format)                     devise/registrations#edit
                         PATCH  /account(.:format)                          devise/registrations#update
                         PUT    /account(.:format)                          devise/registrations#update
                         DELETE /account(.:format)                          devise/registrations#destroy
       user_confirmation POST   /account/confirmation(.:format)             devise/confirmations#create
   new_user_confirmation GET    /account/confirmation/new(.:format)         devise/confirmations#new
                         GET    /account/confirmation(.:format)             devise/confirmations#show
             user_unlock POST   /account/unlock(.:format)                   devise/unlocks#create
         new_user_unlock GET    /account/unlock/new(.:format)               devise/unlocks#new
                         GET    /account/unlock(.:format)                   devise/unlocks#show
          calendar_posts GET    /calendars/:calendar_id/posts(.:format)     posts#index
                         POST   /calendars/:calendar_id/posts(.:format)     posts#create
       new_calendar_post GET    /calendars/:calendar_id/posts/new(.:format) posts#new
                         GET    /posts/:id/edit(.:format)                   posts#edit
                         GET    /posts/:id(.:format)                        posts#show
                         PATCH  /posts/:id(.:format)                        posts#update
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
               calendars GET    /calendars(.:format)                        calendars#index
                         POST   /calendars(.:format)                        calendars#create
            new_calendar GET    /calendars/new(.:format)                    calendars#new
           edit_calendar GET    /calendars/:id/edit(.:format)               calendars#edit
                calendar GET    /calendars/:id(.:format)                    calendars#show
                         PATCH  /calendars/:id(.:format)                    calendars#update
                         PUT    /calendars/:id(.:format)                    calendars#update
                         DELETE /calendars/:id(.:format)                    calendars#destroy
MacBook-Pro-de-Thibaud:calendy TXC$ rake routes
                  Prefix Verb   URI Pattern                                      Controller#Action
                    root GET    /                                                pages#home
        new_user_session GET    /account/sign_in(.:format)                       devise/sessions#new
            user_session POST   /account/sign_in(.:format)                       devise/sessions#create
    destroy_user_session DELETE /account/sign_out(.:format)                      devise/sessions#destroy
           user_password POST   /account/password(.:format)                      devise/passwords#create
       new_user_password GET    /account/password/new(.:format)                  devise/passwords#new
      edit_user_password GET    /account/password/edit(.:format)                 devise/passwords#edit
                         PATCH  /account/password(.:format)                      devise/passwords#update
                         PUT    /account/password(.:format)                      devise/passwords#update
cancel_user_registration GET    /account/cancel(.:format)                        devise/registrations#cancel
       user_registration POST   /account(.:format)                               devise/registrations#create
   new_user_registration GET    /account/sign_up(.:format)                       devise/registrations#new
  edit_user_registration GET    /account/edit(.:format)                          devise/registrations#edit
                         PATCH  /account(.:format)                               devise/registrations#update
                         PUT    /account(.:format)                               devise/registrations#update
                         DELETE /account(.:format)                               devise/registrations#destroy
       user_confirmation POST   /account/confirmation(.:format)                  devise/confirmations#create
   new_user_confirmation GET    /account/confirmation/new(.:format)              devise/confirmations#new
                         GET    /account/confirmation(.:format)                  devise/confirmations#show
             user_unlock POST   /account/unlock(.:format)                        devise/unlocks#create
         new_user_unlock GET    /account/unlock/new(.:format)                    devise/unlocks#new
                         GET    /account/unlock(.:format)                        devise/unlocks#show
          calendar_posts GET    /calendars/:calendar_id/posts(.:format)          posts#index
                         POST   /calendars/:calendar_id/posts(.:format)          posts#create
       new_calendar_post GET    /calendars/:calendar_id/posts/new(.:format)      posts#new
      edit_calendar_post GET    /calendars/:calendar_id/posts/:id/edit(.:format) posts#edit
           calendar_post GET    /calendars/:calendar_id/posts/:id(.:format)      posts#show
                         PATCH  /calendars/:calendar_id/posts/:id(.:format)      posts#update
                         PUT    /calendars/:calendar_id/posts/:id(.:format)      posts#update
                         DELETE /calendars/:calendar_id/posts/:id(.:format)      posts#destroy
               calendars GET    /calendars(.:format)                             calendars#index
                         POST   /calendars(.:format)                             calendars#create
            new_calendar GET    /calendars/new(.:format)                         calendars#new
           edit_calendar GET    /calendars/:id/edit(.:format)                    calendars#edit
                calendar GET    /calendars/:id(.:format)                         calendars#show
                         PATCH  /calendars/:id(.:format)                         calendars#update
                         PUT    /calendars/:id(.:format)                         calendars#update
                         DELETE /calendars/:id(.:format)                         calendars#destroy

知道如何解决这个问题吗?

【问题讨论】:

  • 你的标记是什么样的?
  • 感谢您的评论。我已经用视图文件的内容更新了问题。
  • @ThibaudClement 我认为相关标记将出现在您的日历视图中(假设您在看到此错误之前点击了“编辑”链接)。
  • 当然。我再次更新了问题。
  • 尝试删除shallow: true,看看你的路线是什么样子的。

标签: ruby-on-rails ruby-on-rails-4 activerecord model-view-controller nested-resources


【解决方案1】:

为一个需要一个参数的命名路径 (edit_post) 传入两个参数。当控制器操作set_post 尝试确定在查找要设置为@post 的记录时使用哪个:id 时,这会导致问题。

这也是为什么您将 .5 神秘地附加到 URL 末尾的原因——我相信 5post:id(在这种情况下),11:id @calendar.

edit_post_path 只需要知道您要编辑的帖子的:id,因此您可以通过将&lt;%= link_to 'Update', edit_post_path(@calendar, post) %&gt; 更改为&lt;%= link_to 'Update', edit_post_path(post) %&gt; 来解决此问题(注意删除@calendar) em>。

如果您真的想将这篇文章编辑为嵌套在日历下的资源(在路径/calendars/&lt;calendar_id&gt;/posts/&lt;post_id&gt;/edit),请查看您的config/routes.rbshallow: true 选项(在 :calendars 下嵌套 :posts 时使用)是阻止创建嵌套 :edit 路径的原因。

您需要有可用的嵌套:edit 路径,然后您可以像现在一样传递两个参数(类似于edit_calendar_post_path(@calendar, post))。

【讨论】:

  • 非常感谢。你是对的:&lt;%= link_to 'Update', edit_post_path(post) %&gt; 就像一个魅力。也感谢其余的解释,这非常有用,非常感谢。
  • 这是否通过了日历ID?
  • @Nathan 如果他只是删除了@calendar 参数并保持相同的命名路径,那么它将不包括日历ID。如果他对嵌套资源进行了我提到的更新并将两个参数都传递给edit_calendar_post_path,那么它将包含日历ID。
  • 对,那么在他的编辑操作中他有什么令人困惑的地方:@calendar = Calendar.find(params[:calendar_id]) - 所以不确定他的意图是什么,但值得注意的是,除非他使用,否则他不会得到 calendar_id嵌套路由或显式将参数添加到路径。
  • @ThibaudClement:@Nathan 很好地说明了您在:edit 操作中尝试执行的操作显示。如果您确实希望/需要@calendar 可用,那么没有可用的:calendar_id 将是一个问题。
【解决方案2】:

该错误让我认为您在视图模板中构建的链接存在问题。我会提供更多帮助,但我看不到视图文件或 rake routes 的输出。如果没有这两件事,我很难告诉你为什么你的应用程序会生成一个有趣的 url——但这通常意味着视图模板没有调用正确的 url_helper。

【讨论】:

  • 感谢您的回答。我刚刚用我的视图内容和在终端中运行rake routes 的结果更新了问题。如果您还需要其他东西,请告诉我。
【解决方案3】:

edit_post_path 相关的问题。使用浅嵌套,编辑路径在父范围之外。 .5 是添加到 url 的 Post ID,但不是有效的 url 参数,因为日历中已经有一个 ID 参数。根据您的路线设置方式,您似乎需要将 id 设置为链接中的参数,如下所示:

link_to "edit post", edit_post_path(post)

【讨论】:

  • 感谢您的回答。当我按照您的建议进行操作时,出现以下错误:undefined method id' for nil:NilClass`。有什么想法吗?
  • 你没有@post 实例变量,它应该只是'post'。现在编辑答案。我相信 edit_post_path(post) 也适合你
  • 谢谢。不幸的是,我仍然收到相同的Couldn't find Post with 'id'=11 错误。也许我应该避开浅层路线。
  • 浅嵌套没什么问题。您的视图中一定有其他内容正在尝试使用日历 ID 查询帖子,但我没有看到...您从链接中删除了 @calender 对吗?
  • 是的,我确实从链接中删除了@calendar。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
相关资源
最近更新 更多