Module: ArSync

Defined in:
lib/ar_sync.rb,
lib/ar_sync/core.rb,
lib/ar_sync/rails.rb,
lib/ar_sync/config.rb,
lib/ar_sync/version.rb,
lib/generators/ar_sync/types/types_generator.rb,
lib/generators/ar_sync/install/install_generator.rb

Defined Under Namespace

Modules: ApiControllerConcern, ModelBase, Rails, StaticJsonConcern, TypeScript Classes: ApiNotFound, Collection, CollectionWithOrder, Config, InstallGenerator, SyncSchemaBase, TypesGenerator

Constant Summary collapse

VERSION =
'1.1.3'

Class Method Summary collapse

Class Method Details

.configObject



10
11
12
# File 'lib/ar_sync/config.rb', line 10

def self.config
  @config ||= Config.new :current_user, nil, nil
end

.configure {|config| ... } ⇒ Object

Yields:



14
15
16
# File 'lib/ar_sync/config.rb', line 14

def self.configure
  yield config
end

.on_notification(&block) ⇒ Object



12
13
14
# File 'lib/ar_sync/core.rb', line 12

def self.on_notification(&block)
  @sync_send_block = block
end

.serialize(record_or_records, query, user: nil) ⇒ Object



80
81
82
# File 'lib/ar_sync/core.rb', line 80

def self.serialize(record_or_records, query, user: nil)
  ArSerializer.serialize record_or_records, query, context: user, use: :sync
end

.signed_key(key, time) ⇒ Object



76
77
78
# File 'lib/ar_sync/core.rb', line 76

def self.signed_key(key, time)
  "#{key};#{time};#{Digest::SHA256.hexdigest("#{config.key_secret}#{key};#{time}")[0, 16]}"
end

.skip_notification?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/ar_sync/core.rb', line 26

def self.skip_notification?
  Thread.current[:ar_sync_skip_notification]
end

.sync_key(model, to_user = nil, signature: true) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ar_sync/core.rb', line 56

def self.sync_key(model, to_user = nil, signature: true)
  if model.is_a? ArSync::Collection
    key = [to_user&.id, model.klass.name, model.name].join '/'
  else
    key = [to_user&.id, model.class.name, model.id].join '/'
  end
  key = Digest::SHA256.hexdigest("#{config.key_secret}#{key}")[0, 32] if config.key_secret
  key = "#{config.key_prefix}#{key}" if config.key_prefix
  key = signature && config.key_expires_in ? signed_key(key, Time.now.to_i.to_s) : key
  key + ';/'
end

.sync_send(to:, action:, model:, path: nil, field: nil, to_user: nil) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ar_sync/core.rb', line 39

def self.sync_send(to:, action:, model:, path: nil, field: nil, to_user: nil)
  key = sync_key to, to_user, signature: false
  e = { action: action }
  e[:field] = field if field
  if model
    e[:class] = model.class.base_class.name
    e[:id] = model.id
  end
  event = ["#{key}#{path}", e]
  buffer = Thread.current[:ar_sync_compact_notifications]
  if buffer
    buffer << event
  else
    @sync_send_block&.call [event]
  end
end

.sync_serialize(target, user, query) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/ar_sync/core.rb', line 84

def self.sync_serialize(target, user, query)
  case target
  when ArSync::Collection, ArSync::ModelBase
    serialized = ArSerializer.serialize target, query, context: user, use: :sync
    return serialized if target.is_a? ArSync::ModelBase
    {
      _sync: { keys: [ArSync.sync_key(target), ArSync.sync_key(target, user)] },
      ordering: target.ordering,
      collection: serialized
    }
  when ActiveRecord::Relation, Array
    ArSync.serialize target.to_a, query, user: user
  when ArSerializer::Serializable
    ArSync.serialize target, query, user: user
  else
    target
  end
end

.validate_expiration(signed_key) ⇒ Object



68
69
70
71
72
73
74
# File 'lib/ar_sync/core.rb', line 68

def self.validate_expiration(signed_key)
  signed_key = signed_key.to_s
  return signed_key unless config.key_expires_in
  key, time, signature, other = signed_key.split ';', 4
  return unless signed_key(key, time) == [key, time, signature].join(';')
  [key, other].compact.join ';' if Time.now.to_i - time.to_i < config.key_expires_in
end

.with_compact_notificationObject



16
17
18
19
20
21
22
23
24
# File 'lib/ar_sync/core.rb', line 16

def self.with_compact_notification
  key = :ar_sync_compact_notifications
  Thread.current[key] = []
  yield
ensure
  events = Thread.current[key]
  Thread.current[key] = nil
  @sync_send_block&.call events if events.present?
end

.without_notificationObject



30
31
32
33
34
35
36
37
# File 'lib/ar_sync/core.rb', line 30

def self.without_notification
  key = :ar_sync_skip_notification
  flag_was = Thread.current[key]
  Thread.current[key] = true
  yield
ensure
  Thread.current[key] = flag_was
end