开发者

link_to passing paramater and display problem - tag feature - Ruby on Rails

开发者 https://www.devze.com 2022-12-26 17:42 出处:网络
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 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] }}
                     )
                  )
0

精彩评论

暂无评论...
验证码 换一张
取 消