动态更新ActiveRecord对象属性

时间:2016-05-13 07:03:28

标签: ruby-on-rails 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检查时,params很好,Float值存储在hash中,但出于某种原因,当我保存记录时,只有: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
=> #<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}

似乎按dateString创建DailyScore对象不起作用,并且出于某种原因,只保存:average属性。

3 个答案:

答案 0 :(得分:3)

这样可以解决问题:)

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

send调用由符号定义的方法或(就我们的情况而言)字符串。

答案 1 :(得分:2)

您可以使用您的数组变量使用ActiveRecord哈希界面,如下所示:

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

thing.save

或者,您可以使用params hash appraoch。 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。

有关详细信息,请参阅:

答案 2 :(得分:1)

您可以像下面的代码一样更新

scrollLocations.ContentSize = new System.Drawing.SizeF((float)contentView2.Bounds.Width, 
                              (float)contentView2.Bounds.Height);
scrollLocations.Frame = View.Bounds;