syncano 3.1.4 → 4.0.0.alpha

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.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -1
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +3 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +25 -1
  7. data/Guardfile +22 -4
  8. data/README.md +68 -447
  9. data/Rakefile +48 -5
  10. data/circle.yml +10 -0
  11. data/lib/active_attr/dirty.rb +3 -17
  12. data/lib/active_attr/typecasting/hash_typecaster.rb +34 -0
  13. data/lib/active_attr/typecasting_override.rb +29 -0
  14. data/lib/syncano.rb +53 -92
  15. data/lib/syncano/api.rb +13 -0
  16. data/lib/syncano/connection.rb +97 -0
  17. data/lib/syncano/model/associations.rb +121 -0
  18. data/lib/syncano/{active_record/association → model/associations}/base.rb +5 -5
  19. data/lib/syncano/{active_record/association → model/associations}/belongs_to.rb +6 -6
  20. data/lib/syncano/{active_record/association → model/associations}/has_many.rb +15 -9
  21. data/lib/syncano/{active_record/association → model/associations}/has_one.rb +4 -4
  22. data/lib/syncano/model/base.rb +257 -0
  23. data/lib/syncano/{active_record → model}/callbacks.rb +16 -13
  24. data/lib/syncano/{active_record → model}/scope_builder.rb +53 -69
  25. data/lib/syncano/query_builder.rb +19 -129
  26. data/lib/syncano/resources.rb +126 -0
  27. data/lib/syncano/resources/base.rb +304 -300
  28. data/lib/syncano/resources/collection.rb +19 -223
  29. data/lib/syncano/resources/space.rb +29 -0
  30. data/lib/syncano/schema.rb +86 -0
  31. data/lib/syncano/schema/attribute_definition.rb +83 -0
  32. data/lib/syncano/schema/resource_definition.rb +36 -0
  33. data/lib/syncano/scope.rb +10 -0
  34. data/lib/syncano/version.rb +3 -4
  35. data/spec/integration/syncano_spec.rb +228 -0
  36. data/spec/spec_helper.rb +15 -9
  37. data/spec/unit/api_spec.rb +5 -0
  38. data/spec/unit/connection_spec.rb +137 -0
  39. data/spec/unit/query_builder_spec.rb +75 -0
  40. data/spec/unit/resources/collection_spec.rb +36 -0
  41. data/spec/unit/resources/space_spec.rb +28 -0
  42. data/spec/unit/resources_base_spec.rb +185 -0
  43. data/spec/unit/schema/attribute_definition_spec.rb +18 -0
  44. data/spec/unit/schema/resource_definition_spec.rb +25 -0
  45. data/spec/unit/schema_spec.rb +3532 -0
  46. data/spec/unit/syncano_spec.rb +63 -0
  47. data/syncano.gemspec +8 -14
  48. metadata +85 -210
  49. data/lib/generators/syncano/install_generator.rb +0 -17
  50. data/lib/generators/syncano/templates/initializers/syncano.rb +0 -7
  51. data/lib/syncano/active_record/associations.rb +0 -112
  52. data/lib/syncano/active_record/base.rb +0 -318
  53. data/lib/syncano/batch_queue.rb +0 -58
  54. data/lib/syncano/batch_queue_element.rb +0 -33
  55. data/lib/syncano/clients/base.rb +0 -123
  56. data/lib/syncano/clients/rest.rb +0 -79
  57. data/lib/syncano/clients/sync.rb +0 -164
  58. data/lib/syncano/errors.rb +0 -17
  59. data/lib/syncano/jimson_client.rb +0 -66
  60. data/lib/syncano/packets/auth.rb +0 -27
  61. data/lib/syncano/packets/base.rb +0 -70
  62. data/lib/syncano/packets/call.rb +0 -34
  63. data/lib/syncano/packets/call_response.rb +0 -33
  64. data/lib/syncano/packets/error.rb +0 -19
  65. data/lib/syncano/packets/message.rb +0 -30
  66. data/lib/syncano/packets/notification.rb +0 -39
  67. data/lib/syncano/packets/ping.rb +0 -12
  68. data/lib/syncano/resources/admin.rb +0 -26
  69. data/lib/syncano/resources/api_key.rb +0 -108
  70. data/lib/syncano/resources/data_object.rb +0 -316
  71. data/lib/syncano/resources/folder.rb +0 -88
  72. data/lib/syncano/resources/notifications/base.rb +0 -103
  73. data/lib/syncano/resources/notifications/create.rb +0 -20
  74. data/lib/syncano/resources/notifications/destroy.rb +0 -20
  75. data/lib/syncano/resources/notifications/message.rb +0 -9
  76. data/lib/syncano/resources/notifications/update.rb +0 -24
  77. data/lib/syncano/resources/project.rb +0 -96
  78. data/lib/syncano/resources/role.rb +0 -11
  79. data/lib/syncano/resources/subscription.rb +0 -12
  80. data/lib/syncano/resources/user.rb +0 -65
  81. data/lib/syncano/response.rb +0 -22
  82. data/lib/syncano/sync_connection.rb +0 -133
  83. data/spec/admins_spec.rb +0 -16
  84. data/spec/api_keys_spec.rb +0 -34
  85. data/spec/collections_spec.rb +0 -67
  86. data/spec/data_objects_spec.rb +0 -113
  87. data/spec/folders_spec.rb +0 -39
  88. data/spec/notifications_spec.rb +0 -43
  89. data/spec/projects_spec.rb +0 -35
  90. data/spec/roles_spec.rb +0 -13
  91. data/spec/sync_resources_spec.rb +0 -35
  92. data/spec/syncano_spec.rb +0 -9
@@ -1,7 +1,7 @@
1
- require 'syncano/active_record/scope_builder'
1
+ require 'syncano/model/scope_builder'
2
2
 
3
- class Syncano
4
- module ActiveRecord
3
+ module Syncano
4
+ module Model
5
5
  # Module with associations functionality for Syncano::ActiveRecord
6
6
  module Association
7
7
  # Base class for all associations
@@ -9,10 +9,10 @@ class Syncano
9
9
  # Constructor for association
10
10
  # @param [Class] source_model
11
11
  # @param [Symbol] name
12
- def initialize(source_model, name)
12
+ def initialize(source_model, name, options = {})
13
13
  self.source_model = source_model
14
14
  self.associated_model = name.to_s.classify.constantize
15
- self.foreign_key = source_model.name.foreign_key
15
+ self.foreign_key = options[:foreign_key] || source_model.name.foreign_key
16
16
  end
17
17
 
18
18
  # Checks if association is belongs_to type
@@ -1,18 +1,18 @@
1
- require 'syncano/active_record/association/base'
1
+ require 'syncano/model/associations/base'
2
2
 
3
- class Syncano
4
- module ActiveRecord
3
+ module Syncano
4
+ module Model
5
5
  module Association
6
6
  # Class for belongs to association
7
- class BelongsTo < Syncano::ActiveRecord::Association::Base
7
+ class BelongsTo < Syncano::Model::Association::Base
8
8
  attr_reader :associated_model, :foreign_key, :source_model
9
9
 
10
10
  # Constructor for belongs_to association
11
11
  # @param [Class] source_model
12
12
  # @param [Symbol] name
13
- def initialize(source_model, name)
13
+ def initialize(source_model, name, options = {})
14
14
  super
15
- self.foreign_key = associated_model.name.foreign_key
15
+ self.foreign_key = options[:foreign_key] || associated_model.name.foreign_key
16
16
  end
17
17
 
18
18
  # Checks if association is belongs_to type
@@ -1,10 +1,10 @@
1
- require 'syncano/active_record/association/base'
1
+ require 'syncano/model/associations/base'
2
2
 
3
- class Syncano
4
- module ActiveRecord
3
+ module Syncano
4
+ module Model
5
5
  module Association
6
6
  # Class for has many association
7
- class HasMany < Syncano::ActiveRecord::Association::Base
7
+ class HasMany < Syncano::Model::Association::Base
8
8
  attr_reader :associated_model, :foreign_key, :source_model
9
9
 
10
10
  # Checks if association is has_many type
@@ -24,20 +24,26 @@ class Syncano
24
24
 
25
25
  # Builds new associated object
26
26
  # @return [Object]
27
- def build
28
- associated_model.new(foreign_key => source.id)
27
+ def build(attributes = {})
28
+ new(attributes)
29
+ end
30
+
31
+ def new(attributes = {})
32
+ associated_model.new(attributes.merge(foreign_key => source.id))
29
33
  end
30
34
 
31
35
  # Creates new associated object
32
36
  # @return [Object]
33
- def create
34
- associated_model.create(foreign_key => source.id)
37
+ def create(attributes = {})
38
+ associated_model.create(attributes.merge(foreign_key => source.id))
35
39
  end
36
40
 
37
41
  # Adds object to the related collection by setting foreign key
38
42
  # @param [Object] object
39
43
  # @return [Object]
40
44
  def <<(object)
45
+ "Object should be an instance of #{associated_model} class" unless object.is_a?(associated_model)
46
+
41
47
  object.send("#{foreign_key}=", source.id)
42
48
  object.save unless object.new_record?
43
49
  object
@@ -55,7 +61,7 @@ class Syncano
55
61
  # @param [String] name
56
62
  # @param [Array] args
57
63
  def method_missing(name, *args)
58
- scope_builder = Syncano::ActiveRecord::ScopeBuilder.new(associated_model).by_parent_id(source.id)
64
+ scope_builder = Syncano::Model::ScopeBuilder.new(associated_model).where("#{foreign_key} = ?", source.id)
59
65
 
60
66
  if scope_builder.respond_to?(name) || !source.scopes[name].nil?
61
67
  scope_builder.send(name, *args)
@@ -1,10 +1,10 @@
1
- require 'syncano/active_record/association/base'
1
+ require 'syncano/model/associations/base'
2
2
 
3
- class Syncano
4
- module ActiveRecord
3
+ module Syncano
4
+ module Model
5
5
  module Association
6
6
  # Class for has one association
7
- class HasOne < Syncano::ActiveRecord::Association::Base
7
+ class HasOne < Syncano::Model::Association::Base
8
8
  attr_reader :associated_model, :foreign_key, :source_model
9
9
 
10
10
  # Checks if association is has_one type
@@ -0,0 +1,257 @@
1
+ require 'syncano/model/scope_builder'
2
+ require 'syncano/model/associations'
3
+ require 'syncano/model/callbacks'
4
+
5
+ module Syncano
6
+ # Scope for modules and classes integrating ActiveRecord functionality
7
+ module Model
8
+ # Class for integrating ActiveRecord functionality
9
+ class Base
10
+ include ActiveAttr::Model
11
+ include ActiveAttr::Dirty
12
+
13
+ include ActiveModel::ForbiddenAttributesProtection
14
+ include Syncano::Model::Associations
15
+ include Syncano::Model::Callbacks
16
+
17
+ attribute :id, type: Integer
18
+ attribute :created_at, type: DateTime
19
+ attribute :updated_at, type: DateTime
20
+
21
+ # Constructor for model
22
+ # @param [Hash] params
23
+ def initialize(params = {})
24
+ if params.is_a?(Syncano::Resources::Object)
25
+ self.syncano_object = params
26
+ self.attributes = syncano_object_merged_attributes
27
+ mark_as_saved!
28
+ else
29
+ self.syncano_object = self.class.syncano_class.objects.new
30
+ self.attributes = params
31
+ end
32
+ end
33
+
34
+ # Gets collection with all objects
35
+ # @return [Array]
36
+ def self.all
37
+ scope_builder.all
38
+ end
39
+
40
+ # Returns first object or collection of first x objects
41
+ # @param [Integer] amount
42
+ # @return [Object, Array]
43
+ def self.first(amount = nil)
44
+ scope_builder.first(amount)
45
+ end
46
+
47
+ # Returns last object or collection of last x objects
48
+ # @param [Integer] amount
49
+ # @return [Object, Array]
50
+ def self.last(amount = nil)
51
+ scope_builder.last(amount)
52
+ end
53
+
54
+ # Returns scope builder with condition passed as arguments
55
+ # @param [String] condition
56
+ # @param [Array] params
57
+ # @return [Syncano::ActiveRecord::ScopeBuilder]
58
+ def self.where(condition, *params)
59
+ scope_builder.where(condition, *params)
60
+ end
61
+
62
+ # Returns scope builder with order passed as first argument
63
+ # @param [String] order
64
+ # @return [Syncano::ActiveRecord::ScopeBuilder]
65
+ def self.order(order)
66
+ scope_builder.order(order)
67
+ end
68
+
69
+ # Returns one object found by id
70
+ # @param [Integer] id
71
+ # @return [Object]
72
+ def self.find(id)
73
+ scope_builder.find(id)
74
+ end
75
+
76
+ def reload!
77
+ syncano_object.reload!
78
+ self.attributes = syncano_object_merged_attributes
79
+ mark_as_saved!
80
+ self
81
+ end
82
+
83
+ # Creates new object with specified attributes
84
+ # @param [Hash] attributes
85
+ # @return [Object]
86
+ def self.create(attributes)
87
+ new_object = self.new(attributes)
88
+ new_object.save
89
+ new_object
90
+ end
91
+
92
+ # Saves object in Syncano
93
+ # @return [TrueClass, FalseClass]
94
+ def save
95
+ if valid?
96
+ was_persisted = persisted?
97
+
98
+ process_callbacks(:before_save)
99
+ process_callbacks(was_persisted ? :before_update : :before_create)
100
+
101
+ syncano_object.custom_attributes = attributes_to_sync
102
+ syncano_object.save
103
+ self.attributes = syncano_object_merged_attributes
104
+ mark_as_saved!
105
+
106
+ process_callbacks(was_persisted ? :after_update : :after_create)
107
+ process_callbacks(:after_save)
108
+ end
109
+
110
+ saved?
111
+ end
112
+
113
+ def self.syncano_class
114
+ syncano_class
115
+ end
116
+
117
+ # Updates object with specified attributes
118
+ # @param [Hash] attributes
119
+ # @return [TrueClass, FalseClass]
120
+ def update_attributes(attributes)
121
+ self.attributes = attributes
122
+ self.save
123
+ end
124
+
125
+ # Returns scope builder with limit parameter set to parameter
126
+ # @param [Integer] amount
127
+ # @return [Syncano::ActiveRecord::ScopeBuilder]
128
+ def self.limit(amount)
129
+ scope_builder.limit(amount)
130
+ end
131
+
132
+ # Returns hash with scopes
133
+ # @return [HashWithIndifferentAccess]
134
+ def self.scopes
135
+ self._scopes ||= HashWithIndifferentAccess.new
136
+ end
137
+
138
+ # Overwritten equality operator
139
+ # @param [Object] object
140
+ # @return [TrueClass, FalseClass]
141
+ def ==(object)
142
+ self.class == object.class && id == object.id
143
+ end
144
+
145
+ # Performs validations
146
+ # @return [TrueClass, FalseClass]
147
+ def valid?
148
+ process_callbacks(:before_validation)
149
+ process_callbacks(:after_validation) if result = super
150
+ result
151
+ end
152
+
153
+ # Deletes object from Syncano
154
+ # @return [TrueClass, FalseClass]
155
+ def destroy
156
+ process_callbacks(:before_destroy)
157
+ syncano_object.destroy
158
+ process_callbacks(:after_destroy) if syncano_object.destroyed?
159
+ end
160
+
161
+ def destroyed?
162
+ syncano_object.destroyed?
163
+ end
164
+
165
+ # Checks if object has not been saved in Syncano yet
166
+ # @return [TrueClass, FalseClass]
167
+ def new_record?
168
+ !persisted?
169
+ end
170
+
171
+ # Checks if object has been already saved in Syncano
172
+ # @return [TrueClass, FalseClass]
173
+ def persisted?
174
+ !syncano_object.new_record?
175
+ end
176
+
177
+ def saved?
178
+ !new_record? && !changed?
179
+ end
180
+
181
+ private
182
+
183
+ class_attribute :syncano_class, :_scopes
184
+ attr_accessor :syncano_object
185
+
186
+ def mark_as_saved!
187
+ raise(Syncano::Error.new('primary key is blank')) if new_record?
188
+
189
+ @previously_changed = changes
190
+ @changed_attributes.clear
191
+ self
192
+ end
193
+
194
+ # Setter for scopes attribute
195
+ def self.scopes=(hash)
196
+ self._scopes = hash
197
+ end
198
+
199
+ # Returns scope builder for current model
200
+ # @return [Syncano::ActiveRecord::ScopeBuilder]
201
+ def self.scope_builder
202
+ Syncano::Model::ScopeBuilder.new(self)
203
+ end
204
+
205
+ # Defines model scope
206
+ # @param [Symbol] name
207
+ # @param [Proc] procedure
208
+ def self.scope(name, procedure)
209
+ scopes[name] = procedure
210
+ end
211
+
212
+ # Overwritten method_missing for handling calling defined scopes
213
+ # @param [String] name
214
+ # @param [Array] args
215
+ def self.method_missing(name, *args)
216
+ if scopes[name].nil?
217
+ super
218
+ else
219
+ scope_builder.send(name.to_sym, *args)
220
+ end
221
+ end
222
+
223
+ # Returns scope builder for specified class
224
+ # @return [Syncano::ActiveRecord::ScopeBuilder]
225
+ def scope_builder(object_class)
226
+ Syncano::Model::ScopeBuilder.new(object_class)
227
+ end
228
+
229
+ def attributes_to_sync
230
+ attributes_names = self.class.attributes_to_sync
231
+ attributes.select{ |name, value| attributes_names.include?(name.to_sym) }
232
+ end
233
+
234
+ def self.attributes_to_sync
235
+ syncano_class.schema.collect{ |attribute| attribute[:name].to_sym }
236
+ end
237
+
238
+ def syncano_object_merged_attributes
239
+ syncano_object.attributes.except(:custom_attributes).merge(syncano_object.custom_attributes)
240
+ end
241
+
242
+ def self.inherited(child_class)
243
+ # Load schema and generate attributes
244
+ child_class_name = child_class.name.demodulize.tableize.singularize
245
+ syncano_class = MODEL_SCHEMA.find{ |syncano_class| syncano_class.name == child_class_name }
246
+
247
+ syncano_class.schema.each do |attribute_schema|
248
+ attribute attribute_schema['name'], type: String
249
+ end
250
+
251
+ child_class.syncano_class = syncano_class
252
+
253
+ super
254
+ end
255
+ end
256
+ end
257
+ end
@@ -1,20 +1,9 @@
1
- class Syncano
2
- module ActiveRecord
1
+ module Syncano
2
+ module Model
3
3
  # Module with callbacks functionality for Syncano::ActiveRecord
4
4
  module Callbacks
5
5
  extend ActiveSupport::Concern
6
6
 
7
- included do
8
- # Defines chains for all types of callbacks
9
- [:validation, :save, :create, :update, :destroy].each do |action|
10
- [:before, :after].each do |type|
11
- chain_name = "#{type}_#{action}_callbacks"
12
- class_attribute chain_name
13
- send("#{chain_name}=", [])
14
- end
15
- end
16
- end
17
-
18
7
  # Class methods for Syncano::ActiveRecord::Callbacks module
19
8
  module ClassMethods
20
9
  private
@@ -30,6 +19,20 @@ class Syncano
30
19
  end
31
20
  end
32
21
  end
22
+
23
+ def inherited(subclass)
24
+ # Initializes chains for all types of callbacks
25
+ [:validation, :save, :create, :update, :destroy].each do |action|
26
+ [:before, :after].each do |type|
27
+ chain_name = "#{type}_#{action}_callbacks"
28
+
29
+ subclass.class_attribute chain_name
30
+ subclass.send("#{chain_name}=", [])
31
+ end
32
+ end
33
+
34
+ super
35
+ end
33
36
  end
34
37
 
35
38
  # Processes callbacks with specified type
@@ -1,36 +1,30 @@
1
- class Syncano
2
- module ActiveRecord
1
+ module Syncano
2
+ module Model
3
3
  # ScopeBuilder class allows for creating and chaining more complex queries
4
4
  class ScopeBuilder
5
5
  # Constructor for ScopeBuilder
6
6
  # @param [Class] model
7
7
  def initialize(model)
8
- raise 'Model should be a class extending module Syncano::ActiveRecord::Base' unless model <= Syncano::ActiveRecord::Base
8
+ raise 'Model should be a class extending module Syncano::Model::Base' unless model <= Syncano::Model::Base
9
9
 
10
10
  self.model = model
11
- self.parameters = {}
11
+ self.query = HashWithIndifferentAccess.new
12
12
  end
13
13
 
14
14
  # Returns collection of objects
15
15
  # @return [Array]
16
16
  def all
17
- folder.data_objects.all(parameters).collect do |data_object|
17
+ model.syncano_class.objects.all(parameters).collect do |data_object|
18
18
  model.new(data_object)
19
19
  end
20
20
  end
21
21
 
22
- # Returns count of objects
23
- # @return [Integer]
24
- def count
25
- folder.data_objects.all(parameters).count
26
- end
27
-
28
22
  # Returns one object found by id
29
23
  # @param [Integer] id
30
24
  # @return [Object]
31
25
  def find(id)
32
- parameters[:data_ids] = [id]
33
- all.first
26
+ data_object = model.syncano_class.objects.find(id)
27
+ data_object.present? ? model.new(data_object) : nil
34
28
  end
35
29
 
36
30
  # Returns first object or collection of first x objects
@@ -53,34 +47,31 @@ class Syncano
53
47
  # @param [String] condition
54
48
  # @param [Array] params
55
49
  # @return [Syncano::ActiveRecord::ScopeBuilder]
56
- def where(condition, *params)
57
- raise 'Invalid params count in where clause!' unless condition.count('?') == params.count
50
+ def where(conditions, *params)
51
+ raise 'Invalid params count in where clause!' unless conditions.count('?') == params.count
58
52
 
59
- params.each do |param|
60
- condition.sub!('?', param.to_s)
61
- end
53
+ params = params.dup
62
54
 
63
- conditions = condition.gsub(/\s+/, ' ').split(/and/i)
55
+ conditions.gsub(/\s+/, ' ').split(/and/i).each do |condition|
56
+ if condition.ends_with?('?')
57
+ value = params.shift
58
+ condition.gsub!('?', '').strip!
59
+ else
60
+ value = true
61
+ end
64
62
 
65
- conditions.each do |condition|
66
- attribute, operator, value = condition.split(' ')
63
+ attribute, operator = condition.split(' ', 2)
64
+ operator.upcase!
67
65
 
68
66
  raise 'Invalid attribute in where clause!' unless model.attributes.keys.include?(attribute)
69
67
  raise 'Invalid operator in where clause!' unless self.class.where_mapping.keys.include?(operator)
70
- raise 'Parameter in where clause is not an integer!' if !(value =~ /\A[-+]?[0-9]+\z/)
71
68
 
72
- method_name = "#{model.filterable_attributes[attribute]}__#{self.class.where_mapping[operator]}"
73
- parameters[method_name] = value
74
- end
69
+ operator = self.class.where_mapping[operator]
75
70
 
76
- self
77
- end
71
+ query[attribute] = HashWithIndifferentAccess.new if query[attribute].nil?
72
+ query[attribute][operator] = value
73
+ end
78
74
 
79
- # Adds to the current scope builder condition for filtering by parent_id
80
- # @param [Integer] parent_id
81
- # @return [Syncano::ActiveRecord::ScopeBuilder]
82
- def by_parent_id(parent_id)
83
- parameters[:parent_ids] = parent_id
84
75
  self
85
76
  end
86
77
 
@@ -88,53 +79,36 @@ class Syncano
88
79
  # @param [String] order
89
80
  # @return [Syncano::ActiveRecord::ScopeBuilder]
90
81
  def order(order)
91
- attribute, order_type = order.gsub(/\s+/, ' ').split(' ')
92
- raise 'Invalid attribute in order clause' unless (model.attributes.keys + ['id', 'created_at']).include?(attribute)
93
-
94
- attribute = model.map_to_syncano_attribute(attribute)
95
- order_type = order_type.to_s.downcase == 'desc' ? 'DESC' : 'ASC'
96
-
97
- self.parameters.merge!({ order_by: attribute, order: order_type })
98
-
99
- self
100
- end
101
-
102
- # Adds to the current scope builder condition for filtering by ids newer than provided
103
- # @param [Integer, String] id - id or datetime
104
- # @return [Syncano::ActiveRecord::ScopeBuilder]
105
- def since(id)
106
- if !(id =~ /\A[-+]?[0-9]+\z/)
107
- self.parameters[:since] = id
82
+ if order.is_a?(Hash)
83
+ attribute = order.keys.first
84
+ order_type = order[attribute]
108
85
  else
109
- self.parameters[:since_time] = id.to_time
86
+ attribute, order_type = order.gsub(/\s+/, ' ').split(' ')
110
87
  end
111
- self
112
- end
113
88
 
114
- # Adds to the current scope builder condition for filtering by ids older than provided
115
- # @param [Integer] id
116
- # @return [Syncano::ActiveRecord::ScopeBuilder]
117
- def before(id)
118
- self.parameters[:max_id] = id
119
- self
120
- end
89
+ raise 'Invalid attribute in order clause' unless (model.attributes.keys).include?(attribute)
90
+
91
+ self.order_clause = order_type.to_s.downcase == 'desc' ? "-#{attribute}" : attribute
121
92
 
122
- # Adds to the current scope builder limit clause
123
- # @param [Integer] amount
124
- # @return [Syncano::ActiveRecord::ScopeBuilder]
125
- def limit(amount)
126
- self.parameters[:limit] = amount
127
93
  self
128
94
  end
129
95
 
96
+ # # Adds to the current scope builder limit clause
97
+ # # @param [Integer] amount
98
+ # # @return [Syncano::ActiveRecord::ScopeBuilder]
99
+ # def limit(amount)
100
+ # self.parameters[:limit] = amount
101
+ # self
102
+ # end
103
+ #
130
104
  private
131
105
 
132
- attr_accessor :parameters, :model, :scopes
106
+ attr_accessor :order_clause, :query, :model, :scopes
133
107
 
134
- # Returns folder for current model
108
+ # Returns Syncano::Resource class for current model
135
109
  # @return [Syncano::Resources::Folder]
136
- def folder
137
- model.folder
110
+ def syncano_class
111
+ model.syncano_class
138
112
  end
139
113
 
140
114
  # Returns scopes for current model
@@ -143,10 +117,20 @@ class Syncano
143
117
  model.scopes
144
118
  end
145
119
 
120
+ def parameters
121
+ params = {}
122
+
123
+ params[:order_by] = order_clause if order_clause.present?
124
+ params[:query] = query.to_json if query.present?
125
+
126
+ params
127
+ end
128
+
146
129
  # Returns mapping for operators
147
130
  # @return [Hash]
148
131
  def self.where_mapping
149
- { '=' => 'eq', '!=' => 'neq', '<>' => 'neq', '>=' => 'gte', '>' => 'gt', '<=' => 'lte', '<' => 'lt' }
132
+ { '=' => '_eq', '!=' => '_neq', '<>' => '_neq', '>=' => '_gte', '>' => '_gt',
133
+ '<=' => '_lte', '<' => '_lt', 'IS NOT NULL' => '_exists', 'IN' => '_in' }
150
134
  end
151
135
 
152
136
  # Applies scope to the current scope builder