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
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.
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
The parameter you're trying to access is nil, not just empty. One way to fix this is call nil? instead of empty? in your code. This worked for me:
@posts=Post.all(:joins => :tags,:conditions=>(params[:tag_name].nil? ? {}:
{ :tags => { :tag_name => params[:tag_name] }}
)
)
精彩评论