【问题标题】:undefined method `articles' for nil:NilClass when i tried to display related articles on my article show page当我试图在我的文章显示页面上显示相关文章时,nil:NilClass 的未定义方法“文章”
【发布时间】:2017-10-03 20:04:50
【问题描述】:

你好朋友,我昨天在我的 Rails 应用程序上遇到了这个错误。当我尝试在我的文章显示页面上显示相关文章时,我得到 nil:NilClass 的未定义方法 `articles'

这是我的应用代码

tag.rb

class Tag < ApplicationRecord
  has_many :taggings
  has_many :articles, through: :taggings

  def to_s
    name
  end

end

tagging.rb

class Tagging < ApplicationRecord
  belongs_to :tag
  belongs_to :article
end

articles_controller

class ArticlesController < ApplicationController
 before_action :find_article, only: [:show, :edit, :update, :destroy]
 before_action :owned_article, only: [:edit, :update, :destroy]
 before_action :authenticate_user!, except: [:index, :show]

def index
 @articles = Article.all.order("created_at desc")
end

def show
end

def new
  @article = current_user.articles.build
end

def create
  @article = current_user.articles.build(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end

def edit
end

def update
  if @article.update(article_params)
    redirect_to @article, notice: "Your article was successfully updated!"
  else
    render 'edit'
  end
end

def destroy
  @article.destroy
  redirect_to articles_path
end

private

def find_article
  @article = Article.find(params[:id])
end

def article_params
  params.require(:article).permit(:title, :content, :image, :tag_list)
end

def owned_article
  unless current_user == @article.user
    flash[:alert] = "That article does not belong to you!"
    redirect_to root_path
  end
end

结束

文章 show.html.erb

<div class="container">
<div class="row text-white text-center">
    <div class="col-md-10 col-lg-10 ml-sm-auto mr-sm-auto article-show-col">
        <br>
        <h1><%= @article.title %></h1>
        <p class="text-muted">Posted on: <%=       @article.created_at.strftime('%-b %-d, %Y') %></p>

        <p>
          Tags:
          <% @article.tags.each do |tag| %>
            <%= link_to tag.name, tag_path(tag) %>
          <% end %>
        </p>


        <!-- <br> -->
        <div class="article-show-image">
            <%= image_tag @article.image.url(:wide) %>
        </div>
        <!-- <br> -->
        <p><%= @article.content.html_safe %></p>

        <hr class="index-hr">

        <h5>Broadcast this article</h5>

        <%= social_share_button_tag("Hey! Checkout this new article from TWM!") %>

        <hr class="index-hr">

        **<h5>Related Articles</h5>
        <% @tag.articles.each do |article| %>
            <li><%= link_to article.title, article_path(article) %></li>
        <% end %>**

        <div class="btn-group">
            <%= link_to "Back", articles_path, class: "btn-custom btn-sm" %>
            <% if user_signed_in? %>
                <% if @article.user_id == current_user.id %>
                    <%= link_to "Delete", article_path(@article), method: :delete, data: { confirm: "Are you sure you want to delete this article?" }, class: "btn-custom btn-sm" %>
                    <%= link_to "Edit", edit_article_path, class: "btn-custom btn-sm" %>
                <% end %>
            <% end %>
        </div>
    </div>
</div>

标签控制器

class TagsController < ApplicationController
before_action :find_article, only: [:show, :edit, :update, :destroy]

def index
    @tags = Tag.all.order("created_at desc")
end

def show
end

def destroy
    @tag.destroy
    redirect_to tags_path
end

private

def find_article
    @tag = Tag.find(params[:id])
end
end

显示标签视图

<div class="container text-white text-center">

<h1>Articles Tagged with <%= @tag.name %></h1>

<ul>
  <% @tag.articles.each do |article| %>
    <li><%= link_to article.title, article_path(article) %></li>
  <% end %>
</ul>

谢谢!

【问题讨论】:

  • 发布您的routes.rb 文件并确保包含定义show 方法的行。 id 可能不是您需要从 params 中提取的属性的名称。
  • 在您的文章 show.html.erb 中,您使用的是 @tag.articles 并且 @tag 不存在。

标签: ruby-on-rails ruby tags ruby-on-rails-5


【解决方案1】:

这里有一个更长的答案,可以为您的问题提供解决方案。问题是您想要获取与您正在显示的article 共享tag 的所有articles,而可能不会在相关文章列表中显示当前文章。我将通过将related_articles 方法添加到您的Article 模型并在您的视图中调用它来完成此操作。

将以下方法添加到app/models/article.rb

def related_articles
    Article.joins(:tags).where(tags: { id: self.tags.pluck(:id) }).where.not(id: self.id)
end

上面的查询应该返回所有具有匹配标签的文章,同时排除自身。

您现在可以将视图中的相关文章部分替换为:

**<h5>Related Articles</h5>
<% @article.related_articles.each do |article| %>
    <li><%= link_to article.title, article_path(article) %></li>
<% end %>**

最后一点与您的问题不严格相关,但值得一提。通过迭代@article.tags,您的视图正在创建一个 N+1 查询。这些都是非常低效的。好消息是,这可以通过 eager loading 来解决,只需更改 articles_controller 中的 find_articles 方法,如下所示:

def find_article
  @article = Article.includes(:tags).find(params[:id])
end

可能有一种更有效的方式来编写related_articles 查询,但这应该可行。

编辑:

下面是编写related_articles 查询的另一种方式。这将产生相同的结果。它将更多的处理转移到数据库中,从而减少了对数据库的调用。

def related_articles
    Article.distinct.joins(tags: :articles).where.not(id: self.id)
end

【讨论】:

  • 在我定义了你所说的related_articles 方法之后,我能够实现我想要的......你救了我的压力人,我很感激。但是,当我更改我的 find_article 方法时,我收到此错误“未定义的方法 `includes' for #<0x50478f0>
【解决方案2】:

您的 ArticlesController 在显示视图中使用时未实例化 @tag 变量。

【讨论】:

    【解决方案3】:

    在您的show.html.erb 中,您正在尝试执行以下操作:

    <div class="container">
      <div class="row text-white text-center">
        <div class="col-md-10 col-lg-10 ml-sm-auto mr-sm-auto article-show-col">
    
          ...
    
          <% @tag.articles.each do |article| %>
              <li><%= link_to article.title, article_path(article) %></li>
          <% end %>**
    
          ...
    
        </div>
      </div>
    </div>
    

    但是,嘿,看看吧!在您的 show 操作中没有 @tag

    class ArticlesController < ApplicationController
      before_action :find_article, only: [:show, :edit, :update, :destroy]
      before_action :owned_article, only: [:edit, :update, :destroy]
      before_action :authenticate_user!, except: [:index, :show]
    
      ...
    
      def show
        #look! no @tag
      end
    
      ...
    
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-13
      • 2020-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-07
      相关资源
      最近更新 更多