Module: ArSync::ModelBase::ClassMethods

Defined in:
lib/ar_sync/class_methods.rb

Defined Under Namespace

Modules: WriteHook

Instance Method Summary collapse

Instance Method Details

#_each_sync_child(&block) ⇒ Object



29
30
31
32
# File 'lib/ar_sync/class_methods.rb', line 29

def _each_sync_child(&block)
  _sync_children_info.each(&block)
  superclass._each_sync_child(&block) if superclass < ActiveRecord::Base
end

#_each_sync_parent(&block) ⇒ Object



24
25
26
27
# File 'lib/ar_sync/class_methods.rb', line 24

def _each_sync_parent(&block)
  _sync_parents_info.each { |parent, options| block.call(parent, **options) }
  superclass._each_sync_parent(&block) if superclass < ActiveRecord::Base
end

#_initialize_sync_callbacksObject



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/ar_sync/class_methods.rb', line 168

def _initialize_sync_callbacks
  return if defined? @_sync_callbacks_initialized
  @_sync_callbacks_initialized = true
  prepend WriteHook
  attr_reader :_sync_parents_info_before_mutation, :_sync_belongs_to_info_before_mutation, :_sync_watch_values_before_mutation

  _sync_define :id

  serializer_defaults namespace: :sync do |current_user|
    { _sync: _sync_field(current_user) }
  end

  after_initialize do
    @_initialized = true
  end

  before_destroy do
    @_sync_parents_info_before_mutation ||= _sync_current_parents_info
    @_sync_watch_values_before_mutation ||= _sync_current_watch_values
    @_sync_belongs_to_info_before_mutation ||= _sync_current_belongs_to_info
  end

  %i[create update destroy].each do |action|
    after_commit on: action do
      next if ArSync.skip_notification?
      self.class.default_scoped.scoping { _sync_notify action }
      @_sync_watch_values_before_mutation = nil
      @_sync_parents_info_before_mutation = nil
      @_sync_belongs_to_info_before_mutation = nil
    end
  end
end

#_sync_child_info(name) ⇒ Object



18
19
20
21
22
# File 'lib/ar_sync/class_methods.rb', line 18

def _sync_child_info(name)
  info = _sync_children_info[name]
  return info if info
  superclass._sync_child_info name if superclass < ActiveRecord::Base
end

#_sync_children_infoObject



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

def _sync_children_info
  @_sync_children_info ||= {}
end

#_sync_define(name, serializer_data_block: nil, **option, &data_block) ⇒ Object



131
132
133
134
135
# File 'lib/ar_sync/class_methods.rb', line 131

def _sync_define(name, serializer_data_block: nil, **option, &data_block)
  _initialize_sync_callbacks
  serializer_field name, **option, &(serializer_data_block || data_block) unless _serializer_field_info name
  serializer_field name, **option, namespace: :sync, &data_block
end

#_sync_has_many(name, direction: :asc, first: nil, last: nil, preload: nil, association: nil, **option, &data_block) ⇒ Object

Raises:

  • (ArgumentError)


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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ar_sync/class_methods.rb', line 64

def _sync_has_many(name, direction: :asc, first: nil, last: nil, preload: nil, association: nil, **option, &data_block)
  raise ArgumentError, 'direction not in [:asc, :desc]' unless %i[asc desc].include? direction
  raise ArgumentError, 'first and last cannot be both specified' if first && last
  raise ArgumentError, 'cannot use first or last with direction: :desc' if direction != :asc && !first && !last
  if data_block.nil? && preload.nil?
    association_name = association || name.to_s.underscore.to_sym
    order_option_from_params = lambda do |params|
      if first || last
        params_first = first && [first, params[:first]&.to_i].compact.min
        params_last = last && [last, params[:last]&.to_i].compact.min
        { direction: direction, first: params_first, last: params_last }
      else
        {
          first: params[:first]&.to_i,
          last: params[:last]&.to_i,
          order_by: params[:order_by],
          direction: params[:direction] || :asc
        }
      end
    end
    preload = lambda do |records, _context, **params|
      ArSerializer::Field.preload_association(
        self,
        records,
        association_name,
        **order_option_from_params.call(params)
      )
    end
    data_block = lambda do |preloaded, _context, **params|
      records = preloaded ? preloaded[id] || [] : __send__(name)
      next records unless first || last
      ArSync::CollectionWithOrder.new(
        records,
        **order_option_from_params.call(params)
      )
    end
    serializer_data_block = lambda do |preloaded, _context, **_params|
      preloaded ? preloaded[id] || [] : __send__(name)
    end
    if first
      params_type = { first?: :int }
    elsif last
      params_type = { last?: :int }
    else
      params_type = lambda do
        orderable_keys = reflect_on_association(association_name)&.klass&._serializer_orderable_field_keys || []
        orderable_keys &= [*option[:only]].map(&:to_s) if option[:only]
        orderable_keys -= [*option[:except]].map(&:to_s) if option[:except]
        orderable_keys |= ['id']
        order_by = orderable_keys.size == 1 ? orderable_keys.first : orderable_keys.sort
        { first?: :int, last?: :int, direction?: %w[asc desc], orderBy?: order_by }
      end
    end
  else
    params_type = {}
  end
  _sync_define(
    name,
    serializer_data_block: serializer_data_block,
    preload: preload,
    association: association,
    params_type: params_type,
    **option,
    &data_block
  )
end

#_sync_parents_infoObject



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

def _sync_parents_info
  @_sync_parents_info ||= []
end

#_sync_self?Boolean

Returns:

  • (Boolean)


4
5
6
7
8
# File 'lib/ar_sync/class_methods.rb', line 4

def _sync_self?
  return true if defined?(@_sync_self)

  superclass._sync_self? if superclass < ActiveRecord::Base
end

#sync_collection(name) ⇒ Object



42
43
44
# File 'lib/ar_sync/class_methods.rb', line 42

def sync_collection(name)
  ArSync::Collection.find self, name
end

#sync_define_collection(name, first: nil, last: nil, direction: :asc) ⇒ Object



137
138
139
140
141
# File 'lib/ar_sync/class_methods.rb', line 137

def sync_define_collection(name, first: nil, last: nil, direction: :asc)
  _initialize_sync_callbacks
  collection = ArSync::Collection.new self, name, first: first, last: last, direction: direction
  sync_parent collection, inverse_of: [self, name]
end

#sync_has_data(*names, **option, &data_block) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/ar_sync/class_methods.rb', line 46

def sync_has_data(*names, **option, &data_block)
  @_sync_self = true
  names.each do |name|
    _sync_children_info[name] = nil
    _sync_define name, **option, &data_block
  end
end

#sync_has_many(name, **option, &data_block) ⇒ Object



54
55
56
57
# File 'lib/ar_sync/class_methods.rb', line 54

def sync_has_many(name, **option, &data_block)
  _sync_children_info[name] = [:many, option, data_block]
  _sync_has_many name, **option, &data_block
end

#sync_has_one(name, **option, &data_block) ⇒ Object



59
60
61
62
# File 'lib/ar_sync/class_methods.rb', line 59

def sync_has_one(name, **option, &data_block)
  _sync_children_info[name] = [:one, option, data_block]
  _sync_define name, **option, &data_block
end

#sync_parent(parent, inverse_of:, only_to: nil, watch: nil) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/ar_sync/class_methods.rb', line 34

def sync_parent(parent, inverse_of:, only_to: nil, watch: nil)
  _initialize_sync_callbacks
  _sync_parents_info << [
    parent,
    { inverse_name: inverse_of, only_to: only_to, watch: watch }
  ]
end