How to pass an object in a form

Hi,

Here’s a basic one again.

I have 3 models:

class Program < ActiveRecord::Base
has_many :comments
end

class Comment < ActiveRecord::Base
belongs_to :program
belongs_to :user
end

class User < ActiveRecord::Base
has_many :comments
end

Comments contain the next info:

  t.references :program
  t.references :user
  t.text :body
  t.timestamps

I implemented a RESTful app starting with programs and comments. And
later on I added Restful authentication ending up with the users object.

So now when I create a comment for a program I want to keep the data of
what user created that comment (that’s why I added the t.references :
user to the comments).

Everything is more or less ok but I don’t know to pass the user
reference when creating the comment. The user is known at the controller
via the current_user that the authentication plugin provides.

This is the form in the comments new.html.erb:

<% form_for([@program, @comment]) do |f| %>

Body
<%= f.text_area :body %>

<%= f.submit "Create" %>

<% end %>

How to plug the user object that the create method expects?
I’ve tried hidden fields but didn’t manage to get it working.

Any suggestions?

Thanks.

Thanks for the help.

Ok so now I don’t use any field and expect the controller to know about
the user. I did a test, user1 is loged in when posting.

This is the POST generated to create a comment:

Processing CommentsController#create (for 127.0.0.1 at 2008-03-05
14:57:51) [POST]

Session ID:
BAh7C…

Parameters: {
“program_id”=>“1”,
“commit”=>“Create”,
“authenticity_token”=>“ff…”,
“action”=>“create”,
“controller”=>“comments”,
“comment”=>{“body”=>“A new comment by user1”}}

Comment Create (0.000000)←[0m ←[0m
INSERT INTO comments (program_id, updated_at, body, user_id,
created_at) VALUES(1, ‘2008-03-05 14:57:51’, ‘A new comment by
user1’, NULL, ‘2008-03-05 14:57:51’)

So as we see the user_id is not included in the parameters at all. And
from the last part we see that the VALUE for user_id is NULL. So I’m
still facing the same problem that let me to try the hidden field.

Hints?

as the user is available in the controller directly through a method,
there is no need to use a hidden field or pass it with the form in any
other way. Besides, this would enable users to play with the form data
and e.g. post comments under another users id.

Instead, user this approach:
def create
@comment = current_user.comments.build(params[:comment])
if @comment.save
# … and so on, usual stuff
end
end

Buy building the object though the associations #build method, the
user_id column is automatically filled in, and for the user there is
no way of hacking another id into this.

This approach should be used in othert similar situations with nested
resources as well. it makes the code cleaner and more secure in
general.

On 5 Mrz., 13:05, comopasta Gr [email protected]

Hi,

@comment.user = current_user

I think that line was the final hint. But then I realized that at this
point I just want to see the user name and so far I was dealing with the
id, so I would need to look for the right name based on the user id.

So, I changed the comments model so that is contains a created_by string
instead of a reference to user.

Then I ended up with:

def create
@comment = @program.comments.build(params[:comment])
@comment.created_by = current_user.login

And in the view I use:

<% for comment in @comments %>

<%=h comment.created_by %> ....

And well that seems to be going fine. I can retrieve now from each
comment the name of the user that created it. That’s what I was looking
for (today :sunglasses:

I think this should do it…

Thanks a lot!
(I don’t know what I would do without this forum :wink:

what does your create action look like now?

also. slight correction as also program is a parent of the comment:

@program = Program.find(params[:progam_id])
@comment = @program.comments.build(params[:comment])
@comment.user = current_user
if @comment.save
#…

On 5 Mrz., 14:09, comopasta Gr [email protected]

On Mar 5, 5:53 am, comopasta Gr [email protected]
wrote:

One question for you… what if the user changes their name?

Robby

One question for you… what if the user changes their name?

Robby

I guess the question is for me since I said I’m happy with username at
this point. Yep that is a valid point. It would be safer to use the ID.

At this point I can move forward with the username. They wont change
them since I don’t let them do it :sunglasses:

But ID should be the one to use.

Cheers

another consideration is if you want to allow users to delete their
own comments. If you just store the username for a comment, you can’t
allow this, unless your usernames are unique and can’t be changed. So
yes, storing the id for the user is much better.

You might also want to check out the acts_as_commentable plugin which
provides a porlymorphic comment class, allowing you to assign comments
to various different models.

You can also use the userstamp plugin which will assign the currently
logged in user’s id to the object being created if your model contains
a ‘created_by’ column in the associated database table. I’m a big fan
of this option, since I often like to record the id of the user that
created or updated an object.

Mike

Hi,

If you want to be more DRY in your template, you can do:

in create.rhtml:
<% render :partial => ‘comment_strip’, :collection => @comments -%>

in _comment_strip.rhtml partial:
<% comment ||= comment_strip -%>

<%=h comment.created_by %> ...

Chris

On Mar 5, 9:53 pm, comopasta Gr [email protected]

Nice discussion you guys have here.

What if you have two levels of nesting? Take the following three
models:

Driver
has_many :cars
has_many :mugshots, :class_name => ‘Image’, :as => :asset

Car
belongs_to :driver
has_many :photos, :class_name => ‘Image’, :as => :asset

Image
belongs_to :asset, :polymorphic => true
has_attachment :content_type => :image, # using attachment_fu

How would you code the form to make mass-assignment work?