How might these params be captured

Unsure and no luck so far on how to save the params from 3 text fields all for the same object / method. I guess this would be an array of arrays ?

{“cantitle”=>{“1”=>{“title_opt”=>“CEO”},
“2”=>{“title_opt”=>“COO”},
“3”=>{“title_opt”=>“CIO”}},

Stuart

No I would loop them as each needs to be a seperate record. However I just can’t figure out how to call them.
{“cantitle”=>{“1”=>{“title_opt”=>“CEO”}, “2”=>{“title_opt”=>“COO”},> “3”=>{“title_opt”=>“CIO”}},

The formfields are like this <%text_field :cantitle, :title_opt, index => 1%>
<%text_field :cantitle, :title_opt, index => 2%>
<%text_field :cantitle, :title_opt, index => 3%>

I had to add index to make them all individual params.
Just can’t figure out what they are called. ??
"[cantitle][:1][:title_opt] etc ? Maybe, not in front of my dev machine right now.

Stuart

Hey Stuart-

  You can grab the params like this:

# Assuming you want to make new Cantitle objects
params['cantitle'].each {|k, v| Cantitle.create(v) }

# Assuming you want to update pre existing Cantitle objects
params['cantitle'].each {|k, v| Cantitle.find(k).update_attributes(v) }

Cheers-
-- Ezra Zygmuntowicz-- Lead Rails Evangelist
-- ez@engineyard.com
-- Engine Yard, Serious Rails Hosting
-- (866) 518-YARD (9273)

Why does this work params[‘cantitle’].each {|k, v| Cantitle.create(v) }

Yet this doesn’t work:

params[‘cantitle’].each {|k, v|

cantitle.candidate_id = @candidate_id

cantitle.user_id = current_user.id

Cantitle.create(v) }

the candidate_id and user_id need to be inserted with each record.
I get a “undefined local variable or method `cantitle’”

Stuart

Unsure and no luck so far on how to save the params from 3 text
fields all for the same object / method. I guess this would be an
array of arrays ?

{“cantitle”=>{“1”=>{“title_opt”=>“CEO”}, “2”=>{“title_opt”=>“COO”},
“3”=>{“title_opt”=>“CIO”}},

Stuart

Hey Stuart-

    You can grab the params like this:

Assuming you want to make new Cantitle objects

params[‘cantitle’].each {|k, v| Cantitle.create(v) }

Assuming you want to update pre existing Cantitle objects

params[‘cantitle’].each {|k, v| Cantitle.find(k).update_attributes(v) }

Why does this work params[‘cantitle’].each {|k, v| Cantitle.create(v) }

Yet this doesn’t work:

params[‘cantitle’].each {|k, v|

cantitle.candidate_id = @candidate_id

cantitle.user_id = current_user.id

Cantitle.create(v) }

the candidate_id and user_id need to be inserted with each record.
I get a “undefined local variable or method `cantitle’”

Doing this:

a = params[‘cantitle’]
a.each {|k, v|
cantitle = Cantitle.new
cantitle.candidate_id = @candidate_id
cantitle.user_id = current_user.id
cantitle.title_opt = v
cantitle.save }

I am now getting this in the title_opt field
— !map:HashWithIndifferentAccess title_opt: COO

Close I guess :slight_smile:
Stuart

Not 100% sure what you really need, bu i think you mixed it up,
as you try to manipulate a "cantitle" object before you have one,
and you should use build, not create.

for each params set in params[:cantitle]:
1) build a cantitle object with the parameters (v)
2) add the @candidate_id
3) add the current_user.id
4) save the cantitle object

params[:cantitle].each do |k, v|
    cantitle = Cantitle.build(v)
    cantitle.candidate_id = @candidate_id
    cantitle.user_id = current_user.id
    cantitle.save
end

I assume @candidate_id is initiated and filled before that pice of
code...

Question for Ezra: i relied on your example for this, but im a bit
confused:
when i do :
params[:cantitle].each do |k, v|
is k = 'title_opt' and v = k's value ?

and wouldnt create() or build() require the key => value pair instead
of just v (the value) ?
or am i mixing something up here ?
I still have to learn much about ruby, i know more about the logic in
rails than about the
actual language and syntax beneath :stuck_out_tongue:

ah, figured it out myself.

@Dark Ambient:

k,v| means:

k is the key of the array (meaning: the number of the arrays entry)
v is the hash in each array entry { title_opt => someValue }

so it would be:

cantitle.title_opt = v[:title_opt]

.... i think ... :smiley:
or use my way with Cantiltle.build(v)

ah, figured it out myself.

@Dark Ambient:

k,v| means:
k is the key of the array (meaning: the number of the arrays entry)
v is the hash in each array entry { title_opt => someValue }

Okay, at first I thought I had a multidimensional array. Which I guess it still is ?
But each array is a hash ?
I’m not looking for any explanation, I’m sure it will eventually sink in. I think I’m more used to seeing the v stand for value.

so it would be:

cantitle.title_opt = v[:title_opt]

… i think … :smiley:

Good thinking :slight_smile: , it worked.

or use my way with Cantiltle.build
(v)

I’ll keep this one in my pocket for now .

Thank you for the help.
Stuart

well the hash <-> array stuff confused and still confuses me from time
to time...
if you ever had experience with another scripting language, this
analogy might help:
arrays with number keys are also arrays in ruby.
arrays with named keys are known hashes in ruby, and they have no
specific order, like numbered arrays have.

params[:cantile] contains an array (or a hash if the numbers are given
as strings)...
{"1"=>somevalue1, "2"=>somevalue2, "3"=>somevalue3},

so params[:cantitle].each do |k,v| gives you each object in that
arrays/hash
with k = the number and v = somevalue

but each v contains a hash: {:title_opt => value } (a named key and a
correspnind value are a hash)

dont know if i used the right vocabulary in every place but i think
you might get the idea ...

well the hash <-> array stuff confused and still confuses me from time
to time…
if you ever had experience with another scripting language, this
analogy might help:
arrays with number keys are also arrays in ruby.

arrays with named keys are known hashes in ruby, and they have no
specific order, like numbered arrays have.

I think arrays with named keys are hashes in other languages as well. If I remember, PHP was the same.

params[:cantile] contains an array (or a hash if the numbers are given
as strings)…

{“1”=>somevalue1, “2”=>somevalue2, “3”=>somevalue3},

so params[:cantitle].each do |k,v| gives you each object in that
arrays/hash
with k = the number and v = somevalue

but each v contains a hash: {:title_opt => value } (a named key and a
correspnind value are a hash)

dont know if i used the right vocabulary in every place but i think
you might get the idea …

Yes, I do get the idea.

So now :slight_smile:

As my next challenge.
I have this situation - where I’m collecting a city and state,
I believe (haven’t gotten my hands dirty yet)
where the params are coming through as such

“canlocation”=>{“1”=>{“city”=>“Phoenix”,
“state_id”=>“3”},
“2”=>{“city”=>“Boston”,
“state_id”=>“19”},
“3”=>{“city”=>“Seattle”,
“state_id”=>“47”}}}

Actually I was pretty surprised at the nice neat way they get send. I mean since they are both part of the same model, Rails seems to join them together nicely in the array or hashes :slight_smile:

Current thinking is state_id gets nested inside of the city loop ?

Stuart

Nope no nesting needed, very nice -

b = params[‘canlocation’]
b.each {|k, v|

canlocation = Canlocation.new
canlocation.candidate_id = @candidate_id
canlocation.user_id = current_user.id
canlocation.city = v[:city]
canlocation.state_id = v[:state_id]
 canlocation.save

}

Works well.

Stuart

Hello Thorsten,

well the hash <-> array stuff confused and still confuses me
from time to time...
if you ever had experience with another scripting language, this
analogy might help:
arrays with number keys are also arrays in ruby.
arrays with named keys are known hashes in ruby, and they
have no specific order, like numbered arrays have.

If by named keys, you mean strings or symbols then your definition
is not correct.

From the doc :

     A +Hash+ is a collection of key-value pairs. It is similar to an
     +Array+, except that indexing is done via arbitrary keys of any
     object type, not an integer index. The order in which you traverse
     a hash by either key or value may seem arbitrary, and will
     generally not be in the insertion order.

You've got key-value pairs. But for key you can use any object,
and the same for value.

$ irb
irb(main):001:0> a=%w(un deux)
=> ["un", "deux"]
irb(main):002:0> b={ a => 1, 'foo' => 4, :bar => 6 }
=> {:bar=>6, ["un", "deux"]=>1, "foo"=>4}
irb(main):003:0> b[a]
=> 1

As you can see, I've used an array as a key so b[a] works.

With Rails, we manipulate often Hash-like objects called
HashWithIndifferentAccess objects. The difference is that
string key and symbol key give access to the same value, e.g.
options['foo'] is the same as options[:foo]

Rails also has an OrderedHash class, that is, key-value pairs
are ordered.

    -- Jean-François.

So what I have here is an array or an array of arrays (below) ? Or did I thoroughly miss your point?
.
“canlocation”=>{“1”=>{“city”=>
“Phoenix”,
“state_id”=>“3”},
“2”=>{“city”=>“Boston”,
“state_id”=>“19”},
“3”=>{“city”=>“Seattle”,
“state_id”=>“47”}}}

Also, I notice some odd behaviour in that if no values are created, this array of arrays still exists.
Example:
If I have a field set up like such:

<%= options_from_collection_for_select @terms, :id, :name %>

Which is still multiple values but in one array, if nothing is selected there are no params.

Yet with this element:

<%= text_field(:canlocation, :city, "index" => 1)%> <%= collection_select(:canlocation, :state_id, @states, :id, :name, { :prompt => true },{"index" => 1})%>

this will still show up:

“canlocation”=>{“1”=>{“city”=> ,
“state_id”=>},

This make sense ?
If so, how does one test for an empty array in the controller ?
empty?, blank?, and nil seem to have no effect ?

Stuart

Worked it out -
a = params[‘cantitle’]
a.each {|k, v|
cantitle = Cantitle.new
cantitle.candidate_id = @candidate_id
cantitle.user_id = current_user.id
unless v[:title_opt].blank? # checks here for no value.
cantitle.title_opt = v[:title_opt]
cantitle.save
end
}

Stuart