ylluminate
ylluminate

Reputation: 12369

How to access fields by attribute name from ActiveRecord row results?

Apparently I'm missing something obvious here, but would appreciate a quick example.

I've got a record coming back from ActiveRecord where I have a few columns selected from a query. The fields are of BigDecimal format and need to be flattened to string.

I had initially thought it was sufficient to pull the query with:

rows = ModelName.order("date DESC").select('table_name.precise_number1, table_name.precise_number2').limit(100).all.zip
rows_stringified1 = Array.new
rows_stringified2 = Array.new

readings.each do |row|
  rows_stringified1.push row[:precise_number1].to_s
  rows_stringified2.push row[:precise_number2].to_s
end

However, this yields an error such as can't convert Symbol into Integer. Obviously I'm not following exactly how to access columns from records in a row set result.

How would you normally do this?

Upvotes: 0

Views: 420

Answers (1)

mu is too short
mu is too short

Reputation: 434595

Presumably you have a typo and you're doing this:

readings = ModelName.order("date DESC").
                     select('table_name.precise_number1, table_name.precise_number2').
                     limit(100).
                     all.
                     zip

instead of assigning to rows. Noticed that zip at the end? That doesn't make any sense. When you do this:

[a, b, c].zip

you get this:

[[a], [b], [c]]

So, in your readings.each block, the row is in fact [model] rather than the model that you think it is and that means that row[:precise_number1] is trying to access the Array row using the Symbol :precise_number1 instead of the Integer that the Array expects, hence your "can't convert Symbol into Integer" error.

So either get rid of the zip and leave your each as-is:

readings = ModelName.order("date DESC").
                     select('table_name.precise_number1, table_name.precise_number2').
                     limit(100).
                     all
# ...
readings.each do |row|
  rows_stringified1.push row[:precise_number1].to_s
  rows_stringified2.push row[:precise_number2].to_s
end

or keep the zip and adjust your each block to match what row really looks like:

readings = ModelName.order("date DESC").
                     select('table_name.precise_number1, table_name.precise_number2').
                     limit(100).
                     all.
                     zip
# ...
readings.each do |row|
  rows_stringified1.push row.first[:precise_number1].to_s
  rows_stringified2.push row.first[:precise_number2].to_s
end

I'd recommend getting rid of the zip as it does nothing useful and just confuses things.

Upvotes: 2

Related Questions