lockstep_rails 0.3.22 → 0.3.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,16 @@
1
- require "rubygems"
2
- require "bundler/setup"
3
- require "active_model"
4
- require "erb"
5
- require "dry-types"
6
- require "json"
7
- require "active_support/hash_with_indifferent_access"
8
- require "lockstep/query"
9
- require "lockstep/query_methods"
10
- require "lockstep/error"
11
- require "lockstep/exceptions"
12
- require "lockstep/relation_array"
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'active_model'
4
+ require 'erb'
5
+ require 'dry-types'
6
+ require 'json'
7
+ require 'active_support/hash_with_indifferent_access'
8
+ require 'lockstep/query'
9
+ require 'lockstep/query_methods'
10
+ require 'lockstep/error'
11
+ require 'lockstep/exceptions'
12
+ require 'lockstep/relation_array'
13
+ require 'pry'
13
14
 
14
15
  module Lockstep
15
16
  class ApiRecord
@@ -42,7 +43,7 @@ module Lockstep
42
43
  # @params [Hash], [Boolean] a `Hash` of attributes and a `Boolean` that should be false only if the object already exists
43
44
  # @return [Lockstep::ApiRecord] an object that subclasses `Parseresource::Base`
44
45
  def initialize(attributes = {}, new = true)
45
- #attributes = HashWithIndifferentAccess.new(attributes)
46
+ # attributes = HashWithIndifferentAccess.new(attributes)
46
47
 
47
48
  if new
48
49
  @unsaved_attributes = attributes
@@ -85,7 +86,7 @@ module Lockstep
85
86
  fname = fname.to_sym
86
87
  class_eval do
87
88
  define_method(fname) do
88
- val = get_attribute("#{fname}")
89
+ val = get_attribute(fname.to_s)
89
90
 
90
91
  # If enum, substitute with the enum key
91
92
  if val.present? && (enum = enum_config[fname]).present?
@@ -95,10 +96,10 @@ module Lockstep
95
96
  val
96
97
  end
97
98
  end
98
- unless self.respond_to? "#{fname}="
99
+ unless respond_to? "#{fname}="
99
100
  class_eval do
100
101
  define_method("#{fname}=") do |val|
101
- set_attribute("#{fname}", val)
102
+ set_attribute(fname.to_s, val)
102
103
 
103
104
  val
104
105
  end
@@ -125,7 +126,7 @@ module Lockstep
125
126
  def self.belongs_to(parent, config = {})
126
127
  config = config.with_indifferent_access
127
128
  class_name = config[:class_name]
128
- raise "Class name cannot be empty in #{parent}: #{self.name}" if class_name.blank?
129
+ raise "Class name cannot be empty in #{parent}: #{name}" if class_name.blank?
129
130
 
130
131
  included = config[:included] || false
131
132
  primary_key = config[:primary_key]
@@ -139,7 +140,7 @@ module Lockstep
139
140
  belongs_to_relations[parent] = {
140
141
  name: parent, class_name: class_name,
141
142
  included: included, primary_key: primary_key, foreign_key: foreign_key,
142
- loader: loader, polymorphic: polymorphic,
143
+ loader: loader, polymorphic: polymorphic
143
144
  }
144
145
 
145
146
  # define_method("build_#{parent}") do |attributes_hash|
@@ -156,7 +157,7 @@ module Lockstep
156
157
  def self.has_many(parent, config = {})
157
158
  config = config.with_indifferent_access
158
159
  class_name = config[:class_name]
159
- raise "Class name cannot be empty in #{parent}: #{self.name}" if class_name.blank?
160
+ raise "Class name cannot be empty in #{parent}: #{name}" if class_name.blank?
160
161
 
161
162
  included = config[:included] || false
162
163
  primary_key = config[:primary_key]
@@ -164,13 +165,13 @@ module Lockstep
164
165
  polymorphic = config[:polymorphic]
165
166
  loader = config[:loader]
166
167
 
167
- primary_key ||= self.id_ref
168
- foreign_key ||= self.id_ref
168
+ primary_key ||= id_ref
169
+ foreign_key ||= id_ref
169
170
  field(parent)
170
171
  has_many_relations[parent] = {
171
172
  name: parent, class_name: class_name, included: included,
172
173
  primary_key: primary_key, foreign_key: foreign_key, polymorphic: polymorphic,
173
- loader: loader,
174
+ loader: loader
174
175
  }
175
176
  end
176
177
 
@@ -182,46 +183,48 @@ module Lockstep
182
183
  schema.belongs_to_relations.each do |relation, config|
183
184
  params = {}
184
185
  config.except(:name).each { |k, v| params[k.to_sym] = v }
185
- self.belongs_to(relation, params)
186
+ belongs_to(relation, params)
186
187
  end
187
188
 
188
189
  schema.has_many_relations.each do |relation, config|
189
190
  params = {}
190
191
  config.except(:name).each { |k, v| params[k.to_sym] = v }
191
- self.has_many(relation, params)
192
+ has_many(relation, params)
192
193
  end
193
194
  end
194
195
 
195
196
  def to_pointer
196
197
  klass_name = self.class.model_name.to_s
197
- { "__type" => "Pointer", "className" => klass_name.to_s, self.id_ref => self.id }
198
+ { '__type' => 'Pointer', 'className' => klass_name.to_s, id_ref => id }
198
199
  end
199
200
 
200
201
  def self.to_date_object(date)
201
202
  date = date.to_time if date.respond_to?(:to_time)
202
- { "__type" => "Date", "iso" => date.getutc.iso8601 } if date && (date.is_a?(Date) || date.is_a?(DateTime) || date.is_a?(Time))
203
+ if date && (date.is_a?(Date) || date.is_a?(DateTime) || date.is_a?(Time))
204
+ date.getutc.iso8601(fraction_digits = 3)
205
+ end
203
206
  end
204
207
 
205
208
  # Creates setter methods for model fields
206
- def create_setters!(k, v)
207
- unless self.respond_to? "#{k}="
209
+ def create_setters!(k, _v)
210
+ unless respond_to? "#{k}="
208
211
  self.class.send(:define_method, "#{k}=") do |val|
209
- set_attribute("#{k}", val)
212
+ set_attribute(k.to_s, val)
210
213
 
211
214
  val
212
215
  end
213
216
  end
214
217
  end
215
218
 
216
- def method_missing(method, *args, &block)
217
- raise StandardError.new("#{method} has not been defined for #{self.class.name}")
219
+ def method_missing(method, *_args)
220
+ raise StandardError, "#{method} has not been defined for #{self.class.name}"
218
221
  # super
219
222
  end
220
223
 
221
224
  def self.method_missing(method_name, *args)
222
225
  method_name = method_name.to_s
223
- if method_name.start_with?("find_by_")
224
- attrib = method_name.gsub(/^find_by_/, "")
226
+ if method_name.start_with?('find_by_')
227
+ attrib = method_name.gsub(/^find_by_/, '')
225
228
  finder_name = "find_all_by_#{attrib}"
226
229
 
227
230
  define_singleton_method(finder_name) do |target_value|
@@ -229,8 +232,8 @@ module Lockstep
229
232
  end
230
233
 
231
234
  send(finder_name, args[0])
232
- elsif method_name.start_with?("find_all_by_")
233
- attrib = method_name.gsub(/^find_all_by_/, "")
235
+ elsif method_name.start_with?('find_all_by_')
236
+ attrib = method_name.gsub(/^find_all_by_/, '')
234
237
  finder_name = "find_all_by_#{attrib}"
235
238
 
236
239
  define_singleton_method(finder_name) do |target_value|
@@ -244,10 +247,10 @@ module Lockstep
244
247
  end
245
248
 
246
249
  # Creates getter methods for model fields
247
- def create_getters!(k, v)
248
- unless self.respond_to? "#{k}"
249
- self.class.send(:define_method, "#{k}") do
250
- get_attribute("#{k}")
250
+ def create_getters!(k, _v)
251
+ unless respond_to? k.to_s
252
+ self.class.send(:define_method, k.to_s) do
253
+ get_attribute(k.to_s)
251
254
  end
252
255
  end
253
256
  end
@@ -283,19 +286,19 @@ module Lockstep
283
286
  # end
284
287
  # end
285
288
 
286
- def self.id_ref=(val)
287
- @id_ref = val
289
+ class << self
290
+ attr_writer :id_ref
288
291
  end
289
292
 
290
293
  def self.id_ref
291
- raise StandardError.new("id_ref has not been defined for #{self.name}") if @id_ref.blank?
294
+ raise StandardError, "id_ref has not been defined for #{name}" if @id_ref.blank?
292
295
 
293
296
  @id_ref
294
297
  end
295
298
 
296
299
  # Alias for id_ref. Used by polymorphic association
297
300
  def self.primary_key
298
- self.id_ref
301
+ id_ref
299
302
  end
300
303
 
301
304
  def id_ref
@@ -308,8 +311,8 @@ module Lockstep
308
311
  @model_name_uri
309
312
  end
310
313
 
311
- def self.model_name_uri
312
- @model_name_uri
314
+ class << self
315
+ attr_reader :model_name_uri
313
316
  end
314
317
 
315
318
  def self.config
@@ -318,13 +321,16 @@ module Lockstep
318
321
 
319
322
  # Gets the current class's Lockstep.io base_uri
320
323
  def self.model_base_uri
321
- raise StandardError.new("Cannot establish connection for auto-generated Schema. Create a new model if you want to retrieve data from Lockstep Platform") if self.name.starts_with?("Schema::")
322
- raise StandardError.new("URL Path is not defined for #{self.name}") if model_name_uri.blank?
324
+ if name.starts_with?('Schema::')
325
+ raise StandardError,
326
+ 'Cannot establish connection for auto-generated Schema. Create a new model if you want to retrieve data from Lockstep Platform'
327
+ end
328
+ raise StandardError, "URL Path is not defined for #{name}" if model_name_uri.blank?
323
329
 
324
330
  base_url = config[:base_url]
325
- base_url += "/" unless base_url.ends_with?("/")
331
+ base_url += '/' unless base_url.ends_with?('/')
326
332
  base_url += model_name_uri
327
- base_url += "/" unless base_url.ends_with?("/")
333
+ base_url += '/' unless base_url.ends_with?('/')
328
334
  base_url
329
335
  end
330
336
 
@@ -339,19 +345,19 @@ module Lockstep
339
345
  def self.resource
340
346
  # load_settings
341
347
 
342
- #refactor to settings['app_id'] etc
348
+ # refactor to settings['app_id'] etc
343
349
  # app_id = @@settings['app_id']
344
350
  # master_key = @@settings['master_key']
345
351
  # RestClient::Resource.new(self.model_base_uri, app_id, master_key)
346
- Lockstep::Client.new(self.model_base_uri)
352
+ Lockstep::Client.new(model_base_uri)
347
353
  end
348
354
 
349
- def self.query_path=(value)
350
- @query_path = value
355
+ class << self
356
+ attr_writer :query_path
351
357
  end
352
358
 
353
359
  def self.query_path
354
- @query_path || "query"
360
+ @query_path || 'query'
355
361
  end
356
362
 
357
363
  # Batch requests
@@ -396,6 +402,7 @@ module Lockstep
396
402
  def self.merge_all_attributes(objects, response)
397
403
  objects.each_with_index do |item, index|
398
404
  next unless response[index]
405
+
399
406
  new_attributes = response[index].transform_keys { |key| key.underscore }
400
407
  item.merge_attributes(new_attributes)
401
408
  end
@@ -417,7 +424,7 @@ module Lockstep
417
424
  # end
418
425
 
419
426
  def self.bulk_import(new_objects, slice_size = 20)
420
- return true if new_objects.blank?
427
+ return [] if new_objects.blank?
421
428
 
422
429
  # Batch saves seem to fail if they're too big. We'll slice it up into multiple posts if they are.
423
430
  new_objects.each_slice(slice_size) do |objects|
@@ -425,46 +432,41 @@ module Lockstep
425
432
  batch_json = []
426
433
 
427
434
  objects.each do |item|
428
- raise StandardError.new("Bulk Import cannot only create records at the moment. It cannot update records") unless item.new?
435
+ unless item.new?
436
+ raise StandardError,
437
+ 'Bulk Import cannot only create records at the moment. It cannot update records'
438
+ end
429
439
 
430
440
  batch_json << item.attributes_for_saving.transform_keys { |key| key.camelize(:lower) }
431
441
  end
432
442
 
433
- resp = self.resource.post("", body: batch_json)
434
- # TODO attach errors if resp code is 400
435
-
436
- if resp.code.to_s == "400"
443
+ resp = resource.post('', body: batch_json)
444
+ # TODO: attach errors if resp code is 400
445
+ if resp.code != '200'
437
446
  # Error format in JSON
438
447
  # "errors": {
439
448
  # "[0].EmailAddress": [
440
449
  # "The EmailAddress field is not a valid e-mail address."
441
450
  # ]
442
451
  # }
443
- error_response = JSON.parse(resp.body)
444
- errors = error_response["errors"]
445
- errors.each do |key, messages|
446
- splits = key.split(".")
447
- attribute = splits.last&.underscore
448
- # Remove the [] from the first split to get the position in integer
449
- position = splits.first[1..(splits.first.size - 2)].to_i
450
- messages.each do |message|
451
- new_objects[position].errors.add attribute, ": #{message}"
452
- end
452
+ if resp.code == '401'
453
+ raise Lockstep::Exceptions::UnauthorizedError, 'Unauthorized: Check your App ID & Master Key'
454
+ elsif resp.code == '400'
455
+ raise Lockstep::Exceptions::BadRequestError, JSON.parse(resp.body)
456
+ elsif resp.code == '404'
457
+ raise Lockstep::Exceptions::RecordNotFound, 'Resource not found in the Platfrom'
453
458
  end
454
- return false
455
- elsif resp.code.to_s != "200"
456
- return false
457
459
  end
458
460
 
459
461
  response = JSON.parse(resp.body)
460
- if response && response.is_a?(Array) && response.length == objects.length
461
- # return response.map { |item|
462
- # Lockstep::Contact.new(item.transform_keys { |key| key.underscore }, false)
463
- # }
464
- merge_all_attributes(objects, response)
465
- end
462
+ next unless response && response.is_a?(Array) && response.length == objects.length
463
+
464
+ # return response.map { |item|
465
+ # Lockstep::Contact.new(item.transform_keys { |key| key.underscore }, false)
466
+ # }
467
+ merge_all_attributes(objects, response)
466
468
  end
467
- true
469
+ new_objects
468
470
  end
469
471
 
470
472
  # def self.load_settings
@@ -516,8 +518,10 @@ module Lockstep
516
518
  # @return [Lockstep::ApiRecord] an object that subclasses Lockstep::ApiRecord.
517
519
  def self.find(id)
518
520
  raise Lockstep::Exceptions::RecordNotFound, "Couldn't find #{name} without an ID" if id.blank?
519
- record = where(self.id_ref => id).first
521
+
522
+ record = where(id_ref => id).first
520
523
  raise Lockstep::Exceptions::RecordNotFound, "Couldn't find #{name} with id: #{id}" if record.blank?
524
+
521
525
  record
522
526
  end
523
527
 
@@ -525,13 +529,13 @@ module Lockstep
525
529
  #
526
530
  def self.find_by(*args)
527
531
  raise Lockstep::Exceptions::RecordNotFound, "Couldn't find an object without arguments" if args.blank?
532
+
528
533
  key, value = args.first.first
529
534
  unless valid_attribute?(key, raise_exception: true)
530
- raise StandardError.new("Attribute '#{key}' has not been defined for #{self.name}")
535
+ raise StandardError, "Attribute '#{key}' has not been defined for #{name}"
531
536
  end
532
537
 
533
- record = where(key => value).first
534
- record
538
+ where(key => value).first
535
539
  end
536
540
 
537
541
  # Find a Lockstep::ApiRecord object by chaining #where method calls.
@@ -576,19 +580,17 @@ module Lockstep
576
580
  # Valid only if the record is not an API record.
577
581
  # Default scopes build queries using ApiRecord to avoid conflicts. In this case, the query results in an
578
582
  # exception as the fields wouldn't have been defined in the ApiRecord
579
- return true if self.name == "Lockstep::ApiRecord"
583
+ return true if name == 'Lockstep::ApiRecord'
580
584
 
581
585
  attr = key.to_s
582
586
  Lockstep::Query::PREDICATES.keys.each do |predicate|
583
587
  if attr.end_with?(predicate)
584
- attr = attr.gsub(predicate, "")
588
+ attr = attr.gsub(predicate, '')
585
589
  break
586
590
  end
587
591
  end
588
592
  valid = schema.has_key?(attr)
589
- if raise_exception && !valid
590
- raise StandardError.new("Attribute '#{attr}' has not been defined for #{self.name}")
591
- end
593
+ raise StandardError, "Attribute '#{attr}' has not been defined for #{name}" if raise_exception && !valid
592
594
 
593
595
  valid
594
596
  end
@@ -613,19 +615,19 @@ module Lockstep
613
615
  # create RESTful resource for the specific Parse object
614
616
  # sends requests to [base_uri]/[classname]/[objectId]
615
617
  def instance_resource
616
- self.class.resource["#{self.id}"]
618
+ self.class.resource[id.to_s]
617
619
  end
618
620
 
619
621
  def pointerize(hash)
620
622
  new_hash = {}
621
623
  hash.each do |k, v|
622
- if v.respond_to?(:to_pointer)
623
- new_hash[k] = v.to_pointer
624
- elsif v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime)
625
- new_hash[k] = self.class.to_date_object(v)
626
- else
627
- new_hash[k] = v
628
- end
624
+ new_hash[k] = if v.respond_to?(:to_pointer)
625
+ v.to_pointer
626
+ elsif v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime)
627
+ self.class.to_date_object(v)
628
+ else
629
+ v
630
+ end
629
631
  end
630
632
  new_hash
631
633
  end
@@ -642,13 +644,13 @@ module Lockstep
642
644
  else
643
645
  false
644
646
  end
645
- rescue
647
+ rescue StandardError
646
648
  false
647
649
  end
648
650
 
649
651
  def create
650
652
  attrs = attributes_for_saving.transform_keys { |key| key.camelize(:lower) }
651
- resp = self.resource.post("", body: [attrs])
653
+ resp = resource.post('', body: [attrs])
652
654
  result = post_result(resp)
653
655
  end
654
656
 
@@ -659,7 +661,7 @@ module Lockstep
659
661
  # put_attrs = attributes_for_saving.to_json
660
662
 
661
663
  attrs = attributes_for_saving.transform_keys { |key| key.camelize(:lower) }
662
- resp = self.resource.patch(self.id, body: attrs)
664
+ resp = resource.patch(id, body: attrs)
663
665
  result = post_result(resp)
664
666
  end
665
667
 
@@ -681,40 +683,40 @@ module Lockstep
681
683
  # the object nor the relations it contains. Make another request here.
682
684
  # TODO: @@has_many_relations structure has been changed from array to hash, need to evaluate the impact here
683
685
  if has_many_relations.keys.map { |relation| relation.to_s.to_sym }
684
- #todo: make this a little smarter by checking if there are any Pointer objects in the objects attributes.
686
+ # TODO: make this a little smarter by checking if there are any Pointer objects in the objects attributes.
685
687
  # @attributes = self.class.to_s.constantize.where(:objectId => @attributes[self.id_ref]).first.attributes
686
- @attributes = self.class.to_s.constantize.where(self.id_ref => @attributes[self.id_ref]).first.attributes
688
+ @attributes = self.class.to_s.constantize.where(id_ref => @attributes[id_ref]).first.attributes
687
689
  end
688
690
  end
689
691
 
690
692
  def post_result(resp)
691
- if resp.code.to_s == "200" || resp.code.to_s == "201"
693
+ if resp.code.to_s == '200' || resp.code.to_s == '201'
692
694
  body = JSON.parse(resp.body)
693
695
  # Create method always responds with an array, whereas update responds with the object
694
696
  body = body.first if body.is_a?(Array)
695
697
 
696
698
  merge_attributes(body)
697
699
 
698
- return true
699
- elsif resp.code.to_s == "400"
700
+ true
701
+ elsif resp.code.to_s == '400'
700
702
  error_response = JSON.parse(resp.body)
701
- errors = error_response["errors"]
703
+ errors = error_response['errors']
702
704
  errors.each do |key, messages|
703
- attribute = key.split(".").last&.underscore
705
+ attribute = key.split('.').last&.underscore
704
706
  messages.each do |message|
705
707
  self.errors.add attribute, ": #{message}"
706
708
  end
707
709
  end
708
710
  else
709
711
  error_response = JSON.parse(resp.body)
710
- if error_response["error"]
711
- pe = LockstepError.new(error_response["code"], error_response["error"])
712
- else
713
- pe = LockstepError.new(resp.code.to_s)
714
- end
712
+ pe = if error_response['error']
713
+ LockstepError.new(error_response['code'], error_response['error'])
714
+ else
715
+ LockstepError.new(resp.code.to_s)
716
+ end
715
717
  self.errors.add(pe.code.to_s.to_sym, pe.msg)
716
- self.error_instances << pe
717
- return false
718
+ error_instances << pe
719
+ false
718
720
  end
719
721
  end
720
722
 
@@ -724,9 +726,9 @@ module Lockstep
724
726
 
725
727
  put_attrs = relations_for_saving(put_attrs)
726
728
 
727
- put_attrs.delete(self.id_ref)
728
- put_attrs.delete("created")
729
- put_attrs.delete("modified")
729
+ put_attrs.delete(id_ref)
730
+ put_attrs.delete('created')
731
+ put_attrs.delete('modified')
730
732
  put_attrs
731
733
  end
732
734
 
@@ -734,25 +736,28 @@ module Lockstep
734
736
  all_add_item_queries = {}
735
737
  all_remove_item_queries = {}
736
738
  @unsaved_attributes.each_pair do |key, value|
737
- next if !value.is_a? Array
739
+ next unless value.is_a? Array
738
740
 
739
741
  # Go through the array in unsaved and check if they are in array in attributes (saved stuff)
740
742
  add_item_ops = []
741
743
  @unsaved_attributes[key].each do |item|
742
744
  found_item_in_saved = false
743
745
  @attributes[key].each do |item_in_saved|
744
- if !!(defined? item.attributes) && item.attributes[self.id_ref] == item_in_saved.attributes[self.id_ref]
746
+ if !!(defined? item.attributes) && item.attributes[id_ref] == item_in_saved.attributes[id_ref]
745
747
  found_item_in_saved = true
746
748
  end
747
749
  end
748
750
 
749
- if !found_item_in_saved && !!(defined? item.id)
750
- # need to send additem operation to parse
751
- put_attrs.delete(key) # arrays should not be sent along with REST to parse api
752
- add_item_ops << { "__type" => "Pointer", "className" => item.class.to_s, self.id_ref => item.id }
753
- end
751
+ next unless !found_item_in_saved && !!(defined? item.id)
752
+
753
+ # need to send additem operation to parse
754
+ put_attrs.delete(key) # arrays should not be sent along with REST to parse api
755
+ add_item_ops << { '__type' => 'Pointer', 'className' => item.class.to_s, id_ref => item.id }
756
+ end
757
+ unless add_item_ops.empty?
758
+ all_add_item_queries.merge!({ key => { '__op' => 'Add',
759
+ 'objects' => add_item_ops } })
754
760
  end
755
- all_add_item_queries.merge!({ key => { "__op" => "Add", "objects" => add_item_ops } }) if !add_item_ops.empty?
756
761
 
757
762
  # Go through saved and if it isn't in unsaved perform a removeitem operation
758
763
  remove_item_ops = []
@@ -760,28 +765,31 @@ module Lockstep
760
765
  @attributes[key].each do |item|
761
766
  found_item_in_unsaved = false
762
767
  @unsaved_attributes[key].each do |item_in_unsaved|
763
- if !!(defined? item.attributes) && item.attributes[self.id_ref] == item_in_unsaved.attributes[self.id_ref]
768
+ if !!(defined? item.attributes) && item.attributes[id_ref] == item_in_unsaved.attributes[id_ref]
764
769
  found_item_in_unsaved = true
765
770
  end
766
771
  end
767
772
 
768
773
  if !found_item_in_unsaved && !!(defined? item.id)
769
774
  # need to send removeitem operation to parse
770
- remove_item_ops << { "__type" => "Pointer", "className" => item.class.to_s, self.id_ref => item.id }
775
+ remove_item_ops << { '__type' => 'Pointer', 'className' => item.class.to_s, id_ref => item.id }
771
776
  end
772
777
  end
773
778
  end
774
- all_remove_item_queries.merge!({ key => { "__op" => "Remove", "objects" => remove_item_ops } }) if !remove_item_ops.empty?
779
+ unless remove_item_ops.empty?
780
+ all_remove_item_queries.merge!({ key => { '__op' => 'Remove',
781
+ 'objects' => remove_item_ops } })
782
+ end
775
783
  end
776
784
 
777
- # TODO figure out a more elegant way to get this working. the remove_item merge overwrites the add.
785
+ # TODO: figure out a more elegant way to get this working. the remove_item merge overwrites the add.
778
786
  # Use a seperate query to add objects to the relation.
779
- #if !all_add_item_queries.empty?
787
+ # if !all_add_item_queries.empty?
780
788
  # #result = self.instance_resource.put(all_add_item_queries.to_json, {:content_type => "application/json"}) do |resp, req, res, &block|
781
789
  # # return puts(resp, req, res, false, &block)
782
790
  # #end
783
791
  # puts result
784
- #end
792
+ # end
785
793
 
786
794
  put_attrs.merge!(all_add_item_queries) unless all_add_item_queries.empty?
787
795
  put_attrs.merge!(all_remove_item_queries) unless all_remove_item_queries.empty?
@@ -789,17 +797,17 @@ module Lockstep
789
797
  end
790
798
 
791
799
  def update_attributes(attributes = {})
792
- self.update(attributes)
800
+ update(attributes)
793
801
  end
794
802
 
795
803
  def update_attribute(key, value)
796
- send(key.to_s + "=", value)
804
+ send(key.to_s + '=', value)
797
805
  update
798
806
  end
799
807
 
800
808
  def destroy
801
- resp = self.resource.delete(self.id)
802
- if resp.code.to_s == "200"
809
+ resp = resource.delete(id)
810
+ if resp.code.to_s == '200'
803
811
  @attributes = {}
804
812
  @unsaved_attributes = {}
805
813
  return true
@@ -812,7 +820,7 @@ module Lockstep
812
820
 
813
821
  fresh_object = self.class.find(id)
814
822
  @attributes = {}
815
- @attributes.update(fresh_object.instance_variable_get("@attributes"))
823
+ @attributes.update(fresh_object.instance_variable_get('@attributes'))
816
824
  @unsaved_attributes = {}
817
825
 
818
826
  self
@@ -845,27 +853,30 @@ module Lockstep
845
853
  attrs = @unsaved_attributes[k.to_s] ? @unsaved_attributes : @attributes
846
854
  case attrs[k]
847
855
  when Hash
848
- klass_name = attrs[k]["className"]
849
- klass_name = "User" if klass_name == "_User"
850
- case attrs[k]["__type"]
851
- when "Pointer"
852
- result = klass_name.to_s.constantize.find(attrs[k][self.id_ref])
853
- when "Object"
856
+ klass_name = attrs[k]['className']
857
+ klass_name = 'User' if klass_name == '_User'
858
+ case attrs[k]['__type']
859
+ when 'Pointer'
860
+ result = klass_name.to_s.constantize.find(attrs[k][id_ref])
861
+ when 'Object'
854
862
  result = klass_name.to_s.constantize.new(attrs[k], false)
855
- when "Date"
856
- result = DateTime.parse(attrs[k]["iso"]).in_time_zone
857
- when "File"
858
- result = attrs[k]["url"]
859
- when "Relation"
860
- objects_related_to_self = klass_name.constantize.where("$relatedTo" => { "object" => { "__type" => "Pointer", "className" => self.class.to_s, self.id_ref => self.id }, "key" => k }).all
863
+ when 'Date'
864
+ result = DateTime.parse(attrs[k]['iso']).in_time_zone
865
+ when 'File'
866
+ result = attrs[k]['url']
867
+ when 'Relation'
868
+ objects_related_to_self = klass_name.constantize.where('$relatedTo' => {
869
+ 'object' => { '__type' => 'Pointer',
870
+ 'className' => self.class.to_s, id_ref => id }, 'key' => k
871
+ }).all
861
872
  attrs[k] = Lockstep::RelationArray.new self, objects_related_to_self, k, klass_name
862
873
  @unsaved_attributes[k] = Lockstep::RelationArray.new self, objects_related_to_self, k, klass_name
863
874
  result = @unsaved_attributes[k]
864
875
  end
865
876
  else
866
- # TODO changed from @@has_many_relations to @@has_many_relations.keys as we have changed the has_many_relations
877
+ # TODO: changed from @@has_many_relations to @@has_many_relations.keys as we have changed the has_many_relations
867
878
  # from array to hash to capture more data points. Not sure of the impact of this.
868
- #relation will assign itself if an array, this will add to unsave_attributes
879
+ # relation will assign itself if an array, this will add to unsave_attributes
869
880
  if has_many_relations.keys.index(k.to_s)
870
881
  if attrs[k].nil?
871
882
  # result = nil
@@ -883,7 +894,7 @@ module Lockstep
883
894
  result = @unsaved_attributes[k]
884
895
  end
885
896
  else
886
- result = attrs["#{k}"]
897
+ result = attrs[k.to_s]
887
898
  end
888
899
  end
889
900
  result
@@ -938,24 +949,28 @@ module Lockstep
938
949
  end
939
950
 
940
951
  def primary_key
941
- self.id_ref
952
+ id_ref
942
953
  end
943
954
 
944
955
  # aliasing for idiomatic Ruby
945
956
  def id
946
- get_attribute(self.id_ref) rescue nil
957
+ get_attribute(id_ref)
958
+ rescue StandardError
959
+ nil
947
960
  end
948
961
 
949
962
  def objectId
950
- get_attribute(self.id_ref) rescue nil
963
+ get_attribute(id_ref)
964
+ rescue StandardError
965
+ nil
951
966
  end
952
967
 
953
968
  def created_at
954
- get_attribute("created")
969
+ get_attribute('created')
955
970
  end
956
971
 
957
972
  def updated_at
958
- get_attribute("modified")
973
+ get_attribute('modified')
959
974
  end
960
975
 
961
976
  def self.included(base)
@@ -965,10 +980,10 @@ module Lockstep
965
980
  module ClassMethods
966
981
  end
967
982
 
968
- #if we are comparing objects, use id if they are both Lockstep::ApiRecord objects
969
- def ==(another_object)
970
- if another_object.class <= Lockstep::ApiRecord
971
- self.id == another_object.id
983
+ # if we are comparing objects, use id if they are both Lockstep::ApiRecord objects
984
+ def ==(other)
985
+ if other.class <= Lockstep::ApiRecord
986
+ id == other.id
972
987
  else
973
988
  super
974
989
  end
@@ -989,12 +1004,14 @@ module Lockstep
989
1004
  val = relation_config[:loader].call(self)
990
1005
  else
991
1006
  return val unless relation_config[:foreign_key].present? and relation_config[:primary_key].present?
1007
+
992
1008
  relation_klass = relation_config[:class_name].constantize
993
1009
  return val unless relation_klass.model_name_uri.present?
994
1010
 
995
- query = { relation_config[:foreign_key] => self.send(relation_config[:primary_key]) }
1011
+ query = { relation_config[:foreign_key] => send(relation_config[:primary_key]) }
996
1012
  if relation_config[:polymorphic]
997
- polymorphic_config = Lockstep::RelationArray.has_many_polymorphic_attributes(self, relation_config[:polymorphic])
1013
+ polymorphic_config = Lockstep::RelationArray.has_many_polymorphic_attributes(self,
1014
+ relation_config[:polymorphic])
998
1015
  query.merge!(polymorphic_config)
999
1016
  end
1000
1017
  related_objects = relation_klass.send(:where, query).execute
@@ -1005,7 +1022,8 @@ module Lockstep
1005
1022
  if relation_config[:loader].present?
1006
1023
  val = relation_config[:loader].call(self)
1007
1024
  else
1008
- val = relation_config[:class_name].constantize.send(:find_by, relation_config[:primary_key] => self.send(relation_config[:foreign_key]))
1025
+ val = relation_config[:class_name].constantize.send(:find_by,
1026
+ relation_config[:primary_key] => send(relation_config[:foreign_key]))
1009
1027
  end
1010
1028
  end
1011
1029
 
@@ -1060,7 +1078,7 @@ module Lockstep
1060
1078
  elsif values.is_a?(Hash)
1061
1079
  value_map = values.with_indifferent_access
1062
1080
  else
1063
- raise StandardError.new("Invalid values for enum #{attribute}")
1081
+ raise StandardError, "Invalid values for enum #{attribute}"
1064
1082
  end
1065
1083
 
1066
1084
  # Convert values to string if the value is symbol
@@ -1089,9 +1107,21 @@ module Lockstep
1089
1107
  value = get_attribute(attribute)
1090
1108
  next if value.nil?
1091
1109
 
1092
- unless values_map.values.include?(value)
1093
- errors.add attribute, "has an invalid value"
1094
- end
1110
+ errors.add attribute, 'has an invalid value' unless values_map.values.include?(value)
1111
+ end
1112
+ end
1113
+
1114
+ def self.single_record!
1115
+ define_singleton_method :record do
1116
+ resp = resource.get('')
1117
+
1118
+ return [] if %w(404).include?(resp.code.to_s)
1119
+ # TODO handle non 200 response code. Throwing an exception for now
1120
+ raise StandardError.new("#{resp.code} error while fetching: #{resp.body}") unless %w(201 200).include?(resp.code.to_s)
1121
+
1122
+ result = JSON.parse(resp.body)
1123
+ r = result.transform_keys { |key| key.underscore }
1124
+ model_name.to_s.constantize.new(r, false)
1095
1125
  end
1096
1126
  end
1097
1127
 
@@ -1111,7 +1141,7 @@ module Lockstep
1111
1141
  as_json(options).to_json
1112
1142
  end
1113
1143
 
1114
- def as_json(options = {})
1144
+ def as_json(_options = {})
1115
1145
  @attributes.merge(@unsaved_attributes).as_json
1116
1146
  end
1117
1147
  end