Для нескольких типов задач необходимо иметь возможность получать последние изменения определенных данных. Например при реализации offline-first концепции нужно реплицировать данные между сервером и клиентом: есть несколько клиентов, они постоянно опрашивают/подключены через веб-сокет сервер на предмет изменений. Чтобы не слать каждый раз целиком все данные, нужно иметь возможность получить все изменения с последнего таймстемпа актуального для клиента. То есть:
- Клиент запросил индекс, получил список данных и таймстемп когда он их получил
- Клиент опрашивает - не изменилось ли чего на сервере
- Сервер проверяет все изменения по заданному скопу начиная с запрашиваемого клиентом таймстемпа
- Если что-то изменилось - он отсылает клиенту только те поля записей, которые изменились в формате json.
Diffit позволяет отслеживать такие изменения и генерирует из них ответ, содержащий только изменившиеся поля:
В настоящее время поддерживается только json
:
{
"timestamp": "2015-05-27 21:31:45 +0300",
"changes":
[
{
"model": "ModelName",
"record_id": 12,
"values": {
"column_name1": "new value",
"column_name2": "facebook",
},
},
{...}
]
}
- Добавть гем в
Gemfile
:
gem 'diffit'
- Создать миграцию для внутренних нужд Diffit (инициалайзер, таблица, функция в БД, индексы, правила):
rails generate diffit:install <имя таблицы, default: "diffit">
Инициалайзер config/initializers/diffit.rb
:
Diffit.setup do |config|
config.table_name = "diffits" # название таблицы с дифами
config.serializer = :json # сериалайзер ответа
config.timestamp_format = ->(timestamp) { timestamp.to_s } # формат возвращаемого таймстемпа
end
- Создаст миграцию с триггером на таблицу, которую хотим отслеживать:
rails generate diffit:table <таблица/модель>
- Добавить
diffit!
в отслеживаемую модель:
class User < ActiveRecord::Base
diffit!
end
User.where(login: 'Vlad').diff_from(1.day.ago)
# or
Diffit.diff_from(1.day.ago, resources: [User.all, Post.where(user_id: 1), Comments.last(10)])
# or
User.first.diff_from(1.day.ago)
bundle
rake db:migrate
rake