CodeWalrus
CodeWalrus

Reputation: 6068

Rails: acts_as_taggable_on, getting errors when attempting to find articles by tag

I have been following along with a RailsCasts episode, and am trying to make articles taggable. Then I want to make tags clickable on articles show.html page, so that users can find other related articles. I am using Rails 4. However, I have been getting the following error:

ActiveRecord::RecordNotFound in ArticlesController#show

Couldn't find Article without an ID

Extracted source (around line #43):

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

I then tried to make the following changes, which I observed after looking at the RailsCast code:

articles_controller.rb

[...]
    def show  
        if params[:tag]
          @articles = Article.tagged_with(params[:tag])
        else
          @article = Article.find(params[:id])
        end
    end

Which gave me the error upon clicking a tag on a working show page:

http://localhost:x000/tags/pizza

NoMethodError in Articles#show
undefined method 'title' for nil:NilClass

<div id="article-title">
  <h1>
   <p>
    <%= @article.title %></span>
   </p>
  </h1>
</div>

Which seems odd to me, since the title method works just fine otherwise. Everything else works on the site, the tags save and can be edited in the articles edit page, but finding all articles with a specific tag isn't working.

=== Relevant code areas:

_form.html

<p>
    <%= f.label :keyword_Tags %><br/>
    <%= f.text_field :tag_list %> <span class="gray-text"><em>Separated by commas; single tag has no spaces, only-dashes </em></span>
  </p>

routes.rb

Network::Application.routes.draw do
  resources :libraries

  get "libraries/show"
  devise_for :authors, :controllers => {:registrations => "authors/registrations"}

  get 'tags/:tag', to: 'articles#show', as: :tag 

  devise_scope :author do
    get 'signup', to: 'devise/registrations#new' 
    get 'signin', to: 'devise/sessions#new' 
    # get 'logout', to: 'devise/sessions#destroy' 
  end

  resources :relationships, only: [:create, :destroy]

  get "landing_page/index"
  # The priority is based upon order of creation: first created -> highest priority.
  # See how all your routes lay out with "rake routes".
  resources :articles do
    resources :comments
  end
  # You can have the root of your site routed with "root"
  root 'landing_page#index'
  get '/:id', to: 'libraries#show'
end

article.rb

 class Article < ActiveRecord::Base
    has_many :comments, dependent: :destroy
    belongs_to :author 
    acts_as_taggable
    acts_as_taggable_on :tag_list

    validates :title, presence: true,
                    length: { minimum: 5 }
  validates :text, presence: true,
                                 length: { minimum: 2 }
    validates :article_start, presence: true,
                                        length: {minimum: 10}

end

[num]_create_articles.rb

class CreateArticles < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      t.string :title
      t.time :era
      t.string :chapter
      t.date :article_start
      t.text :text
      t.string :tag_list

      t.timestamps
    end
  end
end

controller

class ArticlesController < ApplicationController
before_filter :authenticate_author!, only: [:create, :new, :edit, :update, :destroy]
#added destroy to above, not in Treebook

def index
    @articles = Article.all 
end

def new # diff between new and create?
    @article = Article.new
end

def create 
    @article = Article.new(article_params)

    #respond_to do|format|

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

    end
end
#end #for respond_to; noticed in "What is a join table"

def show #show, being an action
    @article = Article.find(params[:id])

end


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

def update
    @article = Article.find(params[: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, :author_id, :article_start, :era, :chapter, :address, :tag_list)
    end

end

Request

Parameters:

{"tag"=>"open"}

Upvotes: 0

Views: 442

Answers (1)

Kirti Thorat
Kirti Thorat

Reputation: 53038

Update ArticlesController actions show and index as below:

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

   def index  
     if params[:tag]
       @articles = Article.tagged_with(params[:tag])
     else
       @articles = Article.all
     end
   end

Also, update the routes.rb :

Replace

 get 'tags/:tag', to: 'articles#show', as: :tag

With

 get 'tags/:tag', to: 'articles#index', as: :tag ## It should go to index action not show

Upvotes: 1

Related Questions