动态更新ActiveRecord对象属性

11 浏览
0 Comments

动态更新ActiveRecord对象属性

我想使用从另一个来源访问的属性名称更新AR对象(在实际数据中有很多)。

class DailyScore < ActiveRecord::Base
    attr_accessor :mail, :date, :sun, :express, :average
end
array = ['mail','date','sun']
thing = DailyScore.new

我该如何将数组中的每个项转换为符号,并相应地更新记录?

理想情况下,我想要这样的东西:

array.each do |field|
    thing.field = 1.0 #Float
end

更新(带有更完整的代码示例):

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

当我使用Pry进行检查时,参数很好,Float值存储在哈希中,但由于某种原因,当我保存记录时,只有:average字段被保存,而其他所有字段都是nil。

更新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
=> #
[2] pry(main)> params
 => {:date=>"2015-09-02",
 :mail=>-0.6,
 :express=>-0.1,
 :sun=>-3.2,
 :average=>-3.4}

看来按dateString创建DailyScore对象不起作用,由于某种原因,只有:average属性被保存。

admin 更改状态以发布 2023年5月24日
0
0 Comments

这样就可以搞定啦 🙂

array = ['title', 'date', 'height']
thing = Thing.new
array.each do |field|
 thing.send("#{field}=", 'your value')
end
# save object or do whatever

send 调用由符号或字符串定义的方法(就像我们的例子)。

0
0 Comments

你可以使用ActiveRecord哈希接口,使用你的数组变量,看起来像这样:

array.each do |field|
  thing[field.to_sym] = "I'll tell you later"
end
thing.save

或者,你可以使用params哈希方法。Rails使用params哈希执行类似的操作。你可以以这种方式模拟这种功能:

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)

这种方法的好处是,你可以一次更新整个哈希值。如果你想绕过验证和其他检查,你可以使用update_attributes。

更多信息请参见:

0