1

I have created a ToDoList based off Hartl's tutorial, and following a video and worded tutorial to add a tagging system. I have followed till Section 10, where they asked me to modify my new.html.erb file to the code as shown on the source. To improvise for structural differences in code, I would edit some other files, like in this case, my micropost_form partial instead. Occasionally, I alternated between the code in the video and code in the worded tutorial because some of them would produce error messages or would not produce the required functionality. Here are the files that I think are involved in this question.

_micropost_form.html.erb(The filling up form that would be displayed on the user's home page)

<%= simple_form_for @micropost do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.label :content %><br />
    <%= f.text_area :content, placeholder: "Add new task..." %>
  </div>
  <div class="field">
    <%= f.label :tag_list, "Tags (separated by commas)" %><br />
    <%= f.text_field :tag_list %> 
  </div>
  <%= f.submit "Add Task", class: "btn btn-primary" %>
<% end %>

micropost.html.erb(for showing the individual micro posts)

<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, user_path(micropost.user) %></span>
  <span class="content"><%= micropost.content %></span>
  <p><small>Tags: <%= raw micropost.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %></small</p>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <% if current_user?(micropost.user) %>
      <%= link_to "Done", micropost_path(micropost), method: :delete, data: { confirm: "Keep up the good work!" } %>
    <% end %>
  </span>
</li>

routes.rb

Rails.application.routes.draw do
  resources :users
  resources :microposts          

  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  post    '/signup',  to: 'users#create'
  get    '/login',    to: 'sessions#new'
  post   '/login',    to: 'sessions#create'
  delete '/logout',   to: 'sessions#destroy'
  get   '/users/admin',     to: 'users#admin'

  get 'tags/:tag', to: 'microposts#index', as: :tag

  root   'static_pages#home'
end

micropost_controller

class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy


  def index
    params[:tag] ? @microposts = Micropost.tagged_with(params[:tag]) : @microposts = Micropost.all
  end


  def show
    @micropost = Micropost.find(params[:id])
  end

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end

  def destroy
    @micropost.destroy
    flash[:success] = "You have deleted a task!"
    redirect_to request.referrer || root_url
  end

  private

    def micropost_params
      params.require(:micropost).permit(:content, :tag_list, :tag, 
        {tag_ids: [] }, :tag_ids)
    end

    def correct_user
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to root_url if @micropost.nil?
    end
end

Micropost model

class Micropost < ApplicationRecord
  belongs_to :user
  has_many :taggings
  has_many :tags, through: :taggings
  default_scope -> { order(created_at: :desc) }
  validates :user_id, presence: true
  validates :content, presence: true, length: {maximum: 140 }
  attr_accessor :tag_list



  def self.tagged_with(name)
    Tag.find_by!(name: name).microposts
  end

  def self.tag_counts
    Tag.select('tags.*, count(taggings.tag_id) as count')
    .joins(:taggings).group('taggings.tag_id')
  end

  def tag_list
    tags.map(&:name).join(', ')
  end

  def tag_list=(names)
    self.tags = names.split(',').map do |n|
      Tag.where(name: n.strip).first_or_create!
    end
  end
end

Tag model

class Tag < ApplicationRecord
    attr_accessor :name
  has_many :taggings
  has_many :microposts, through: :taggings
end

static_pages controller

class StaticPagesController < ApplicationController
  def home
    if logged_in?
      @micropost  = current_user.microposts.build
      @feed_items = current_user.feed.paginate(page: params[:page])
    end
  end

  def help
  end

  def about
  end

  def contact
  end
end

feed.html.erb

<% if @feed_items.any? %>
  <ol class="microposts">
    <%= render @feed_items %>
  </ol>
  <%= will_paginate @feed_items %>
<% end %>

I got the following error

ActionController::UrlGenerationError in StaticPages#home
No route matches {:action=>"index", :controller=>"microposts", :tag=>nil}, missing required keys: [:tag]

Error highlighted

app/views/microposts/_micropost.html.erb:5:in `block in _app_views_microposts__micropost_html_erb___3891111682689684005_70324923859580'
app/views/microposts/_micropost.html.erb:5:in `map'
app/views/microposts/_micropost.html.erb:5:in `_app_views_microposts__micropost_html_erb___3891111682689684005_70324923859580'
app/views/shared/_feed.html.erb:3:in `_app_views_shared__feed_html_erb__3168328449514417483_70324923896060'
app/views/static_pages/home.html.erb:13:in `_app_views_static_pages_home_html_erb__3511776991923566869_70324898321240'

Can anyone suggest what might be wrong here? Please let me know if more information is needed.

Update: I have implemented some of the changes provided by the answer below, but still has not understood why :tag is not detected, and why the code in red is actually highlighted.

Prashin Jeevaganth
  • 1,223
  • 1
  • 18
  • 42
  • When do you get error? on form submit or inside controller while redirect ? Use `pry` gem to debug & also notice your action is trying to go Micropost#index with missing `tag_id`. Routes are improper I guess – ray Jan 21 '19 at 05:18
  • I get error when I run `rails server` and just get to `0.0.0.0:3000`. And I dont see how `tag_id` is being used when I try to access `index`, sorry new to rails – Prashin Jeevaganth Jan 21 '19 at 05:25
  • :) Error is in your `routes.rb`. Ensure with complete log from where error generated – ray Jan 21 '19 at 05:26
  • What do you mean by complete log? I'm aware that it comes from `routes.rb` but don't know why it is not fed with `:tag` – Prashin Jeevaganth Jan 21 '19 at 05:29

2 Answers2

1
ActionController::UrlGenerationError in StaticPages#home
No route matches {:action=>"index", :controller=>"microposts", :tag=>nil}, missing required keys: [:tag]

The problem is you don't have an index route for your microposts.

Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/readme',    to: 'static_pages#readme'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  post    '/signup',  to: 'users#create'
  get    '/login',    to: 'sessions#new'
  post   '/login',    to: 'sessions#create'
  delete '/logout',   to: 'sessions#destroy'
  get   '/users/admin',     to: 'users#admin'
  resources :users
  resources :microposts,          only: [:create, :destroy] #Here's the problem
  get 'tags/:tag', to: 'microposts#index', as: :tag
end

change to:

resources :microposts, only: [:index, :create, :destroy]

EDIT:

Another problem is

if logged_in?
  @micropost  = current_user.microposts.build #this just returns a new 1
  @feed_items = current_user.feed.paginate(page: params[:page])
end

You probably want something like:

if logged_in?
  @microposts  = current_user.microposts
  @feed_items = Micropost.all.paginate(page: params[:page])
end

This will give you all the user's microposts. Then you iterate through them in your views.

Noel
  • 966
  • 1
  • 9
  • 19
  • Hi Helsing, appreciate your answer, but changing that didn't change my error message, but thanks for reminding me to give a code update – Prashin Jeevaganth Jan 21 '19 at 15:48
  • I see. It seems like there's an issue with the tags. I'll take a look later today if still not resolved. – Noel Jan 21 '19 at 15:55
  • Thanks a lot for the help in advance. – Prashin Jeevaganth Jan 21 '19 at 15:58
  • @micropost = current_user.microposts.build gives you a new micropost without any tags so that could be why you're seeing that. There may be multiple issues, so as soon as you clear one up you run into a different error. – Noel Jan 21 '19 at 22:13
  • Thanks for your suggestions, I do run into another error of `undefined method to_key for # – Prashin Jeevaganth Jan 22 '19 at 01:02
  • Alright, yea that is now beyond the scope of this question. Glad I was able to help you. If my solution solved your issue make sure to select it as best answer so that people know the issue here was already solved. – Noel Jan 22 '19 at 05:33
1

I actually found the cause of the problem to be quite simple. After running rails console, it seems like my db:seed wasn't even raked properly, causing my tags to have nil names and causing me to be unable to find the route. Looking further into Rails console is adding nil instead of values to solve my seed adding problem, I realised I have added attr_accessor, forgetting that normal attributes should be added via the command line into the Migration instead of writing into the Model directly. Removing it according to the post updates my database and the code works.

Prashin Jeevaganth
  • 1,223
  • 1
  • 18
  • 42