views:

35

answers:

2

I am trying to wrap my head around this problem. I know views shouldn't have that much logic in them. I have an app with users, posts and comments. Users have many posts and comments.

class User < ActiveRecord::Base
has_many :posts
has_many :comments

Posts belong to users and have many comments.

class Post < ActiveRecord::Base
has_many :comments
belongs_to :user

Comments belong to users and posts

class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user

In my post#show view I show comments under the post. I want to show the name of the user who made the comment. At the moment I have this in my view:

<% @post.comments.each do |comment| %>
  <p>
    <b>Commenter:</b>
    <%= link_to  User.find(comment.userid).login, User.find(comment.userid) %>
  </p>

  <p>
    <b>Comment:</b>
    <%= comment.body %>
  </p>
<% end %>

I should probably have that logic in my posts controller. But I am pretty confused. @post.comments returns an array(?) of comments belonging to the post. That means I can't have @commenter = @post.comments.userid. I am confused by the problem so I might not have explained it well.

+2  A: 

In fact during the comments loop, you can use comment.user to get the data of the user since you have declared the User has_many Comments relationship.

PeterWong
One more suggestion, you could use `<%= render :partial => @post.comments %>` to loop through those comments one by one. In this case, you will have to extract the loop into another view file `_comment.html.erb`.
PeterWong
Thanks. Is that just to clean the code up?
GreenRails
Yes, for cleaning up. My answer cleans your `User.find ...` in the view file, and my comment cleans your loop of `@post.comments.each`.
PeterWong
+3  A: 

To be more explicit on the first answer, you simply do this:

<%= link_to comment.user, comment.user %>

In your User model, override the to_s method like this so comment.user returns the string you want:

def to_s
  self.login
end

Finally, use eager loading to get all the data in one SQL call, instead of querying the DB separately for each comment.user. In your Post model:

class Post < ActiveRecord::Base
  has_many :comments, :include => :user

And in the Post controller:

def show
  @post = Post.find(params[:id], :include => :comments)
Ed H
+1 for making clearer.
PeterWong