Search code examples
ruby-on-rails-3link-to

link_to post ID in Rails


In my feed I have this:

<span class="title"><strong><%= link_to feed_item.title, @micropost %></strong></span><br>

I cannot figure out how to make it link to the individual pages for posts.

Right now it links to: http://localhost:3000/microposts and I get an error: No route matches [GET] "/microposts"

if I manually type the URL: http://localhost:3000/microposts/25 I can see the indivual page for the post.

This works fin linking to a user profile, but I can't get the link working to a micropost's page. <%= link_to feed_item.user.name, feed_item.user %>

I'm new to rails and I'm trying to figure this out. Any help would be appreciated.

microposts_controller.rb

class MicropostsController < ApplicationController
  before_filter :signed_in_user, only: [:create, :destroy]
  before_filter :correct_user,   only: :destroy

  def index
  end

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

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

  def destroy
    @micropost.destroy
    redirect_to root_url
  end

  private

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

config/routes.rb

SampleApp::Application.routes.draw do
  resources :users do
    member do
      get :following, :followers
    end
  end
  resources :sessions, only: [:new, :create, :destroy]
  resources :microposts, only: [:create, :destroy, :show]
  resources :relationships, only: [:create, :destroy]

  root to: 'static_pages#home'

  match '/signup',  to: 'users#new'
  match '/signin',  to: 'sessions#new'
  match '/signout', to: 'sessions#destroy', via: :delete

  match '/help',    to: 'static_pages#help'
  match '/about',   to: 'static_pages#about'
  match '/contact', to: 'static_pages#contact'
end

_feed_item.html.erb

<li id="<%= feed_item.id %>">
  <%= link_to gravatar_for(feed_item.user), feed_item.user %>
  <span class="title"><strong><%= link_to feed_item.title, micropost_path(@micropost) %></strong></span><br>
    <span class="user">
      <p><small>Created by: <%= link_to feed_item.user.name, feed_item.user %><br>
        <%= feed_item.loc1T %><br>
         <%= feed_item.startTime.strftime('%A, %B %d, %Y') %></small></p>
    </span>
    <span class="content"><%= feed_item.content %></span>
    <span class="timestamp">
      Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
    </span>
  <% if current_user?(feed_item.user) %>
    <%= link_to "delete", feed_item, method: :delete,
                                     data: { confirm: "Are you sure?" },
                                     title: feed_item.content %>
  <% end %>
</li>

feed.html.erb

<% if @feed_items.any? %>
  <ol class="microposts">
    <%= render partial: 'shared/feed_item', collection: @feed_items %>
  </ol>
  <%= will_paginate @feed_items %>
<% end %>`

static_pages_controller

class StaticPagesController < ApplicationController
  def home
    if signed_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

Solution

  • Long answer

    Rails generates a number of handy named routes for you when you add routes to your routes.rb file. Usually when in doubt for routes I take a look at my rake routes task which shows you a list of all available routes. Try running rake routes > routes.txt and open up the corresponding routes.txt file.

    The resulting file will list out a series of requests for you, in your case you should see something similar to this for your microposts controller:

              POST      /microposts(.:format)                microposts#create
    micropost GET       /microposts/:id(.:format)            microposts#show
              DELETE    /microposts/:id(.:format)            microposts#destroy
    

    Rake routes produces the following information for each of your routes (where applicable):

    1. The route name (if any)
    2. The HTTP verb used (if the route doesn’t respond to all verbs)
    3. The URL pattern to match
    4. The routing parameters for the route

    With that information in mind be can simply look at the urls provided in the routes.txt file for the url we're trying to get to (/microposts/25). You'll see that the listed /microposts/:id(.:format) url pattern handles that perfectly. Lo and behold it also maps to the microposts#show action that you want so now to get the named route just look at the first column to appear and you'll see the "microposts" keyword. Simply add _path` to this and you'll have your named route usable in views to generate link urls. Since this particular route requires an id parameter (as detailed in the url pattern) you have to pass the named route helper and id argument as well.

    Also in your routes.rb file when you add resources :something it generates routes for each of the default seven RESTful routes (new, create, edit, update, delete, index, show). In your case you're explicitly telling rails to generate default routes for the actions create, destroy and show so you can erase the line at the bottom match "/microposts/:id" => "microposts#show" because that's already being handled.


    Short answer

    Change this:

    <%= link_to feed_item.title, @micropost %>
    

    To this:

    <%= link_to feed_item.title, micropost_path(feed_item) %>
    

    See Ruby on Rails Guides: Rails routing from the Outside In for all you need to know about routes.