robertlong
robertlong

Reputation: 81

Tag links not working with acts as taggable on and Rails 3.1

I'm currently using the following gems in my application to provide pagination, search, linkable tags, and a tag cloud.

gem 'will_paginate', '~> 3.0.2' gem 'acts-as-taggable-on', '~>2.1.0'

I have everything implemented so far in Rails 3.1 except the tag links. I have them displayed below every post and in the tag cloud and both link to different views and neither works.

A link in the tag cloud (Test1) links me to: /posts/tag?id=Test1 which gives me an error "Couldn't find Post with id=tag"

And a link in the post redirects me to /posts?tag=Test2&view=tag which doesn't change anything. All my posts are still displayed.

Here's what I've changed so far to try and implement this:

The edited part of my routes.rb:

resources :posts do
collection do
  get :tag
end

end

My post.rb:

acts_as_taggable_on :tags
def self.tag_post_list(page, tag)

  Post.tagged_with(tag).by_date.paginate(:page => params[page], :per_page => 20)

end

Post_Controller.rb:

def index
  @posts = Post.search(params[:search], params[:page])
  @tags = Post.tag_counts_on(:tags)
  if request.xhr?
    render :partial => @posts
  end
end
def tag
  @posts = Post.tagged_with(params[:id])
  @tags = Post.tag_counts_on(:tags)
  render :action => 'index'
end
def show
  @post = Post.find(params[:id])
  @tags = Post.tag_counts_on(:tags)

  respond_to do |format|
    format.html # show.html.erb
    format.json { render json: @post }
  end
end

Posts_helper.rb:

include ActsAsTaggableOn::TagsHelper

Tag cloud in application.html.erb

<% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
<%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
<% end %>

Tag cloud definition in application_controller.rb

def tag_cloud
  @tags = Post.tag_counts_on(:tags)
end

Links in my posts:

<% for tag in post.tags %>
<%= link_to tag.name, posts_path(:view =>'tag', :tag => tag.name) %>
<% end %>

The error in my console:

Started GET "/posts/tag?id=Test1" for 127.0.0.1 at 2011-11-05 00:35:00 -0700
Processing by PostsController#show as HTML
Parameters: {"id"=>"tag"}
Post Load (0.0ms)  SELECT "posts".* FROM "posts" WHERE "posts"."id" = $1 LIMIT 1  [["id", "tag"]]
Completed 404 Not Found in 3ms

ActiveRecord::RecordNotFound (Couldn't find Post with id=tag): app/controllers/posts_controller.rb:33:in `show'

I've searched the internet for the past 5 hours trying to figure this out, but nothing is up to date or entirely relevant.

I get that it is passing "tag" to the show action, but how do I get it to pass the relevant ID and anything else I need to show the correct posts with that tag?

Upvotes: 1

Views: 1338

Answers (2)

robertlong
robertlong

Reputation: 81

Stupid mistake:

I wasn't passing paginate to the @posts array in the tag definition.

@posts = Post.tagged_with(params[:id]).paginate(:page => params[:page], :per_page => 10)

Work's perfectly. Thanks for the help, you were part of the solution.

Upvotes: 1

Thilo
Thilo

Reputation: 17735

Looking at your rake routes output, here's your problem:

     post GET    /posts/:id(.:format)         {:action=>"show", :controller=>"posts"}
    ...
tag_posts GET    /posts/tag(.:format)         {:action=>"tag", :controller=>"posts"}

the URL /posts/tag?id=Test1 is matched by both these routes, so the first one is used, leading to the posts#show action being called instead of the posts#tag action as intended.

Now I'm not quite sure why that is - you seem to have too many routes defined for the posts controller. Do you have any other entries for posts somewhere in your routes file in addition to the one you have in your question?

With just this:

resources :posts do
  collection do
    get :tag
  end
end

your rake route output should look like this:

tag_posts GET    /posts/tag(.:format)       {:action=>"tag", :controller=>"posts"}
    posts GET    /posts(.:format)           {:action=>"index", :controller=>"posts"}
          POST   /posts(.:format)           {:action=>"create", :controller=>"posts"}
 new_post GET    /posts/new(.:format)       {:action=>"new", :controller=>"posts"}
edit_post GET    /posts/:id/edit(.:format)  {:action=>"edit", :controller=>"posts"}
     post GET    /posts/:id(.:format)       {:action=>"show", :controller=>"posts"}
          PUT    /posts/:id(.:format)       {:action=>"update", :controller=>"posts"}
          DELETE /posts/:id(.:format)       {:action=>"destroy", :controller=>"posts"}

Here the tag_post route is defined prior to the default post route, which would fix your issue.

EDIT:

Based on your comment, change the route you added slightly to this:

match "/posts/tag/:id" => "posts#tag", :as => :tag_posts

and then use the named route in your link:

link_to tag.name, tag_posts_path(tag.name)

Upvotes: 0

Related Questions