views:

68

answers:

2

I have gotten a great deal of help from KandadaBoggu on my last question and very very thankful for that. As we were getting buried in the comments I wanted to break this part out.

I am attempting to create a tag feature on the rails blog I am developing. The relationship is Post has_many :tags and Tag belongs_to :post. Adding and deleting tags to posts are working great.

In my /view/posts/index.html.erb I have a section called tags where I am successfully querying the Tags table, grouping them and displaying the count next to the tag_name (as a side note, I mistakenly called the column containing the tag name, 'tag_name' instead of just 'name' as I should have) . In addition the display of these groups are a link that is referencing the index method in the PostsController. That is where the problem is.

When you navigate to /posts you get an error because there is no parameter being passed (without clicking the tag group link). I have the .empty? in there so not sure what is going wrong here. Here is the error and code:

Error

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.empty?

/views/posts/index.html.erb

<% @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 %>

PostsController

  def index
    @tag_counts = Tag.count(:group => :tag_name, :order => 'updated_at DESC', :limit => 10)
    @posts=Post.all(:joins => :tags,:conditions=>(params[:tag_name].empty? ? {}: 
                     { :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
A: 

Here where you are calling empty?, if params[:tag_name] is nil, it will raise the error you are seeing.

@posts=Post.all(:joins => :tags,:conditions=>(params[:tag_name].empty? ? {}: 
                     { :tags => { :tag_name => params[:tag_name] }}
                     )
                  )

If you just care whether it is nil or not, you can take advantage of the fact that nil is falsey and do this

@posts=Post.all(:joins => :tags,:conditions=>(params[:tag_name] ? 
                     { :tags => { :tag_name => params[:tag_name] }} : {}

                     )
                  )

But that is pretty ugly. It might be better to do something like this to make it clearer what you are doing:

@posts = if params[:tag_name]
           Post.all
         else
           Tag.find_by_name(params[:tag_name], :include => :posts).posts
         end
BaroqueBobcat
Ok, tag group links work great, and no error to land on /posts but two things: first, it seems to be displaying each post entry three times in a a row, and second it is only displaying posts that actually have tags (three times). Any ideas (new to ruby if you can't tell). Thanks for the help.
bgadoci
also, I tried the last, cleaned up solutions, but didn't recognized 'pages'.
bgadoci
actually, just looked, the repeated display is directly correlated to the number of tags the post has. Three tags = displayed three times, etc.
bgadoci
just to clarify, it is only repeating in the index view, not when you pass the parameter by clicking the tag group.
bgadoci
Thats because of the `@tag_counts.each` You could check for the param there again and render differently, but it might be better just to make a new action to handle showing pages with a particular tag.
BaroqueBobcat
The @tag_counts.each is in the view and is for the listing of tag groups in the sidebar, how is that affecting the post display? Not following here. I might just make this a new question. Thanks for all the help.
bgadoci
I made this a new question.
bgadoci
A: 

When I gave you the solution, I had forgotten the fact that I had monkey patched my Nil class with a empty? method. That is the reason why it is not working for you.

Change the code as follows:

conditions, joins = {}, nil
unless(params[:tag_name] || "").empty?
  conditions = ["tags.tag_name = ? ", params[:tag_name]]
  joins = :tags
end
@posts=Post.all(:joins => joins, :conditions=> conditions)

Edit 1

The code above performs empty check instead of nil check. I always make it a practice to perform a empty check for query parameters. This covers the cases where the action is invoked from a search form. In such cases tag_name will not be nil but an empty string.

Edit 2

Fixed the multiple row issue.

Edit 3

I fixed the posts no show issue when tag names are present.

Edit 4

In order to get the count in DESC order remove the the order clause from your count call.

@tag_counts = Tag.count(:group => :tag_name, :limit => 10)

The count method returns a ordered hash sorted by count. You changed the default sort order by adding the order clause.

KandadaBoggu
Thanks again for all the help. The only code of the 4 blocks given above that I have working is the second set posted by BaroqueBobcat but it is displaying the post in the index view multiple times. In fact the number of times it is displayed is directly correlated to the number of tags the post has. Any ideas on how to fix that?
bgadoci
just to clarify, it is only repeating in the index view, not when you pass the parameter by clicking the tag group.
bgadoci
I have updated the answer. The fix will use joins only when tag_name is present.
KandadaBoggu
I can't get that code to work. I created a new question using the code from BaroqueBobcat to try an tackle this. The code you gave me above will ends up in to posts being displayed and when clicking the tag groups it only displays the first search, after that, doesn't work. Sorry man, again I really appreciate all your help.
bgadoci
I have fixed the issue. Copy the code in its entirety. I was using `if` instead of `unless` in the code sample. I have tested this and it works.
KandadaBoggu
Dude, you are awesome. Just sat down and put this in. All works perfectly. Thank you so much!!!!!!!!!!!!!!!!!!!!
bgadoci
Any idea what you would add to order by tags with the highest count?
bgadoci
Updated my answer. Take a look.
KandadaBoggu