Search code examples
ruby-on-railsrubyrails-activerecordforum

ruby on rails: ordering index of topics based on polymorphic associated comments not showing the right data when rendered


I'm building a basic forum application in Ruby on Rails (v4.1.7) and I'm having an issue with displaying the topics in descending order based on their last post. The code I'm using below will show the topics in the correct descending order, however the last post times and last poster name are wrong.

When I view the topic with comments#index, these data are correct. Both comments#index and topics#index call the same partial to display the topic:

I believe this may have to do with me calling topic.comments.last Testing it out, it seems to be displaying the FIRST comments userdata and created_at, rather than the last, however the forums ARE showing up in the correct order.

Partial: _topic.html.erb:

<article class="topic">
  <h2><%= link_to(topic.title, topic_comments_path(topic)) %></h2>
  <div class="author">
    By <strong><%= topic.user.name %> </strong>
       on <%= topic.created_at.strftime('%b %d %Y') %>
  </div>
  <div class="stats">
    Viewed <%= pluralize(topic.view_count, 'time') %>.
    <% if topic.comments.any? %>
      Last comment <%= time_ago_in_words(topic.comments.last.created_at) %> ago
      by <%= topic.comments.last.user.name %>.
    <% else %>
      No comments.
    <% end %>
    <span class="pull-right">
      <%= pluralize(topic.comments.count, 'comment') %>.
    </span>
  </div>
</article>

topics_controller#index (produces incorrect data):

def index
  @topics = Topic.includes(:comments).order('comments.created_at desc')
end

I have also attempted:

def index
  @topics = Topic.includes(:comments).paginate(page: params[:page]).order('comments.created_at desc')
end

topics/index.html.erb(wrong data):

<% provide(:title, 'Forum Index') %>
<%= render partial: @topics, spacer_template: 'shared/hr' %>

Viewing a specific thread (in this case the topic.comments.last.user.name and topic.comments.last.created_at are the correct values):

def index
  @context = context
  @comments = @context.comments.paginate(page: params[:page])
end
#...
private
  def context
    Topic.find(params[:topic_id]) if params[:topic_id]
  end

topics/index.html.erb (right data):

<% provide(:title, @context.title) %>
<h1>View Discussion</h1>
<%= render(partial: 'topics/topic', object: @context) %>  # Partial with right data
<hr />
<%= render(partial: 'comment',
           collection: @comments,
           spacer_template: 'shared/hr',
           locals: { topic: @context }) || 'No comments.' %>

<hr />
<%= render partial: 'comment_form', locals: { context: @context,
                                              comment: @context.comments.new } %>

Solution

  • topic.comments.last
    

    should be

    topic.comments.first
    

    because you're placing the latest comments first.

    Where it's working fine, it is because you aren't ordering the comments and the last will fetch the comment with the highest primary index value which is most likely the ID.

    Hope that clears it up.

    And just FYI:

    topic.comments.count
    

    will fire up another query in your view. Change the count to size