Forum: Ruby on Rails managing belongs_to fields in a form

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B45eab4f18aa1bb2a44d6e657531a642?d=identicon&s=25 Alain Ravet (aravet)
on 2005-12-16 10:37
Hi all,

I cannot find a clean way to create/edit an object that 'belongs_to'
another one, just by using form fields.
I always need to explicitely unassemble it, store the master id in a
hidden field, and then refetch the master from its id, and put it back
in the object.

To summarize:
I want to create a new member, for a given project

    @project= ...
    @member = Member.new (:project => @project)

=> in the view, if I have a form with

  project<%= text_field 'member', 'project' %><br>
  login  <%= text_field 'member', 'name'    %><br>

it doesn't work:
    - the project fields contains/shows
		#<Project:0x248aa50>
    - when I submit the form, I get the  error :
		"Project expected, got String"

Is there a nice Rails idioms to solve this problem?


Alain
3203ed0e608d3bfae1e31282e629ffa2?d=identicon&s=25 Peter Fitzgibbons (Guest)
on 2005-12-16 11:46
(Received via mailing list)
On 12/16/05, Alain Ravet <alainravet-spam2004@yahoo.com> wrote:
> I want to create a new member, for a given project
>     - the project fields contains/shows
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>

You could try using the session for it.  I keep both ids (
session[:project_id] or session[:project][:id] ) and whole objects (
session[:project] ) inside it.

Disclaimer: I am running a low-medium load public site and I have NOT
profiled memory use yet.

--
Eea7ad39737b0dbf3de38874e0a6c7d8?d=identicon&s=25 Justin Forder (Guest)
on 2005-12-16 13:07
(Received via mailing list)
Alain Ravet wrote:
>
> 		#<Project:0x248aa50>
>     - when I submit the form, I get the  error :
> 		"Project expected, got String"
>
> Is there a nice Rails idioms to solve this problem?

The technique demonstrated in the 15 minute Rails movie, at the point
where comments are added to blog posts, is to put the parent object's ID
in the URL that the child details will be submitted to:

In the view of a specific post, app/views/blog/show.rhtml, which also
shows the existing comments, this form is used to add a new comment:

<%= form_tag :action => 'comment', :id => @post %>
   <%= text_area "comment", "body" %><br/>
   <%= submit_tag "Comment!"%>
</form>

and the new comment is handled by this action in the controller:

   def comment
     Post.find(params[:id]).comments.create(params[:comment])
     flash[:notice] = "Added your comment."
     redirect_to :action => "show", :id => params[:id]
   end

regards

   Justin
B45eab4f18aa1bb2a44d6e657531a642?d=identicon&s=25 Alain Ravet (aravet)
on 2005-12-16 14:07
Justin

   > The technique demonstrated in the 15 minute Rails movie,
   > is to put the parent object's ID in the URL parameter

I know, and that's what I do, but it's not nice.

What if an object belongs_to 5 other entities:
   def new
       ...
       m = Member.new (:project => project,
               :section => section, :branch => branch,
                etc...)
And what if this object already exist, and you just want to edit it?

It's not very comfortable, having to
   1/dismantle all the parts linked to foreign keys,
   2/ship their IDs(in the url),
   <form action here>
   3/collect the parts + the foreign keys id, and then
   4/ fetch the foreign object and rebuild the main object
before
   5/saving.


I wonder if there isn't a Rails idiom to solve that problem?

Alain
Eea7ad39737b0dbf3de38874e0a6c7d8?d=identicon&s=25 Justin Forder (Guest)
on 2005-12-16 15:23
(Received via mailing list)
Alain Ravet wrote:

>    > The technique demonstrated in the 15 minute Rails movie,
>    > is to put the parent object's ID in the URL parameter
>
> I know, and that's what I do, but it's not nice.

OK - your previous post said that you were using a hidden field.

>    2/ship their IDs(in the url),
>    <form action here>
>    3/collect the parts + the foreign keys id, and then
>    4/ fetch the foreign object and rebuild the main object
> before
>    5/saving.

Your earlier question was just about members of projects (which in
general would be many-to-many, so you might be editing a Membership
rather than a Member). I'm not clear on whether, in your expanded
example, it's the Member or the Project that has section and branch - or
the Membership?

Which relationships are genuine "belongs to" (strict containment)
relationships, and which are just references?

> I wonder if there isn't a Rails idiom to solve that problem?

I don't claim any particular expertise, but this is my take:

Passing the id in the URL is appropriate when you have navigated from a
parent to a new child. Other references from the child would normally be
set up by controls in the child form (e.g. select lists, checkboxes...).

If you are editing an existing object, and there are relationships that
aren't being changed (e.g. if it isn't changing its parent) then you
don't need to pass those IDs around. You have a copy of the object,
either in the session or in the database, and you can leave those
attributes unchanged. For relationships that *are* changeable, there
should be controls on the child form.

I agree that would be nice if there were standard examples covering the
various relationship types and user interaction styles, and especially
if scaffolding could be extended to cover some of this.

regards

   Justin
B45eab4f18aa1bb2a44d6e657531a642?d=identicon&s=25 Alain Ravet (aravet)
on 2005-12-16 16:06
Justin
   >>    > is to put the parent object's ID in the URL parameter
   >> I know, and that's what I do, but it's not nice.
   >
   > OK - your previous post said that you were using a hidden field.

I've tried many techniques, where I each time explicitely manipulated
the belonged_to/foreign_key related object/id.


   >>    3/collect the parts + the foreign keys id, and then
   >>    4/ fetch the foreign object and rebuild the main object
   >> before    5/saving.
   >
   > Your earlier question was just about members of projects

Actually, I'm letting one member edit his info, but the project is fixed
in advance.
    member = Member.new (:project => the_project)


   > Which relationships are genuine "belongs to" (strict containment)
   > relationships, and which are just references?


For example, add a new 'Employee' to a a given 'Company', and give him a
default work "Address".

=> The data sent to the form is
   e = Employe.new (:company => the_company, :address =>
the_company.address)

In the db, the 'employees' table has 2 foreign keys : company_id, and
address_id.
My problem is that when it comes to creating an 'employee' in a form, I
have to EXPLICITELY manipulate its 'address' and 'company' ids/foreign
keys after the submit, even though I already set those 2 values in an
earlier step (see above).

 ( manipulate the fk == extract them, send them to the form, store them
in hidden fields as numerical values, and after the submit perform
multiple XXX.find( fk) to retrieve the employee previously known address
and company, and stuff them back in the employee object.

I'm just wondering/asking is there is a Rails idiom for this case, that
would make my life simpler and the code shorter/clearer.


Alain
Eea7ad39737b0dbf3de38874e0a6c7d8?d=identicon&s=25 Justin Forder (Guest)
on 2005-12-17 14:39
(Received via mailing list)
Alain Ravet wrote:
>    >>    3/collect the parts + the foreign keys id, and then
>    > Which relationships are genuine "belongs to" (strict containment)
> In the db, the 'employees' table has 2 foreign keys : company_id, and
>
> I'm just wondering/asking is there is a Rails idiom for this case, that
> would make my life simpler and the code shorter/clearer.

So long as there is no risk that the company or company address has been
deleted by another user, you don't need to do those finds - you can just
set the IDs using the accessors for company_id and address_id.

An alternative approach would be to hold the Employee/Company/Address
combination in the session, so that when the form is submitted you could

    - get the Employee out of the session
    - apply the changes
    - save it
    - clear the session attribute

regards

   Justin
This topic is locked and can not be replied to.