【问题标题】:Dynamically updating ActiveRecord object attribute动态更新 ActiveRecord 对象属性
【发布时间】:2016-09-09 06:08:55
【问题描述】:

我想更新一个 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 检查时,参数很好,浮点值存储在哈希中,但由于某种原因,当我保存记录时,只有 :average 字段被保存,而所有其他字段都为零。

更新 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 属性。

【问题讨论】:

  • 你能发布你的 pry 输出吗?这可能很有启发性。
  • 完成。莫非是模型本身有问题?它是通过生成器创建的,然后像往常一样执行 padrino rake db:migrate。它是否可能以某种方式与环境变量有关?此代码在 rake 任务中执行。
  • @MichaelGaskill 我将 Pry 问题作为一个单独的问题重新发布,因为它并不真正属于这个问题的范围。
  • 在我发表评论大约 10 秒后,我才意识到是你。我确信我找到了与您遇到的类似问题的人。但是,唉,事实并非如此。

标签: ruby-on-rails activerecord


【解决方案1】:

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

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

thing.save

或者,您可以使用参数哈希方法。 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】:

这样就可以了:)

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

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

【讨论】:

  • 优秀:新方法信息+1。以前没见过,谢谢。
【解决方案3】:

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

array = ['title','date','height']
thing = Thing.new
array.each do |field|
   thing[field] = "I'll tell you later"
end
thing.save

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 2021-10-12
    • 2021-08-13
    • 2015-02-18
    • 2013-01-18
    • 1970-01-01
    • 2018-07-01
    • 2018-02-02
    相关资源
    最近更新 更多