Ricketyship
Ricketyship

Reputation: 654

Update a ruby array containing objects

If I have an array of objects in ruby, how can I iterate over the array and update the object?

example: test_arr has the following value: (fetched by a find_by_sql)

test_arr = [
  {"id"=>1024, "value"=>"9999"},
  {"id"=>1025, "value"=>"9999"} 
]
test_arr.map{|r| r.value="1111"}

returns ["1111", "1111"]

I need something like: (after update)

[{"id"=>1024, "value"=>"1111"}>,
{"id"=>1025, "value"=>"1111"}>]

Any help would be greatly appreciated.

Upvotes: 5

Views: 16795

Answers (4)

knut
knut

Reputation: 27845

You must use each, because map is returning a changed array. each is iterating the array.

test_arr.each{|r| r.value="1111"}

With

test_arr.map{|r| r.value="1111"}

You return a changed array, the content is the result of the block (in the example it is "1111"). With map! the array is modified.

You may also use:

test_arr.map{|r| 
  r.value="1111"   # modify r
  r                # return r - you are replacing r with r
}

But as already mentioned: each will be better.

Upvotes: 14

megas
megas

Reputation: 21791

Actually your code should update attributes successfully. But I think you confused the map and each methods.

The map method iterates through the whole array and collects results from every iteration, that's why it's second alias name is collect.

What you need is each method, this one will just iterate through the array and do actions described in block.

So, your code should look like this:

test_arr.each { |r| r.value="1111" }
test_arr.inspect 
#=> [#<SimpleClass:0xb74c8968 @attributes={"id"=>1024, "value"=>"1111"}>, #<SimpleClass:0xb74c8940 @attributes={"id"=>1025, "value"=>"1111"}>]

Upvotes: 2

Brad Werth
Brad Werth

Reputation: 17647

If you want to save it right away, try this:

test_arr.map{ |r| r.update_attributes( { :value => "1111" } ) }

If you need more performance than this, you could try update_all, and pass it the IDs from your array of objects. http://apidock.com/rails/ActiveRecord/Relation/update_all

Upvotes: 3

levinalex
levinalex

Reputation: 5949

map iterates over the array and gives you a new array containing the results of the block.

test_arr = test_arr.map { |val|
   val.attr - new_value
   val # last line of the block is the return value
}

use map! to update the array in place.

Upvotes: 1

Related Questions