没有ID的Rails博客找不到分类

时间:2019-03-16 19:56:54

标签: ruby-on-rails

在尝试为Blog创建类别时遇到了一些问题。 ActiveRecord :: RecordNotFound in ArticlesController#index

这是routes.rb文件代码

Rails.application.routes.draw do
  resources :categories
#  get 'sessions/new'

  resources :sessions
  resources :users
  get 'welcome/index'

  resources :articles do
    resources :comments
    collection do
      get :search #creates a new path for searching
    end
  end
  resources :subscribers
  root 'welcome#index'
  get 'pages/about' => 'application#show'
end

这是Articles_controller.rb文件代码

class ArticlesController < ApplicationController

before_action :admin_authorize, :except => [:index, :show, :search]

  def index
    if params[:category].blank?
      @articles = Article.all.order("created_at DESC")
    else
      @category_id = Category.find_by(name: params[:category]).id
      @articles = Article.where(category_id: @category_id).order("created_at DESC")
    end
  end

  def new
    @article = Article.new
    @categories = Category.all.map{|c| [c.name, c.id]}
  end

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

  def create
    @article = Article.new(article_params)
    @article.category_id = params[:category_id]

    respond_to do |format|
      if @article.save
        format.html { redirect_to @article, notice: "Article was successfully created!" }
        format.json { render :show, status: :created, location: @article }
      else
        format.html { render :new}
        format.json {render json: @article.errors, status: :unprocessable_entity}
      end
    end
  end

  def edit
    @article = Article.find(params[:id])
    @categories = Category.all.map{|c| [ c.name, c.id ] }
  end

  def search
    if params[:search].blank?
      @articles = Article.all
    else
      @articles = Article.search(params)
    end
  end

  def update
    @article = Article.find(params[:id])
    @article.category_id = params[:category_id]
    if @article.update(article_params)
      redirect_to @article
    else
      render 'edit'
    end
  end

  def destroy
    @article = Article.find(params[:id])
    @article.destroy
    redirect_to articles_path
  end

private
  def article_params
    params.require(:article).permit(:title, :text, :search, :music, :movie, :photo)
  end

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

这是文章索引视图文件:(其中有错误)

<div class="row">
<div class="col"></div>
<div class="col-md-10">
<h1>List of all Articles</h1>
<% if current_user && current_user.admin? %>
<p>
  <%= link_to 'Create New Article', new_article_path, class:'btn btn-lg btn-info' %>
</p>
<% end %>
<table class="table table-hover table-striped table-responsive-xs">
<thead>
<tr>
  <th>Photo</th>
  <th>Date</th>
  <th>Title</th>
  <th>Text</th>
<% if current_user && current_user.admin? %>
  <th colspan="3">Editing Options</th>
<% else %>
  <th colspan="1">Show Articles</th>
<%end%>
</tr>
</thead>
<tbody>
<% @articles.each do |article| %>
<tr>
  <td>
    <% if article.photo.present? %>
    <%= image_tag article.photo.url(:thumb) %>
    <% else %>
    <%= image_tag('noimage.jpg', style:"width:50px;") %>
    <% end %>
  </td>
  <td>
    <%= article.created_at.strftime('%d/%m/%Y')%>
  </td>
  <td>
    <%= article.title %>
  </td>
  <td>
    <%= truncate(article.text, length: 75) %>
  </td>
  <td>
    <%= link_to Category.find(article.category_id).name, category_path(article.category_id) %>
  </td>
  <td>
    <%= link_to 'Show', article_path(article), class:'btn btn-sm btn-info' %>
  </td>
  <% if current_user && current_user.admin? %>
  <td>
    <%= link_to 'Edit', edit_article_path(article), class:'btn btn-sm btn-warning' %>
  </td>
  <td>
    <%= link_to 'Delete', article_path(article),
        class: 'btn btn-sm btn-danger',
        method: :Delete,
        data: {confirm: "Are you sure???"}%>
  </td>
  <% end %>
</tr>
<% end %>
</tbody>
</table>
<p>
  <%= link_to 'Home', welcome_index_path, class:'btn btn-md btn-warning' %>
</p>
</div>
<div class="col"></div>
</div>

在我的浏览器窗口中,我在这段“文章索引视图”视图代码中看到了该问题:

<% @articles.each do |article| %>
and 
<%= link_to Category.find(article.category_id).name, category_path(article.category_id) %>

1 个答案:

答案 0 :(得分:0)

您几乎拥有一本教科书N+1 query issue,此外,article.category是可选的,因此您可以拨打Category.find(nil).name

假设您已在“文章”和“类别”之间建立了一对多关联

class Category
  has_many :articles
end

class Article
  belongs_to :category
end

首先应确保将类别和文章一起加载:

class ArticlesController < ApplicationController
  def index
    @articles = Article.includes(:category).order(created_at: :desc)
  end
end

然后,当您遍历视图时,只需使用article.category

<% if article.category %>
  <%= link_to article.category.name, article.category %>
<% end %>

您不需要显式传递category_path(article.category_id)。只要通过记录,Rails就会足够聪明地自行解决。

我还将设置一个单独的控制器来处理嵌套在类别中的文章:

# config/routes.rb
resources :categories do
  resources :articles, only: [:index], module: :categories
end

# app/controllers/categories/articles_controller.rb
module Categories
  class ArticlesController
    before_action :set_category

    # GET /categories/:category_id/articles
    def index
      @articles = @category.articles.order(created_at: :desc)
    end

    def set_category
      @category = Category.includes(:articles).find(params[:category_id])
    end
  end
end

它的循环复杂度较低,并且遵守SRP。控制器呈现不同视图的事实也是一个优点,因为它使您可以为不同的上下文设置视图。如果需要,可以使用局部函数来共享代码。

您可以使用以下方法链接到它:

<%= link_to "Articles in #{category.name}", [category, :articles] %>