Managing belongs_to fields in a form

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’ %>

login <%= text_field ‘member’, ‘name’ %>

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

On 12/16/05, Alain R. [email protected] 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
[email protected]
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.

Alain R. 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” %>

<%= submit_tag “Comment!”%>

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

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),

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

Alain R. 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),

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

Alain R. 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

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