I'm about to give up...I guess noone can help with passing a


#1

No one seems to be able to help with my request. I bet this can be done
in rails, but I’m not going to figure it out without any help anytime
soon.

Trying to be brief: I have three classes: Account, Employee, and
AccountEmployeeRelation (which contains more than just the FKs).
In the form where I create a new account, I know how to add a ONE linked
employee. I do not know how to extend this to add MULTIPLE linked
employees.
Here is the working code for one employee:

def new
@account = Account.new
@relation = AccountEmployeeRelation.new
end

def create
@account = Account.new(params[:account])
@relation = AccountEmployeeRelation.new(params[:relation])
@account.account_employee_relations << @relation
@account.save
@relation.save
redirect_to :action => :list
end

The View:
<% form_for :account, :url => { :action => :create } do |form| %>
Title: <%= form.text_field :title %>

<% fields_for :relation do |f|%>
Employee: <%= f.select (:employee_id, Employee.find(:all).map{|u|
[u.name, u.id]}) %>

<% end %>

<%= submit_tag %>
<% end %>

Can anyone help with extending this? I think new needs to look like:
def new
@relations = []
3.times do # I would not really do it this way.
@relations << AccountEmployeeRelation.new
end
end

But I’m stuck on the view.


#2

Rick S. wrote:

def new
@account = Account.new
@relation = AccountEmployeeRelation.new

I will suggest something really sucky. Either it will work
brilliantly, or you will get your answer from others leaping to your
defense from me.

 3.times do |idx|
   instance_eval "@relations_#{idx} = AccountEmployeeRelation.new"
 end

@account = Account.new(params[:account])
 3.times do |idx|
    relation = 

AccountEmployeeRelation.new(params[:“relation_#{idx}”])
account.account_employee_relations << relation
end

The View:
<% form_for :account, :url => { :action => :create } do |form| %>
Title: <%= form.text_field :title %>

 3.times do |idx|  #  similar symbol-abuse here...

<% fields_for :“relation_#{}” do |f|%>

Employee: <%= f.select (:employee_id, Employee.find(:all).map{|u|
[u.name, u.id]}) %>

<% end %>

And so on. However, I suspect in general you user interface is
too-closely matching the exact shape of your database. It should match
the way your users will typically enter their data.


Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!


#3

Rick,

You can set multiple values on a collection like this:

@account.account_employee_ids = params[:relation_ids]

where params[:relation_ids] is an array of the relationship ids.

I wrote up an example in my blog awhile back:

http://javathehutt.blogspot.com/2006/08/rails-realities-part-19-
relation.html

Also if you need to initialize a relationship when you create a new
instance see this post from hasmanyjosh:

http://blog.hasmanythrough.com/2007/1/22/using-faux-accessors-to-
initialize-values

Hope that helps,

-Michael
http://javathehutt.blogspot.com


#4

Rick wrote:

Thanks, I will try your suggestions shortly.

Try Mike’s sooner. :wink:

I’m open to suggestons about my interface. If I wanted to make the
inerface easy (for me) I would make the user create an Account, and
then later go back and add assigned Employees. I think it will be
more convenient (but not for me) to be able to assign employees on the
same form that creates the account.

The best deal there is show them a working interface as soon as
possible, with a few important features in it. Then they can request a
better look-and-feel, based on experience with the prototype…


Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!


#5

I’m quite lost.

I tried the suggestions at the first link…the check_box_tag, which
comes from your page, seems to work.

<% @account.account_employee_relations.each do |child| %>
<%=check_box_tag ‘account[account_employee_relation_ids][]’, child.id,
true %>

<%end%>

This produces (for each check box):

But when I change the check box to a text field:

<%= text_field ‘account[account_employee_relation_ids][]’, child.id
%>

I get an error:

`@account[account_employee_relation_ids]’ is not allowed as an
instance variable name


#6

Thanks, I will try your suggestions shortly.

I’m open to suggestons about my interface. If I wanted to make the
inerface easy (for me) I would make the user create an Account, and
then later go back and add assigned Employees. I think it will be
more convenient (but not for me) to be able to assign employees on the
same form that creates the account.


#7

Rick,

I did something this with a bit of AJAX. Basically, I gave the user the
option to tell me how many fields they wanted, and then had the form
load a partial with teh right number of fields.

Here’s the relevant bit of the _form.rhtml partial:

p>Select
options


number of options: <%= text_field ‘select_field’, ‘options_number’,
:id=>“watch_this”, :value=>@num%>
<%= render :partial=>"select_fields", :locals=>{:num=>@num}%>
<%= observe_field "watch_this", :url=>{:action=>"select_fields", :controller=>"custom_fields",:params=>{:campaign_id=>@campaign.id, :id=>@custom_field.id}}, :update=>"select_fields", :with=>"num" %>

And the _select_fields partial:

<% if num.nil?
num = @num
end
%>
<% if num.nil? or num == 0
num=3
end%>
enter “select” options:

<% num.times do |i|
if !@custom_field.nil? and @custom_field.field_type==“Select”
value = @custom_field.select_options[i]
else
value = “”
end -%>
<%=(i+1).to_s%>) <%= text_field ‘select_field’, ‘options’,:index=>i,
:value=>value %>

<% end -%>

The select_fields action just collects and passes through the number of
fields requested:

def select_fields
unless params[:id].nil?
@custom_field = CustomField.find(params[:id])
end
@num = params[:num].to_i
render :partial=>‘select_fields’, :protocol=>@@protocol
end

Hope that’s helpful. You could do it with just an RJS response to a
form_remote_tag instead of watching the field if you want.

In the end the (variable number of) params come in as a nested hash,
which I then pull apart and assign appropriately.

Asa