I want to update an AR object, using an attribute name that I access from another source (in the real data, there are lots).
class DailyScore < ActiveRecord::Base
attr_accessor :mail, :date, :sun, :express, :average
end
array = ['mail','date','sun']
thing = DailyScore.new
How can I turn each item in the array into a symbol, and update the record accordingly?
Ideally, I'd like something like this:
array.each do |field|
thing.field = 1.0 #Float
end
UPDATE (with fuller code example):
def sort_and_deliver_scores(dates)
# dates example: ["2016-01-01","2016-01-12","2016-01-05"]
dates.each do |dateString|
params = {}
params[:date] = dateString
so_far = 0.0
["mail","express","sun"].each do |paper|
# get all records that correspond to this newspaper
@dailyscores = MyModel
.pluck(:paper,:score, :date)
.select{|b| b[0]==paper}
# add up the scores in all records for each paper that day
today = @dailyscores.map{|c| c[1]}.inject(:+)
todaysScoresByPaper = (today/@dailyscores.size).round(1)
so_far += todaysScoresByPaper
params[paper.to_sym] = todaysScoresByPaper
end
params[:average] = (so_far / 3).round(1)
save_record_as_daily_score_object(params)
end
end
def save_record_as_daily_score_object(params)
ds = DailyScore.where(date: params[:date]).first_or_create!
ds.update!(params)
end
When I check using pry, the params are fine, with Float values stored in the hash, but for some reason, when I save the record, ONLY the :average field gets saved, and all others are nil.
UPDATE 2:
tasks.rake
task :seed_scores => :environment do
# "select_a_few_dates" sends a few dates as strings
sort_and_deliver_scores(Score.all.select_a_few_dates)
end
score.rb
def save_record_as_daily_score_object(params)
ds = DailyScore.where(date: params[:date]).first_or_create!
ds.update!(params)
binding.pry
end
PRY output:
[1] pry(main)> ds
=> #<DailyScore:0x0000010add5ff8
id: 3876,
mail: nil,
average: -3.4,
sun: nil,
express: nil,
date: nil,
created_at: 2016-05-15 09:17:55 UTC,
updated_at: 2016-05-15 12:45:50 UTC>
[2] pry(main)> params
=> {:date=>"2015-09-02",
:mail=>-0.6,
:express=>-0.1,
:sun=>-3.2,
:average=>-3.4}
It seems that creating a DailyScore object by dateString is not working, and for some reason, only the :average attribute is being saved.
You can use the ActiveRecord hash interface, which would look like this, using your array variable:
array.each do |field|
thing[field.to_sym] = "I'll tell you later"
end
thing.save
Alternatively, you can use the params hash appraoch. Rails uses the params hash to perform a similar operation. You can simulate this functionality in this way:
array = ['title','date','height']
values = ['King Lear', '2016-05-13', 13.5]
attributes_hash = {}
array.map {|elem| elem.to_sym }.each_with_index do |field, i|
attributes_hash[field] = values[i]
end
thing.update(attributes_hash)
The benefit of this approach is that you can update an entire hash of values at one time. If you want to bypass validations and other checks, you can use update_attributes, instead.
For more information, see:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With