2016-05-13 4 views
1

Я хочу обновить объект AR, используя имя атрибута, к которому я обращаюсь из другого источника (в реальных данных есть много).Динамическое обновление атрибута объекта ActiveRecord

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 

UPDATE (с кодом, например более полное):

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 

Когда я проверяю с помощью Поддеть, что PARAMS прекрасно, со значениями Float сохраненный в хеше, но по какой-то причине, когда я сохраняю запись, ТОЛЬКО: среднее поле сохраняется, а все остальные - ноль.

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} 

кажется, что создание объекта DailyScore по DateString не работает, а по какой-то причине, только средний атрибут сохраняется.

+0

Вы можете разместить свой выход подглядывать? Это может быть откровенно. –

+0

Готово. Может ли быть ошибка в самой модели? Он был создан с помощью генератора, а затем сделал padrino rake db: мигрировать, как обычно. Возможно ли, что это связано с переменной окружения каким-то образом?Этот код выполняется внутри задачи rake. –

+0

@MichaelGaskill Я переписал проблему Pry как отдельный вопрос, так как он действительно не подпадает под действие этой. –

ответ

2

Вы можете использовать хэш-интерфейс ActiveRecord, который будет выглядеть следующим образом, используя переменный массив:

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

thing.save 

В качестве альтернативы, вы можете использовать Params хэша 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.

Для получения дополнительной информации см:

+0

Спасибо за это, но он не работает для меня, я не понимаю, почему. Я добавлю свой код полностью к вопросу, возможно, ошибка в другом месте. –

1

вы можете обновить это как ниже код

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

это будет делать трюк :)

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

send вызывает метод, определенный символ или (как в нашем случае) строка.

+0

Отлично: +1 для новой информации о методе. Не видели этого раньше, спасибо. –

Смежные вопросы