Simple (I'm sure) Question about Joins

I'm working on a into rails project in parallel with a book I'm reading. I have 3 models/controllers that I'm trying to get to interact properly: user, article, comment

Each article can have many comments, each comment is made by 1 user. Currently I'm able to get the article to show the comment content and the user_id of the commenter. But what I'm tying to do is get the username of the commenter based on that user_id.

Here is part of my controller for the Article

def show     @article = Article.find(params[:id])     @user = User.find(@article.user_id)     @comments = @article.comments     impressionist(@snippet) end

Each comment contains the following: content, user_id, article_id.

I can get the content and the user_id's associated to the article

<%= comment.content %> <%= comment.user_id %>

This is a test comment user_id: 14 This is yet another thrilling test comment user_id: 15

What I'd like is comment.username so I can get the users name, but that is throwing me for a loop. Making the connection between my users object and the comments object.

I just don't know how to get the username associated with that user_id from the users table. I've made it through my Rails Tutorial book, however it didn't cover anything like this and a couple hours of google-fu haven't yielded anything.

Any assistance is greatly appreciated!

Steve:

Assuming your many comments to one user relation is set-up properly, ask for cu = comment.user. Then <%= cu.username %> will work for you.

Doug

Douglas Lovell www.wbreeze.com

Douglas Lovell wrote in post #1071218:

Steve:

Assuming your many comments to one user relation is set-up properly, ask for cu = comment.user. Then <%= cu.username %> will work for you.

Doug

Douglas Lovell www.wbreeze.com

Worked perfectly, thank you! :slight_smile:

I'm working on a into rails project in parallel with a book I'm reading. I have 3 models/controllers that I'm trying to get to interact properly: user, article, comment

Each article can have many comments, each comment is made by 1 user. Currently I'm able to get the article to show the comment content and the user_id of the commenter. But what I'm tying to do is get the username of the commenter based on that user_id.

Here is part of my controller for the Article

def show     @article = Article.find(params[:id])     @user = User.find(@article.user_id)

You did not mention that the article has a user_id. I thought that was comments that had user_id. However since it does have a user_id then assuming you have set up the models correctly you should be able to say @user = @article.user

    @comments = @article.comments     impressionist(@snippet) end

Each comment contains the following: content, user_id, article_id.

I can get the content and the user_id's associated to the article

<%= comment.content %> <%= comment.user_id %>

This is a test comment user_id: 14 This is yet another thrilling test comment user_id: 15

What I'd like is comment.username so I can get the users name, but that is throwing me for a loop. Making the connection between my users object and the comments object.

I just don't know how to get the username associated with that user_id from the users table. I've made it through my Rails Tutorial book, however it didn't cover anything like this and a couple hours of google-fu haven't yielded anything.

Again you should just be able to use comment.user.name

If that does not work show us the most important information, which is how you have defined the relationships in the models (has_many, belongs_to etc).

Colin

Alright so I changed my comment form snippet from:

<%= form_for(@comment, :html => { :class => "joinform" }) do |f| %>

To:

<%= form_for([@snippet, @snippet.comments.build]) do |f| %>

Which caused my comment form to finally work successfully, however the following code now fails (this is my comment snippet)

<div class="comment_container">   <%= gravatar_for comment.user, :size => 30 %> <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span>   <div class="comment_content"><%= comment.content %></div> </div>

What does work about this is the comment.user and comment.created_at lines. Oddly enough, comment.content still shows the comment content. And comment.user.username still yields the users username, comment.user.email yields the commenters email, etc. However when passing comment.user into anything now fails.

NoMethodError in Snippets#show

Showing /Users/morri534/rails_projects/srclockr/app/views/comments/_comment.html.erb where line #2 raised:

undefined method `email' for nil:NilClass

I feel like I'm so close to getting a working comment system, but I'm missing one piece of the puzzle. I fixed the article comment box not working, but now the comments wont display the user info associated with them.

As usual, any help is greatly appreciated :slight_smile:

Here is some more code if it helps any:

class SnippetsController < ApplicationController   before_filter :signed_in_user, :only => [:create]   ...   ...   def show     @snippet = Snippet.find(params[:id])     @user = User.find(@snippet.user_id)     @comments = @snippet.comments     impressionist(@snippet)   end

class Comment < ActiveRecord::Base   attr_accessible :content, :snippet_id, :user_id   belongs_to :snippet   belongs_to :user

class Snippet < ActiveRecord::Base   attr_accessible :content, :title, :description

  belongs_to :user   has_many :comments

Since you have not quoted the previous message I have just wasted time looking back through the thread to work out what this is about. Remember this is a mailing list not a forum, though you may be using a forum style interface

Alright so I changed my comment form snippet from:

<%= form_for(@comment, :html => { :class => "joinform" }) do |f| %>

To:

<%= form_for([@snippet, @snippet.comments.build]) do |f| %>

Which caused my comment form to finally work successfully, however the following code now fails (this is my comment snippet)

<div class="comment_container">   <%= gravatar_for comment.user, :size => 30 %> <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span>   <div class="comment_content"><%= comment.content %></div> </div>

What does work about this is the comment.user and comment.created_at lines. Oddly enough, comment.content still shows the comment content. And comment.user.username still yields the users username, comment.user.email yields the commenters email, etc. However when passing comment.user into anything now fails.

NoMethodError in Snippets#show

Showing /Users/morri534/rails_projects/srclockr/app/views/comments/_comment.html.erb where line #2 raised:

undefined method `email' for nil:NilClass

You appear to have provided lots of irrelevant information this time, but not shown the code where the error is generated. I see that it is in a partial, and that you are calling email on something that is nil. Perhaps you have forgotten to pass the object to the partial.

Also have a look at the Rails Guide on debugging, which will show you techniques that can be used to help in debugging the code.

Colin

Colin Law wrote in post #1071341:

Since you have not quoted the previous message I have just wasted time looking back through the thread to work out what this is about. Remember this is a mailing list not a forum, though you may be using a forum style interface

I do apologize for that, I am quite new to the mailing list format of communication (which is even harder to grasp while viewing the discussion on a site called "ruby-forum").

comment.user.email yields the commenters email, etc. However when passing comment.user into anything now fails.

NoMethodError in Snippets#show

Showing /Users/morri534/rails_projects/srclockr/app/views/comments/_comment.html.erb where line #2 raised:

undefined method `email' for nil:NilClass

You appear to have provided lots of irrelevant information this time, but not shown the code where the error is generated. I see that it is in a partial, and that you are calling email on something that is nil. Perhaps you have forgotten to pass the object to the partial.

This is true, I'm having a very hard time conveying this issue. I have spent countless hours trying to dig through debugging guides (including the one referenced by you) yet I haven't been able to ge to the bottom of this yet. As a direhard PHP programmer, getting my mind into Rails mode is proving to be a challenge, even after reading a whole book and a number of web resources on the topic.

So maybe this will help. If anyone is still willing to take a peek, I have put the code on Github.

The comment form partial that was in place when the comment listings was working is this: https://github.com/uberamd/srclockr/blob/93c88fd17bb4ddde6c9a0eb88a87b2cfeefde897/app/views/shared/_comment_form.html.erb

When _comment_form.html.erb looked like that I was able to get comments to display properly using this code: https://github.com/uberamd/srclockr/blob/93c88fd17bb4ddde6c9a0eb88a87b2cfeefde897/app/views/comments/_comment.html.erb

However, when I changed _comment_form.html.erb to this code, the ability to comment started working perfectly, however listing comments stopped working: https://github.com/uberamd/srclockr/blob/master/app/views/shared/_comment_form.html.erb

Whats odd (to me) is that I can call comment.user.email and get the users email, but changing the _comment_form.html.erb file caused the displaying of comments to break, which is not associated.

The comment, snippet, and user controller can be seen here: https://github.com/uberamd/srclockr/tree/master/app/controllers

And the page where everything is brought together (snippets/show.html.erb): https://github.com/uberamd/srclockr/blob/master/app/views/snippets/show.html.erb

Hopefully this helps clarify the error I'm seeing. Despite my attempts to debug, I'm just entirely lost as to why changing the partial for the comment form broke the displaying of comments, though I'm sure its a fairly basic error I'm encountering. Especially since, on the comments partial, I'm still able to see the comment.content, just none of the comment.user (who made the comment) information.

1 beer for anyone who can help guide this lost soul :slight_smile:

-Steve

Colin Law wrote in post #1071341:

Since you have not quoted the previous message I have just wasted time looking back through the thread to work out what this is about. Remember this is a mailing list not a forum, though you may be using a forum style interface

I do apologize for that, I am quite new to the mailing list format of communication (which is even harder to grasp while viewing the discussion on a site called "ruby-forum").

comment.user.email yields the commenters email, etc. However when passing comment.user into anything now fails.

NoMethodError in Snippets#show

Showing /Users/morri534/rails_projects/srclockr/app/views/comments/_comment.html.erb where line #2 raised:

undefined method `email' for nil:NilClass

You appear to have provided lots of irrelevant information this time, but not shown the code where the error is generated. I see that it is in a partial, and that you are calling email on something that is nil. Perhaps you have forgotten to pass the object to the partial.

This is true, I'm having a very hard time conveying this issue. I have spent countless hours trying to dig through debugging guides (including the one referenced by you) yet I haven't been able to ge to the bottom of this yet. As a direhard PHP programmer, getting my mind into Rails mode is proving to be a challenge, even after reading a whole book and a number of web resources on the topic.

So maybe this will help. If anyone is still willing to take a peek, I have put the code on Github.

The comment form partial that was in place when the comment listings was working is this: https://github.com/uberamd/srclockr/blob/93c88fd17bb4ddde6c9a0eb88a87b2cfeefde897/app/views/shared/_comment_form.html.erb

When _comment_form.html.erb looked like that I was able to get comments to display properly using this code: https://github.com/uberamd/srclockr/blob/93c88fd17bb4ddde6c9a0eb88a87b2cfeefde897/app/views/comments/_comment.html.erb

However, when I changed _comment_form.html.erb to this code, the ability to comment started working perfectly, however listing comments stopped working: https://github.com/uberamd/srclockr/blob/master/app/views/shared/_comment_form.html.erb

Whats odd (to me) is that I can call comment.user.email and get the users email, but changing the _comment_form.html.erb file caused the displaying of comments to break, which is not associated.

The comment, snippet, and user controller can be seen here: https://github.com/uberamd/srclockr/tree/master/app/controllers

And the page where everything is brought together (snippets/show.html.erb): https://github.com/uberamd/srclockr/blob/master/app/views/snippets/show.html.erb

Hopefully this helps clarify the error I'm seeing. Despite my attempts to debug, I'm just entirely lost as to why changing the partial for the comment form broke the displaying of comments, though I'm sure its a fairly basic error I'm encountering. Especially since, on the comments partial, I'm still able to see the comment.content, just none of the comment.user (who made the comment) information.

Sorry, much too much information again. Don't complicate it by telling us about which bits do work or used to work, just pick out the bit of code that is not working and show us that. Put debug code in so that you can tell us what data is going in and explain what is going wrong. We have not (or at least I do not) have time to wade through all that information. If you have multiple problems then start off with just one of them.

There will only be a dozen or so lines of code so just put it inline.

1 beer for anyone who can help guide this lost soul :slight_smile:

I am doing my best, but you must keep the question simple.

Colin

Alright. Short and simple this time. Here is the code for snippets/show.html.erb (showing the article):

                     <div class="span4">         <h1>Comments (<%= @snippet.comments.count %>)</h1>         <hr>         <% if signed_in? %>           <%= render 'shared/comment_form' %>         <% end %>         <% if @snippet.comments.any? %>           <%= render @comments %>         <% else %>         <p>There are no comments on this snippet.</p>         <% end %>       </div>

Here is comment.html.erb being showed by render @comments:

<div class="comment_container">   <%= gravatar_for comment.user, :size => 30 %> <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span>   <div class="comment_content"><%= comment.content %></div> </div>

That is the code that isn't working and is giving the error. The only thing that will display is comment.content.

And here is the log output. Seems to be properly getting the user data for each comment, but comment.user isn't working. If I'm way off, let me know again. At the very least I'm learning to better communicate issues on this style of forum (sadly at the expense of peoples time).

   (0.1ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."snippet_id" = 4   Rendered shared/_comment_form.html.erb (19.5ms)   CACHE (0.0ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."snippet_id" = 4   Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."snippet_id" = 4 ORDER BY comments.created_at ASC   User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 14 LIMIT 1   User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 15 LIMIT 1   CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 14 LIMIT 1   Rendered comments/_comment.html.erb (27.5ms)   Rendered snippets/show.html.erb within layouts/application (172.9ms) Completed 500 Internal Server Error in 21602ms

ActionView::Template::Error (undefined method `email' for nil:NilClass):     1: <div class="comment_container">     2: <%= gravatar_for comment.user, :size => 30 %> <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span>     3: <div class="comment_content"><%= comment.content %></div>     4: </div>   app/helpers/users_helper.rb:7:in `gravatar_for'   app/views/comments/_comment.html.erb:2:in `_app_views_comments__comment_html_erb___715147692_2186695040'   app/views/snippets/show.html.erb:24:in `_app_views_snippets_show_html_erb__1112126603_2190824420'

Colin Law wrote in post #1071379:

Alright. Short and simple this time. Here is the code for snippets/show.html.erb (showing the article):

                     <div class="span4">         <h1>Comments (<%= @snippet.comments.count %>)</h1>         <hr>         <% if signed_in? %>           <%= render 'shared/comment_form' %>         <% end %>         <% if @snippet.comments.any? %>           <%= render @comments %>         <% else %>         <p>There are no comments on this snippet.</p>         <% end %>       </div>

Here is comment.html.erb being showed by render @comments:

<div class="comment_container">   <%= gravatar_for comment.user, :size => 30 %> <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span>   <div class="comment_content"><%= comment.content %></div> </div>

That is the code that isn't working and is giving the error. The only thing that will display is comment.content.

And here is the log output. Seems to be properly getting the user data for each comment, but comment.user isn't working. If I'm way off, let me know again. At the very least I'm learning to better communicate issues on this style of forum (sadly at the expense of peoples time).

   (0.1ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."snippet_id" = 4   Rendered shared/_comment_form.html.erb (19.5ms)   CACHE (0.0ms) SELECT COUNT(*) FROM "comments" WHERE "comments"."snippet_id" = 4   Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."snippet_id" = 4 ORDER BY comments.created_at ASC   User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 14 LIMIT 1   User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 15 LIMIT 1   CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 14 LIMIT 1   Rendered comments/_comment.html.erb (27.5ms)   Rendered snippets/show.html.erb within layouts/application (172.9ms) Completed 500 Internal Server Error in 21602ms

ActionView::Template::Error (undefined method `email' for nil:NilClass):     1: <div class="comment_container">

Put some debug in here to display (or log) comment.inspect (see the Rails Guide on debugging), and also comment.user.inspect unless comment.user is nil.

Colin

Colin Law wrote in post #1071405:

          <%= render @comments %> commented <%= time_ago_in_words comment.created_at %></span>

15 LIMIT 1   CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 14 LIMIT 1   Rendered comments/_comment.html.erb (27.5ms)   Rendered snippets/show.html.erb within layouts/application (172.9ms) Completed 500 Internal Server Error in 21602ms

ActionView::Template::Error (undefined method `email' for nil:NilClass):     1: <div class="comment_container">

Put some debug in here to display (or log) comment.inspect (see the Rails Guide on debugging), and also comment.user.inspect unless comment.user is nil.

Colin

Thanks for the continued replies, Colin.

<%= comment.inspect %> gave me:

#<Comment id: 1, content: "This is a test comment", user_id: 14, snippet_id: 4, created_at: "2012-08-03 18:01:54", updated_at: "2012-08-03 18:01:54">

And <%= comment.user.inspect %> gave me:

#<User id: 14, name: "Steve Morrissey", email: "uberamd@gmail.com", username: "uberamd", isadmin: nil, isbanned: nil, created_at: "2012-08-01 19:59:27", updated_at: "2012-08-02 19:39:18", password_digest: "$2a$10$nLyWoNjW3/7asFRYsfSKh.yEn824BVcoX2S6erXR3QxV...", remember_token: "73iKpBFDCXc4Imq46iABh7RUkG9n8M1HZR9c26b8AIZiFMgAZlt...">

So it appears, from my side of the table, that things are in order, though clearly I'm missing something important. It looks, to me, like comment.user has all the required info to display the gravatar_for image (it just requires an email address) as well as comment.user.username and comment.created_at. But alas, I am clearly wrong as it doesn't work.

Where are you getting gravatar_for from? Perhaps you are using a gem that is not compatible with your version of rails.

Colin

Colin Law wrote in post #1071422:

Completed 500 Internal Server Error in 21602ms

Thanks for the continued replies, Colin. username: "uberamd", isadmin: nil, isbanned: nil, created_at: comment.created_at. But alas, I am clearly wrong as it doesn't work.

Where are you getting gravatar_for from? Perhaps you are using a gem that is not compatible with your version of rails.

Colin

I thought about that, but then I tried to do something even easier. A simple link to the commenters profile <%= link_to comment.user.username, comment.user %> which gives:

NoMethodError in Snippets#show

Showing /Users/smorriss/ruby_projects/srclockr/app/views/comments/_comment.html.erb where line #4 raised:

undefined method `username' for nil:NilClass Extracted source (around line #4):

1: <div class="comment_container"> 2: <%= comment.inspect %> 3: <%= comment.user.inspect %> 4: <span class="username"><%= link_to comment.user.username, comment.user %> commented <%= time_ago_in_words comment.created_at %></span> 5: <div class="comment_content"><%= comment.content %></div> 6: </div>

So I'm basically very confused right now. It looks like comment.user has everything I'd need to do that, yet nothing works. I can't even do a <%= comment.user.username %> to display the users name, as it fails.

There is something horribly wrong somewhere. Which version of ruby and of rails are you using? rails -v and ruby -v. What do you see for inspect comment.user.username?

Colin Law

Colin Law wrote in post #1071427:

undefined method `username' for nil:NilClass

So I'm basically very confused right now. It looks like comment.user has everything I'd need to do that, yet nothing works. I can't even do a <%= comment.user.username %> to display the users name, as it fails.

There is something horribly wrong somewhere. Which version of ruby and of rails are you using? rails -v and ruby -v. What do you see for inspect comment.user.username?

Colin Law

It's starting to feel good that maybe, just maybe, I'm not losing my mind here.

$ rails -v Rails 3.2.6 $ ruby -v ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]

undefined method `username' for nil:NilClass Extracted source (around line #4):

1: <div class="comment_container"> 2: <%= comment.inspect %> 3: <%= comment.user.inspect %> 4: <%= comment.user.username.inspect %> 5: <div class="comment_content"><%= comment.content %></div> 6: </div>

Steve Morrissey wrote in post #1071429:

Colin Law wrote in post #1071427:

undefined method `username' for nil:NilClass

So I'm basically very confused right now. It looks like comment.user has everything I'd need to do that, yet nothing works. I can't even do a <%= comment.user.username %> to display the users name, as it fails.

There is something horribly wrong somewhere. Which version of ruby and of rails are you using? rails -v and ruby -v. What do you see for inspect comment.user.username?

Colin Law

It's starting to feel good that maybe, just maybe, I'm not losing my mind here.

$ rails -v Rails 3.2.6 $ ruby -v ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]

undefined method `username' for nil:NilClass Extracted source (around line #4):

1: <div class="comment_container"> 2: <%= comment.inspect %> 3: <%= comment.user.inspect %> 4: <%= comment.user.username.inspect %> 5: <div class="comment_content"><%= comment.content %></div> 6: </div>

Oddly enough I put a bandaid on this issue by moving the comment_form partial from above the list of comments to under the list of comments. This fixed everything. My guess would be that since the form has fields like comment[content], it was creating an object called comment which was conflicting with the partial that listed the comments out.