0

Here are my models and associations:

project

class Project < ActiveRecord::Base
   ...
   has_many :projectmemberizations
   has_many :users, :through => :projectmemberizations
   has_many :project_comments
   ...
end

project_comment

class ProjectComment < ActiveRecord::Base
   attr_accessible :comment, :created_at, :project_id, :user_id, :user_name
   belongs_to :project
   has_many :projectcommentations
   has_many :users, :through => :projectcommentations

   def user
     self.user
   end
end

projectcommentation

class Projectcommentation < ActiveRecord::Base
   attr_accessible :comment_id, :project_id, :user_id, :user_name
   belongs_to :project_comment
   belongs_to :user
end

user

class User < ActiveRecord::Base
   belongs_to :account
   has_many :projectmemberizations
   has_many :projects, :through => :projectmemberizations
   has_many :projectcommentations
   has_many :project_comments, :through => :projectcommentations
end  

The question

So as you can see, users can comment on a project. That's working fine. But what I'm trying to get working is displaying in the view WHO created a comment. Right now I'm trying to do this and it's not producing any errors, but just not displaying anything for the user_name.

<% @project.project_comments.each do |comment|%>
   <div class="comment">
      <%= image_tag current_user.photo.url(:small) %>
      <strong><%= comment.user_name %></strong>
      <%= comment.comment %>
</div>
<% end %>  

Finally, I've got it working in the rails console if I do this:

comment = ProjectComment.first
comment.user_id = 1
comment.save
comment.user.name

So apparently it's not saving the user_id when adding a comment? Sorry for the length of this by the way!

PS here's she show and new actions in the project_comments controller:

def show
    @project_comment = ProjectComment.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render :json => @project_comment }
    end

  end

  def new
    @project_comment = ProjectComment.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render :json => @project_comment }
    end
  end

ProjectComment create method

 def create
    @project_comment = ProjectComment.new(params[:project_comment])

    respond_to do |format|
      if @project_comment.save
        format.html { redirect_to project_url(@project_comment.project_id), :notice => 'Project comment was successfully created.' }
        format.json { render :json => @project_comment, :status => :created, :location => @project_comment }
      else
        format.html { render :action => "new" }
        format.json { render :json => @project_comment.errors, :status => :unprocessable_entity }
      end
    end
  end

Code from view where comment is created

<%= form_for(@project_comment) do |f| %>
   <%= f.hidden_field :project_id, :value => @project.id %>
   <%= image_tag current_user.photo.url(:small) %>
   <%= f.text_area :comment, :class => "addcomment" %>
   <%= f.submit :value => "Comment", :class => "tagbtn" %>
<% end %>
Trevan Hetzel
  • 1,371
  • 7
  • 21
  • 42
  • 1
    Can you post up the code from the view where the ProjectComment is created? You need to set a user_id there at least or else it won't work. The rails console proves that your associations are working and like @cbascom suggested you have a lot of unnecessary stuff in here. For example, `def user` doesn't actually do anything. – Noah Clark Dec 12 '12 at 13:06
  • Aaahh that would make sense. I'm only setting the project id and not the user id. So I need to add something like: <%= f.hidden_field :user_id, :value => @user.id %> which, if I do that, gives me the error "Called id for nil, which would mistakenly be 4" – Trevan Hetzel Dec 12 '12 at 15:19
  • 1
    Trevan Yeah, you're missing that. Do you have @user defined in your controller? – Noah Clark Dec 12 '12 at 17:23
  • In my ProjectComments controller? No. To define that, would it just be something like ```@user = User.all``` in the show action? – Trevan Hetzel Dec 12 '12 at 17:59
  • I FIGURED IT OUT! I didn't need to define it in the controller, I just needed to save the user_id in a hidden field when submitting the form by doing <%= f.hidden_field :user_id, :value => current_user.id %>. It makes sense now. The value has to be the current_user's id. Thanks for your help! – Trevan Hetzel Dec 12 '12 at 18:39
  • Yeah, I didn't realize you were using current_user instead of user. But glad you got it figured out! – Noah Clark Dec 12 '12 at 19:01

1 Answers1

2

Your template is currently displaying the contents of comment.user_name. Your rails console example that is working uses comment.user.name. You do have user_name in the attr_accessible list of attributes on the ProjectComment model, but none of the posted code fills in a value for that attribute.

I believe from what you are describing that your ProjectCommentation model is unnecessary. The following models should give you what you are looking for:

class Project < ActiveRecord::Base
    ...
    has_many :projectmemberizations
    has_many :users, :through => :projectmemberizations
    has_many :project_comments
    ...
end

class ProjectComment < ActiveRecord::Base
    ...
    attr_accessible :comment, :created_at, :project_id, :user_id, :user_name
    belongs_to :project
    belongs_to :user
    ...
end

class User < ActiveRecord::Base
    belongs_to :account
    has_many :projectmemberizations
    has_many :projects, :through => :projectmemberizations
    has_many :project_comments
end

In the ProjectComment controller:

def create
    # If params[:project_comment] contains the user_id, it will be set here
    @project_comment = ProjectComment.new(params[:project_comment])

    # If your user id comes from somewhere else (like the user that is signed in)
    @project_comment.user_id = <user id here>

    # Normal save logic here
end
cbascom
  • 766
  • 1
  • 5
  • 21
  • You're right. When I change it to ```comment.user.name```, I get "stack level too dep". Taking out the ```def user``` block in the ProjectComment model gets rid of that stack level error, instead giving me "undefined method `user'" – Trevan Hetzel Dec 12 '12 at 02:49
  • Your ProjectComment model currently has_many :users which means the method to access those users is comment.users. Is each ProjectComment supposed to be associated with only one user using belongs_to instead of has_many? – cbascom Dec 12 '12 at 02:56
  • Yeah, only one user can belong to a comment. Many users can comment on the project though. So, a ProjectComment belongs_to a user and a user has_many ProjectComments. – Trevan Hetzel Dec 12 '12 at 03:00
  • Now that I looked at your comment, I see that what you were saying is the comment.user should be plural. Changing it to plural I get this error: "uninitialized constant ProjectComment::Projectcommentation". Any idea what's causing that? Thanks, @cbascom! – Trevan Hetzel Dec 12 '12 at 04:11
  • I edited my original answer to show what I believe your associations should look like based on what you are describing. Once your associations are set up that way, you should be able to do comment.user.name as you wanted to originally. – cbascom Dec 12 '12 at 04:56
  • Thanks for your help. So when I use the associations you provided above and do ```comment.user.name```, I get an "undefined method `name'" error still. Do I need to write some more code in the controller to fill that name value? For what it's worth, if I do ```comment.user.id```, I get the error "Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id". – Trevan Hetzel Dec 12 '12 at 05:07
  • Also, something kind of odd, but if I do ```comment.user_id```, the view displays the number 1 on the very first comment, but none others. It's like it's not looping through or something. – Trevan Hetzel Dec 12 '12 at 05:08
  • If comment.user.id is giving you the called id on nil error, it means that your comment is not correctly associated with a user (and this will also cause the undefined method 'name' error). Any comments that were already created before fixing your associations will have that problem. In the original question you posted, you executed some code in the rails console that set the user_id to 1 for the very first project comment. That is why comment.user_id is set correctly for that comment but no others. If you try comment.user.name for that first comment, it should work as well. – cbascom Dec 12 '12 at 05:18
  • I created a fresh project. No errors. Then added a comment and got the undefined method for name error. So if my comments aren't correctly associated with the users, wouldn't that be a problem in the model associations? Or does it lie in the ProjectComment controller, where I need to define ```user``` better? Again man, thanks for all your help. If I could pay you through SO I totally would :) – Trevan Hetzel Dec 12 '12 at 05:44
  • My guess is the problem is in your ProjectComment controller. You didn't post your create method from that controller, but in that create method you need to make sure you are setting the user_id and the project_id for the ProjectComment you are creating. – cbascom Dec 12 '12 at 05:50
  • Updated the post with the create method. Wouldn't I need to do something like: @project_comment = ProjectComment.new(params[:project_comment], :user.id) ? – Trevan Hetzel Dec 12 '12 at 05:54
  • See the updated answer for the two possibilities for setting user_id. If it is supposed to be coming from the view layer, look at your rails log file and make sure you see the user_id in the parameters that are being sent from the form. – cbascom Dec 12 '12 at 06:07