4

This code shows all the records of CommunityTopic that belongs to current Community. How can I limit the numbers to 10 records to display here?

<ul>
  <% @community.community_topics.each do |topic| %>
    <li>
    <%= link_to topic.title, community_topic_path(@community, topic) %>
    <%= link_to topic.user.user_profile.nickname, community_topic_path(@community, topic) %>
    </li>
  <% end %>
</ul>
HUSTEN
  • 5,117
  • 4
  • 24
  • 38

3 Answers3

8

Use the limit method:

<% @community.community_topics.limit(10).each do |topic| %>

This will only supply the first 10 elements of the collection to the block. If you want to be more sophisticated, you could use something like will_paginate.

In general, such data fetching should take place in the controller. So instead of having a @community variable where the view gets the data from, have a @community_topics as well, which is prefilled with the data you want to render.

Femaref
  • 60,705
  • 7
  • 138
  • 176
  • 2
    You'd better use `limit(10)`, as `take` comes from Array and all the community_topics will be fetched in memory, although only 10 will be shown. – jdoe Dec 24 '12 at 17:32
  • So 'limit' eats less memory?? – HUSTEN Dec 24 '12 at 17:55
  • `limit` will change the database query to only fetch the first 10 records. `take` would trigger the query (all records) to build an array and then truncate the array to the first 10 records. – PinnyM Dec 24 '12 at 18:00
2

You shouldn't usually do this in the view, but rather in the controller. You can use limit as @Fermaref proposed, or you can use a paginator to help you out such as will_paginate or kaminari.

To move this to the controller, try something like this:

def some_action
  @community = Community.find(params[:id])
  @community_topics = @community.community_topics.order(:some_attribute).limit(10)
end

Then just use @community_topics in your view. One advantage here is that you can now move this logic to a private method for reuse if needed. You can also functionally test that @community_topics limits to 10 rows.

PinnyM
  • 35,165
  • 3
  • 73
  • 81
  • What's the reason why I shouldn't do this in view? and what if I'm showing 10 newest Topic in current Community#show? Should I use this way? If they wanna see more, then can press 'show all' and moves to CommunityTopic#index – HUSTEN Dec 24 '12 at 17:28
  • 1
    Modifying/truncating collections in the view is considered poor design, as it makes your logic more difficult to test, debug, and refactor. Sometimes it can't be helped, but data collection for rendering belongs in the controller wherever possible. – PinnyM Dec 24 '12 at 17:30
  • Okay that makes sense Thanks so much! In this case, how can you replace this to controller-based? – HUSTEN Dec 24 '12 at 17:38
  • 1
    Updated to clarify. Note that I added an `order` clause so the topics will return predictably - substitute `:some_attribute` for whatever makes sense in your case. If the association is hard coded to use a specific order this won't be necessary. – PinnyM Dec 24 '12 at 18:04
  • You certainly can. And that will usually be in the controller as well for the same reasons. – PinnyM Dec 24 '12 at 18:53
0

Use 8.3 reorder

The reorder method overrides the default scope order. For example:

@categories = Category.includes(:subcategories).where(active: true).references(:subcategories).order(name: :asc).reorder('categories.name ASC', 'subcategories.name ASC')

http://guides.rubyonrails.org/active_record_querying.html

gilcierweb
  • 2,598
  • 1
  • 16
  • 15