mataal
mataal

Reputation: 441

Displaying associated objects

I am a Ruby on Rails newbie and had a question about the view logic in case of associated objects:

My models look similar to

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

And what I want to display is something like a list of all the posts and the first three comments for each.

So, I kept the post contoller index action simple

class PostController < ApplicationController
  #..
  def index 
    @posts = Post.find(:all)
  end
  #..
end

Now in the views/posts/index.html.erb I can do something like this @posts.comments which I can loop for the first three entries. But How do I access functionality that is normally done in the model (in this case the associated model) like ordering, scoping etc. in the view (or controller)?

Upvotes: 2

Views: 319

Answers (2)

Simone Carletti
Simone Carletti

Reputation: 176412

You should avoid writing complex business login in the view. In this case, your execution is simple enough that you can write all the code in your view. It should look like this

<% @posts.each do |post| %>
  <% @post.comments.all(:limit => 3, :order => "created_at DESC").each do |comment| %>
      do something
  <% end %>
<% end %>

There are a couple of possibile improvements. First, use a named_scope.

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to  :post
  named_scope :recent, proc { |limit| :limit => limit || 3, :order => "created_at DESC") }
  # you can also hard-code the limit value (ScottD)
  named_scope :recent, :limit => 3, :order => "created_at DESC"
end


<% @posts.each do |post| %>
  <% @post.comments.recent.each do |comment| %>
      do something
  <% end %>
<% end %>

If I'm right, the .each can be removed.

<% @posts.each do |post| %>
  <% @post.comments.recent do |comment| %>
      do something
  <% end %>
<% end %>

If you prefer, you can also define a custom relationship (this is for really complex relationships).

Upvotes: 1

Corban Brook
Corban Brook

Reputation: 21378

You could use a find method on the association which specified a limit like:

@post.comments.find(:all, :limit => 3)

in your view, or you can create another association in your Post model something like:

has_many :first_three_comments, :limit => 3, :class_name => "Comment" 

and then you can just reference that association like

@post.first_three_comments.each do |comment| ...

Hope that helps.

Upvotes: 1

Related Questions