Reputation: 81
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
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
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