【问题标题】:Undefined method 'id' for nil:NilClass Ruby on Rails essential trainingnil 的未定义方法“id”:NilClass Ruby on Rails 基本培训
【发布时间】:2015-11-05 23:13:03
【问题描述】:

我得到的错误是这个,它在 Pages#delete 中显示 NoMethodError

nil:NilClass 的未定义方法 `id' 提取的源代码(在第 6 行附近): 4 5 6 7 8 9

<h2>Delete Page</h2>

<%= form_for(:page, :url =>{:action => 'destroy', :id => @page.id}) do |f| %>

   <p>Are you sure you want to permanently delete this page ?</p>

我从页面中删除.html.erb

<%= link_to("<< Back to List", {:action => 'index'}, :class =>'back-link') %>

<div class="pages delete">
    <h2>Delete Page</h2>

    <%= form_for(:page, :url =>{:action => 'destroy', :id => @page.id}) do |f| %>

       <p>Are you sure you want to permanently delete this page ?</p>

       <p class="reference-name"><%= @page.name %></p>

       <div class="form-buttons">
          <%= submit_tag("Delete Page") %>
       </div>

    <% end %>
</div>

我的页面控制器

  class PagesController < ApplicationController

   layout false

  def index
    @pages = Page.sorted
  end

  def show
    @page = Page.find(params[:id])
  end

  def new
    @page = Page.new({:name => "Default"})
  end

  def create
    @page = Page.new(page_params)
    if @page.save
      flash[:notice] = "Page created successfully."
      redirect_to(:action => 'index')
    else
      render('new')
    end
  end

  def edit
    @page = Page.find(params[:id])
  end

  def update
    @page = Page.find(params[:id])
    if @page.update_attributes(page_params)
      flash[:notice] = "Page updated successfully."
      redirect_to(:action => 'show', :id => @page.id)
    else
      render('edit')
    end

  def delete
    @page = Page.find(params[:id])
  end

  def destroy
    page = Page.find(params[:id]).destroy
    flash[:notice] = "Page destroyed successfully."
    redirect_to(:action => 'index')
  end

  private 

     def page_params
      params.require(:page).permit(:subject_id, :name, :permalink, :position, :visible)
     end
  end


end

任何帮助将不胜感激,谢谢

【问题讨论】:

  • 您似乎正在访问一个不存在的页面对象的删除页面。您确定 /pages/delete/:id 中的 id 有效吗?
  • 你能告诉我们你的 routes.rb 吗?
  • 这是我的 route.rb Rails.application.routes.draw do root 'demo#index' #get 'demo/index' match ':controller(/:action(/:id))' , :via => [:get, :post] 结束

标签: ruby-on-rails ruby


【解决方案1】:

Vitaly Stanchits 是对的。当您的控制器操作时:

def delete
  @page = Page.find(params[:id])
end

执行 - 它显然将 @page 设置为 nil,这意味着它找不到具有给定 ID 的页面。

您可以为我们运行rake routes,以确认/pages/delete/:id 确实是您删除视图的预期路径,并根据结果验证您访问的路径是否正确,例如。 /pages/delete/25

如果您确定删除操作中的 @page = Page.find(25) 应该返回有效的数据库记录,请尝试在删除操作中删除 debugger 语句以确保您点击控制器的正确部分,并检查params[:id] 的值。

【讨论】:

  • 我运行 rake routes 这就是我得到的 Prefix Verb URI Pattern Controller#Action root GET / demo#index GET|POST /:controller(/:action(/:id))(.:format ) :controller#:action
  • 通用路由应该捕获/pages/delete/25 url...并传递25作为参数[:id]。当您收到错误时,您可以验证您正在访问的实际网址吗?
【解决方案2】:

问题可能出在您的路由(而不是您的控制器)。

这样做:

#config/routes.rb
resources :pages do
   get :delete #-> url.com/pages/:id/delete
end

这将允许您为您的@page 调用delete 路径:

#app/controllers/pages_controller.rb
class PagesController < ApplicationController
   def delete
      @page = Page.find params[:id]
   end
end

#app/views/pages/delete.html.erb
<%= form_for @page, method: :destroy do |f| %>
   <p>Are you sure you want to permanently delete this page ?</p>
   <%= f.submit %>
<% end %>

必须注意,这超出了“资源丰富”控制器操作的范围,如下所述:http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

每当您在 Rails 中创建 路由 时,它都基于“资源充足”原则(我稍后会解释):

只要您在config/routes.rb 文件中调用resources :x,就会创建上述内容。这为您提供了一组路线,您可以使用这些路线对您的对象执行大部分操作:

<%= link_to "Delete Page", @page, method: :destroy, data: { confirm: "Are you sure?" } %>

以上指向destroy 操作(这是您的表单所指向的),允许您安全地删除有问题的对象。

--

这很重要的原因是我看到很多人——学习 Rails——用超出范围的操作来填充他们的控制器。例如:

#app/controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
   def home
   end

   def contact
   end
end

没有任何问题,只是它违反了保持应用程序object orientated 的约定。在 OOP(Ruby 建立在其之上)中,object 优先。

上面的控制器把flow放在前面;对 Rails 不利。 应该的方式是通过show动作调用@static_page

因此,对于您的情况,您必须记住,如果您想调用 delete 操作,您需要确保它在您的应用程序范围内...

可以执行以下操作:

#app/controllers/pages_controller.rb
class PagesController < ApplicationController
   def index
       @pages = Page.all
   end
end

#app/views/pages/index.html.erb
<% @pages.each do |page| %>
    <%= link_to "Delete Page", page, method: :destroy, data: { confirm: "Are you sure?" } %>
<% end %>

【讨论】:

    猜你喜欢
    • 2017-08-04
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-16
    • 1970-01-01
    相关资源
    最近更新 更多