Class: Synced::Synchronizer

Inherits:
Object
  • Object
show all
Defined in:
lib/synced/synchronizer.rb

Defined Under Namespace

Classes: MissingAPIClient

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model_class, options = {}) ⇒ Synchronizer

Initializes a new Synchronizer

Parameters:

  • remote_objects (Array|NilClass)

    Array of objects to be synchronized with local database. Objects need to respond to at least :id message. If it’s nil, then synchronizer will fetch the remote objects on it’s own.

  • model_class (Class)

    ActiveRecord model class from which local objects will be created.

  • options (Hash) (defaults to: {})
  • api (BookingSync::API::Client)
    • API client to be used for fetching

    remote objects

Options Hash (options):

  • scope: (Symbol)

    Within this object scope local objects will be synchronized. By default it’s model_class.

  • id_key: (Symbol)

    attribute name under which remote object’s ID is stored, default is :synced_id.

  • synced_all_at_key: (Symbol)

    attribute name under which remote object’s sync time is stored, default is :synced_all_at

  • data_key: (Symbol)

    attribute name under which remote object’s data is stored.

  • local_attributes: (Array)

    Array of attributes in the remote object which will be mapped to local object attributes.

  • remove: (Boolean)

    If it’s true all local objects within current scope which are not present in the remote array will be destroyed. If only_updated is enabled, ids of objects to be deleted will be taken from the meta part. By default if cancel_at column is present, all missing local objects will be canceled with cancel_all, if it’s missing, all will be destroyed with destroy_all. You can also force method to remove local objects by passing it to remove: :mark_as_missing.

  • only_updated: (Boolean)

    If true requests to API will take advantage of updated_since param and fetch only created/changed/deleted remote objects

  • mapper: (Module)

    Module class which will be used for mapping remote objects attributes into local object attributes

  • globalized_attributes: (Array|Hash)

    A list of attributes which will be mapped with their translations.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/synced/synchronizer.rb', line 42

def initialize(model_class, options = {})
  @model_class           = model_class
  @scope                 = options[:scope]
  @id_key                = options[:id_key]
  @synced_all_at_key     = options[:synced_all_at_key]
  @data_key              = options[:data_key]
  @remove                = options[:remove]
  @only_updated          = options[:only_updated]
  @include               = options[:include]
  @local_attributes      = attributes_as_hash(options[:local_attributes])
  @api                   = options[:api]
  @mapper                = options[:mapper].respond_to?(:call) ?
                           options[:mapper].call : options[:mapper]
  @fields                = options[:fields]
  @remove                = options[:remove]
  @associations          = Array(options[:associations])
  @remote_objects        = Array(options[:remote]) unless options[:remote].nil?
  @request_performed     = false
  @globalized_attributes = attributes_as_hash(options[:globalized_attributes])
end

Instance Attribute Details

#id_keyObject (readonly)

Returns the value of attribute id_key.



5
6
7
# File 'lib/synced/synchronizer.rb', line 5

def id_key
  @id_key
end

Instance Method Details

#performObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/synced/synchronizer.rb', line 63

def perform
  instrument("perform.synced", model: @model_class) do
    relation_scope.transaction do
      instrument("remove_perform.synced", model: @model_class) do
        remove_relation.send(remove_strategy) if @remove
      end
      instrument("sync_perform.synced", model: @model_class) do
        remote_objects.map do |remote|
          remote.extend(@mapper) if @mapper
          local_object = local_object_by_remote_id(remote.id) || relation_scope.new
          local_object.attributes = default_attributes_mapping(remote)
          local_object.attributes = local_attributes_mapping(remote)
          if @globalized_attributes.present?
            local_object.attributes = globalized_attributes_mapping(remote,
              local_object.translations.translated_locales)
          end
          local_object.save! if local_object.changed?
          local_object.tap do |local_object|
            @associations.each do |association|
              klass = association.to_s.classify.constantize
              klass.synchronize(remote: remote[association], scope: local_object,
                remove: @remove)
            end
          end
        end
      end.tap do |local_objects|
        if updated_since_enabled? && @request_performed
          instrument("update_synced_all_at_perform.synced", model: @model_class) do
            relation_scope.update_all(@synced_all_at_key => Time.now)
          end
        end
      end
    end
  end
end