Reputation: 441
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
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
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