Question

I have an item ActiveRecords and I am trying to set a default value ("Test item") for each of them using a block.
In this expression:

list = {"type1", "type2", "type3", "type4", "..."}
list.each { |name| @item.attributes["#{name}"] = "Test item"] }

values aren't set.

I must use @item.attributes["#{name}"] for interpolation because I can't do this for every item:

@item.tipe1 = "Test item"

So, what happens in the first statement? Why? If what I would like to do is not possible in that way, how I can do the same?

Was it helpful?

Solution

The assignment @items.attributes["#{name}"] = "Test item"] does not work, because the attributes method returns a new Hash object each time you call it. So you are not changing the value of the @items' object as you thought. Instead you are changing the value of the new Hash that has been returned. And this Hash is lost after each iteration (and of course when the each block has finished).

A possible solution would be to create a new Hash with the keys of the @items' attributes and assign this via the attributes= method.

h = Hash.new

# this creates a new hash object based on @items.attributes
# with all values set to "Test Item"
@items.attributes.each { |key, value| h[key] = "Test Item" }

@items.attributes = h

OTHER TIPS

You can use the send method for this purpose. Perhaps like this:

list = {"type1", "type2", "type3", "type4", "..."}
list.each { |name| @item.send("#{name}=", "Test item") }

I think the problem is that you are only changing the returned attribute hash, not the ActiveRecord object.

You need to do something like:

# make hash h
@items.attributes = h

Following your example, perhaps something like:

@items.attributes = %w{type1 type2 type3 type4}.inject({}) { |m, e| m[e] = 'Test item'; m }

BTW, "#{e}" is the same thing as String expression e or for any type: e.to_s. A second example, perhaps easier to read:

a = %w{type1 type2 type3 type4}
h = {}
a.each { |name| h[name] = 'test item' }
@items.attributes = h

Using the attributes= method is probably intended for hash constants, like:

@items.attributes = { :field => 'value', :anotherfield => 'value' }

For entirely generated attributes you could take DanneManne's suggestion and use send.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top