2015-07-30 2 views
2

У меня есть модель Thing с атрибутом rating, который со временем изменится. Я хочу, чтобы узнать, что значение любого Thing.rating было на определенную дату.Есть ли лучший способ записывать значение атрибута каждый день?

Например, если @thing = Thing.first и @thing.rating был равен 5 13 января 2015 года, я хочу, чтобы иметь возможность вернуть это значение на любом будущем.

Одна идея у меня была в том, чтобы создать новую модель под названием ThingPast, которая belong_to Thing и Thing бы have_many_of ThingPast. ThingPast будет иметь атрибуты thing_id, rating и date_created. Каждый день в определенное время задание Cron создает ThingPast для каждого Thing и просто копирует атрибут rating.

Я думаю, что это технически будет работать, но оно кажется излишне сложным и неэффективным. Кто-нибудь знает о лучшем, более простом способе добиться этого?

+0

Я думаю, что вы описали является наиболее логичным способом, Мне будет очень интересно услышать любые альтернативные предложения. Только один комментарий от меня состоял бы в том, чтобы, возможно, изменить имя от «ThingPast» до «ThingRating».Вы записываете значения настоящего, а также прошлое, и вы записываете «Рейтинги» для «Вещей», поэтому также может иметь очевидное имя, которое точно отражает это. Я думаю, что пока вы индексируете 'thing_id', вам будет хорошо с этим подходом. – Matt

ответ

2
  • Добавить ratings таблицу со столбцами rating, thing_id и created_at, а индекс на thing_id и created_at.
  • Удалить rating поле из Thing и заменить его

    has_many :ratings, order: 'created_at desc' 
    
  • Сохранить каждый новый или измененный рейтинг в качестве новой записи в таблице ratings, например, с обратным вызовом after_save.

  • Добавить метод Thing как:

    def rating_at(rating_time) 
        ratings.where("created_at <= ?", rating_time).first.try(:rating) 
    end 
    
  • И заменить недостающее поле:

    def rating 
        ratings.first.try(:rating) 
    end 
    

Теперь, если вы хотите ежедневные рейтинги вы можете перебирать даты и вызова rating_at для каждого:

(1..10).map { |days_ago| thing.rating_at(days_ago.days.ago) }.sort 

Не требуется работа cron.

+0

Это лучшее решение, потому что, если вы действительно в этом уверены, 'рейтинг' всегда ассоциируется с датой (временем), а' thing' может иметь несколько «оценок» за время. – sameera207

1

Вы можете использовать paper_trail gem https://github.com/airblade/paper_trail; он сохраняет версии вашей модели. Он хранит все версии моделей, которые вы выбираете в таблице versions с полиморфным отношением к вашим моделям.

Вы можете получить суточную версию вы хотите, запрашивая таблицу версий

PaperTrail::Version.where(item: Thing.first, created_at: Date.yesterday) 

, который получит Вас версии модели на эту дату

+0

Знаете ли вы, что если использование этого драгоценного камня будет использовать более или менее базу данных памяти, чем создание нового набора объектов каждый день? –

+0

Этот камень создаст новую таблицу базы данных 'versions' и добавит к ней новую запись всякий раз, когда модель изменится. Поэтому я думаю, что это то же самое, что создавать новые объекты каждый день только более общее решение – bigsolom

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