【问题标题】:Rails undefined method `each' for nil:NilClass...but it is definedRails未定义方法'each'为nil:NilClass ...但它已定义
【发布时间】:2015-06-14 05:07:37
【问题描述】:

我已经搜索了几个小时,尝试了所有可能的修复方法。我无法完成这项工作。错误是:

  *NoMethodError in Articles#index
  Showing /Users/myname/blog/app/views/articles/showall.html.erb where     line #21 raised:
undefined method `each' for nil:NilClass*

showall.html.erb 是一个视图。它是从“文章”控制器呈现的。 (都在下面发布)。有一条可以展示的路线,而且效果很好。目前路由配置为:

get 'article/showall'

但是,我也试过这样:

resources :articles do
  get 'showall'
resources :comments

两种方法都有效,但都没有解决问题。

控制器中有一个方法,它不是私有的:

def showall
   @articles = Article.all
end

视图中有问题的代码是:

 <% @articles.each do |article| %>
 <tr>
  <td><%= article.title.truncate(30) %></td>
  <td><%= article.author %></td>
  <td><%= article.manufacturer %></td>
  <td><%= article.model %></td>
  <td><%= article.displacement %></td>`

<% end %>

实际上,我从 index.html.erb 视图中剪切并粘贴了一段代码,它可以完美运行。我已经尝试了我能想到的每一个多元化的细微差别。任何帮助将不胜感激。

本控制器适用部位:

class ArticlesController < ApplicationController
 skip_before_action :authorize, only: [:index, :show, :showall]

 #Filter used to catch nonlogged in users 
 before_filter :require_user, :only => [:index]

#method that checks if logged in, sends them to showall if not.
def require_user
unless User.find_by(id: session[:user_id])
  render 'showall', :notice => "Please log in to read articles."
end
end

def index

@articles = current_user.articles

end

#should list articles, but throws undefined method 'each' error
def showall
@articles = Article.all
end

这是整个视图:

 <%= render "menu" %>

 <body>
 <font color="yellow"><%= flash[:notice] %></font>
 <br>
 <font color="grey">Motorcycle Articles</font>
 <%= link_to 'Post New Article', new_article_path %> 
 <br>

 <table>
 <tr>
 <th>Title</th>

 <th>Author</th>
 <th>Brand</th>
 <th>Model</th>
 <th>Displacment</th>
 <th>Last Edited On:</th>
 <th>Article</th>
 </tr>
 <% @articles.each do |article| %>
  <tr>
  <td><%= article.title.truncate(30) %></td>
  <td><%= article.author %></td>
  <td><%= article.manufacturer %></td>
  <td><%= article.model %></td>
  <td><%= article.displacement %></td>

  <% end %>
  </table>
  <br>
   All articles are property of their respective owners.

 </body>

【问题讨论】:

  • 您确定有一些文章保存在数据库中吗?
  • 是的,我可以用 index.html.erb 列出它们

标签: ruby-on-rails each


【解决方案1】:

路由正在触发索引动作,见:

NoMethodError in Articles#index

您收到错误是因为 current_user.articles 为零。

您需要确保Articles#showall 出现在日志中,这意味着showall 方法被调用。

创建路线:

get '/articles', to: 'Articles#showall'
resources :articles

不建议这样做。有几个部分需要改进。但它应该使错误消失。

【讨论】:

    【解决方案2】:

    您正在调用渲染“showall”,它会渲染视图。这与调用控制器操作的“redirect_to”不同。由于您将 @articles 的值设置为 nil 值(未设置 current_user),因此您会收到此错误。

    为了澄清,在渲染视图之前,您需要重定向到“showall”操作或重新定义@articles 以等于Article.all。我个人会重定向。

    【讨论】:

    • 如果我将 'render' 更改为 'redirect_to',它会返回 Routing Error, uninitialized constant ArticleController,并显示路由表。如果我将其更改为redirect_to article_showall_path,我会得到相同的结果。
    • 如果我将路由更改为resources :articles do resources :comments get 'showall' end,我会得到一个不同的错误:没有路由匹配 [GET] "/article/showall"。然而,路由表中错误的正下方是article_showall_path GET /articles/:article_id/showall(.:format) articles#showall
    • 在调用 :resources 之前使用复数 "articles" 即 GET "articles/showall" 指定路由,到:Articles#showall 应该更正路由问题。从那里您可以使用redirect_to 调用路径,或者只需调用控制器操作(即redirect_to 操作:“showall”)就可以了。顺便说一句,如果您的索引中的视图完全相同,您可以完全跳过新操作并简单地重定向到那里,为任何警报/通知添加一个容器。
    • 我确实决定放弃这种方法,只是在索引视图中添加一些逻辑,以确定个人根据他们的凭据看到的内容。我显然需要回去研究前置过滤器的工作原理。感谢您的意见。
    • 从这里看起来您正确使用了 before_filter,只是路由和重定向的一些次要语义。但是,如果您可以通过一些小逻辑将操作浓缩到索引中,我认为从长远来看这将更易于维护,并且无论如何都是一个更 DRY 的解决方案。干杯!
    【解决方案3】:

    修改您的routes 文件

    routes.rb

    resources :articles do
      collection do
        get 'showall'
      end
    end
    

    【讨论】:

    • 这会导致路由错误No route matches [GET] "/article/showall"。令人困惑,因为 rake 路由显示 article_showall_path GET /articles/:article_id/showall(.:format) articles#showall
    猜你喜欢
    • 1970-01-01
    • 2014-11-23
    • 2013-07-16
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 2012-09-25
    • 1970-01-01
    相关资源
    最近更新 更多