How to access nested params in controller

Hello,

I'm trying to check some value in the controller so that I can change
the behavior accordingly. I have a form set up such that when
submitted, the params looks like this:

{
"transport"=>{
"from_location"=>"Portland",

"transports_transits_attributes"=>{"1246482280809"=>{"city"=>"Osaka",
"country"=>"2"},
"0"=>{"city"=>"Seattle",
"country"=>"1"}},

"to_location"=>"Tokyo",
"departure_date"=>"01-Jul-2009",
"arrival_date"=>"02-Jul-2009"}
}

My question is in regards to the nested table "transports_transits"
that you see in the middle with two records. How would I access the
specific values in the nested table? I know I can populate the model
by @transport = Transport.new(params[:transport]), but what if I want
to access one of the values in "transports_transits" table, say, to
get value "Osaka"?

Thanks!

If I understand the question correctly you eant something like
params[:transports_transits_attributes][:1246482280809][:city] I
think.

Colin

Thanks, Colin.
I tried what you suggested like this (with quotes around the number),
and it worked.

params[:transport][:transports_transits_attributes][:"0"][:city] ==>
gets me "Seattle" from the initial example.

The problem I have now is that the numbers ("0" and "1246482280809")
are auto-assigned, so I don't know how I would access them then. The
first one always seem to get "0", but there can be many more
transports_transits for one transport, and all but the first will get
a random number assigned. Is there a way I can access them without
referring to these numbers? For example, I can get the length of the
array like this:

len = params[:transport][:transports_transits_attributes].length

and I would love to be able to iterate through the array like this
(sorry for the bad syntax, but you get the idea..):

for (int i=0; i<len; i++)
  params[:transport][:transports_transits_attributes](i)[:city]

but I can't seem to do that. Any suggestions?
Thanks!
Kumi

It should be [i] not (i) but a much more railsy way is

params[:transport][:transports_transits_attributes].each do |attr|
  # do something with attr[:city]
end

However, I have to say that you seem to be doing rather unusual things
which, when I find myself in such a situation, usually means I am
tackling something in the wrong way. Can I ask why are you parsing
the params in the first place rather than using them to build objects
in the usual way?

Colin

That did cross my mind, but I also wanted to know how to do something
like this if it was possible. attr[:city] didn't work..

But here's what I'm really trying to do.
I have a form that lets user enter transport information like arrival/
departure airports, time, etc. If there are transits in between, user
can add as many transits as they like - or None. When the form is
submitted, even when there are no transits, there is one empty
transports_transits_attributes, and I'm trying to catch that somehow
so it doesn't get saved to the database with blanks.

Here's the model:

That did cross my mind, but I also wanted to know how to do something
like this if it was possible. attr[:city] didn't work..

Use the debugger to find out why attr[:city] does not work. Google
ruby-debug and look in the ruby guides and railscasts for how to use
it if necessary.

But here's what I'm really trying to do.
I have a form that lets user enter transport information like arrival/
departure airports, time, etc. If there are transits in between, user
can add as many transits as they like - or None. When the form is
submitted, even when there are no transits, there is one empty
transports_transits_attributes, and I'm trying to catch that somehow
so it doesn't get saved to the database with blanks.

Here's the model:

--------------------------------------------
class Transport < ActiveRecord::Base

has_many :users, :through => :transports_users
has_many :transports_transits, :dependent => :destroy
accepts_nested_attributes_for :transports_transits, :allow_destroy
=> true

end
--------------------------------------------

and the form snippet for where transits are added/removed

--------------------------------------------
<div id="transits" style="display: none">
<% f.fields_for :transports_transits do |i| %>
<%= render :partial => 'transport_transit', :locals => { :form =>
i } %>
<% end %>
</div>
<%= add_transport_transit_link(f) %>
--------------------------------------------

and in the helper, I have
--------------------------------------------
def add_transport_transit_link(form_builder)
link_to_function 'Add transits' do |page|
form_builder.fields_for :transports_transits,
TransportsTransit.new, :child_index => 'NEW_RECORD' do |f|
html = render(:partial => 'transport_transit', :locals =>
{ :form => f })
page << "if($('transits').visible()) $('transits').insert
({ bottom: '#{escape_javascript(html)}'.replace(/NEW_RECORD/g, new Date
().getTime()) }); else $('transits').show();"
end
end
end
--------------------------------------------

As you can see, at first, this div is invisible and only becomes
visible when the add_transport_transit_link is clicked for the first
time by the user. The subsequent click will actually add more
transport_transit form.

*** So the real problem is that the first transit form is there
(although invisible).***

I couldn't figure out how to not have the first transit initially -
and that's why I was trying to deal with it after the fact. I hope
I'm making sense here.

This is a bit out of my comfort zone, can anyone else help?

Colin

Thanks, Colin.

I don't understand why yet, but this seems to get the value in the
nested table.

Please disregard my question above.. I figured out what I was doing
wrong.
In the controller (in "def new"), I had

@transport.transports_transits.build

which was the problem all along. This was the reason I had one record
in the nested table even when there was no transit record entered by
the user. I commented it out, deleted the " if visible" part in
helper method, and made the nested transit form visible to start with
and everything works fine now.

Colin, thanks anyway - I learned how to read the params somewhat and
now I know about the ruby-debug gem! :slight_smile:

Kumi