views:

89

answers:

2

I have built a blog application using Ruby on Rails. In the application I have posts and tags. Post has_many :tags and Tag belongs_to :post.

In the /views/posts/index.html view I want to display two things. First is a listing of all posts displayed 'created_at DESC' and then in the side bar I am wanting to reference my Tags table, group records, and display as a link that allows for viewing all posts with that tag.

UPDATE: The issue of duplicate posts being displayed and posts w/o tags not displaying have been fixed. Just trying to figure out now, how to handle the /posts?tag_name=foobar request such that only the posts with that tag are displayed.

UPDATED CODE: The posts are displaying properly, no duplication. The tag count is working correctly, and the tag groups are displaying as links and passing the tag_name into /posts?tag_name=new. I just can't get the link to trigger the display of only the posts that have those tags. FYI, the posts are identified in the tag table by post_id.

PostsController

 def index
    @tag_counts = Tag.count(:group => :tag_name, :order => 'updated_at DESC', :limit => 10)
    @posts = Post.all( :order => 'created_at DESC' ).paginate :page => params[:page], :per_page => 4,
              :conditions => (params[:tag_name] ?
                { :tags => {:tag_name => params[:tag_name]} } : {}
                  )

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @posts }
      format.json { render :json => @posts }
      format.atom
    end
  end

View

Recently Used Tags
        <table>
            <% @tag_counts.each do |tag_name, tag_count| %> 
                <tr>
                    <td><%= link_to(tag_name, posts_path(:tag_name => tag_name)) %></td>
                    <td>(<%=tag_count%>)</td>
                </tr>
            <% end %>
            </table>
            <br>
            <a href="/tags">click to view all tags >></a>
            </div>

This screen shot might help (please note it is really ugly as just working on function) as it shows that there is only 1 tag in new but when the URL is hit, still displaying all posts.

alt text

A: 

To get all posts:

@posts = Post.all.paginate :page => params[:page], :per_page => 5

To show the post's tags:

<% @posts.each do |post| %>
   <% post.tags.each do |tag| %>
      <%= tag.tag_name %>
   <% end %> 
<% end %>

I believe this is what you want.

Edit #1

To show the tags in the side bar:

<% Tags.count(:group=>"tag_name").each_pair do |key, value| %>
    <% link_name = Tags.find( key ).tag_name %>(<%= value %>)
    <%= your_link %>
<% end %>

This will show all the tags with the number of posts between ( ). But I don't know how to build your link... Maybe if you give some more info, i don't know... Do you have a search method?

Anyway... hope it helps you :]

Edit #2

Looking another question you've made and seeing some code, I believe this will solve your problem:

#view
<% Tags.count(:group=>"tag_name").each_pair do |key, value| %>
   <% tag_name = Tags.find( key ).tag_name %>
   <%= link_to(tag_name+"(#{value})", posts_path(:tag_name => tag_name)) %>
<% end %>

#controller
@posts = Post.all.paginate :page => params[:page], :per_page => 5,
   :conditions => (params[:tag_name] ?
      { :tags => {:tag_name => params[:tag_name]} } : {}
   )

Hope it works now.

j.
that addresses the post display but I am also trying to group, link to a search, and display the tag groups through the @post variable in the index method as well.
bgadoci
see my edited answer :]
j.
Ok so this is kind of working as the duplication is gone. Here is the hiccup, when entering URL /posts?tag_name=new, it is not displaying only the posts with that tag. Any ideas?
bgadoci
Also (don't know if this matters or if you already saw it) but my column name in the tags table is actually "tag_name" not just "name" as I set it up incorrectly. Thank you so much for the help.
bgadoci
try using `downcase`... `:conditions => (params[:tag_name] ? { :tags => {:tag_name => params[:tag_name].downcase} } : {}`
j.
Nope. I see where you were going though. I'm not using the #view portion of your code above because it gave me some problems. Just need to figure out how to add to the controller code then when /posts?tag_name=new is passed that it then displays posts.
bgadoci
could you please post how is your code now? tks.
j.
Just updated it and added a little description. Thanks again for so much time on this.
bgadoci
A: 

A join will create a separate entry for every row - and when you've joined posts on tgas, that means the rows have become a sort of Post+Tag meta-object. So you'll get a post-tag for every tag+post there is.

You probably just want to pull out all the posts and just :include => :tags That will mean all posts will appear (regardless of whether there's a tag on it).

Of course, mixing it with the tag-conditions makes it a bit more complicated. You are not likely to find posts with no tags if you're specifically looking for posts with tags with a given name...

If there's only likely to be one tag with the given tag-name, perhaps you'd do better to do something like:

@posts = Tag.find_by_tag_name(params[:tag_name]).posts
Taryn East
Is there no way that I can apply a :limit or :group to the existing code to fix it? As far as the code you suggested, there are multiple records in the Tag table hence the grouping. Every time some adds a Tag to a post, it creates a new record. Then the code is looking for tag_name, grouping and displaying as a link. clicking the link passes the tag_name to the controller which then references the tag table and pulls out the post for each tag. That is where the problem is, it is displaying the post in duplicate for every tag.
bgadoci