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.
- checksums.yaml +7 -0
- data/.gitignore +4 -1
- data/.rspec +2 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +25 -1
- data/Guardfile +22 -4
- data/README.md +68 -447
- data/Rakefile +48 -5
- data/circle.yml +10 -0
- data/lib/active_attr/dirty.rb +3 -17
- data/lib/active_attr/typecasting/hash_typecaster.rb +34 -0
- data/lib/active_attr/typecasting_override.rb +29 -0
- data/lib/syncano.rb +53 -92
- data/lib/syncano/api.rb +13 -0
- data/lib/syncano/connection.rb +97 -0
- data/lib/syncano/model/associations.rb +121 -0
- data/lib/syncano/{active_record/association → model/associations}/base.rb +5 -5
- data/lib/syncano/{active_record/association → model/associations}/belongs_to.rb +6 -6
- data/lib/syncano/{active_record/association → model/associations}/has_many.rb +15 -9
- data/lib/syncano/{active_record/association → model/associations}/has_one.rb +4 -4
- data/lib/syncano/model/base.rb +257 -0
- data/lib/syncano/{active_record → model}/callbacks.rb +16 -13
- data/lib/syncano/{active_record → model}/scope_builder.rb +53 -69
- data/lib/syncano/query_builder.rb +19 -129
- data/lib/syncano/resources.rb +126 -0
- data/lib/syncano/resources/base.rb +304 -300
- data/lib/syncano/resources/collection.rb +19 -223
- data/lib/syncano/resources/space.rb +29 -0
- data/lib/syncano/schema.rb +86 -0
- data/lib/syncano/schema/attribute_definition.rb +83 -0
- data/lib/syncano/schema/resource_definition.rb +36 -0
- data/lib/syncano/scope.rb +10 -0
- data/lib/syncano/version.rb +3 -4
- data/spec/integration/syncano_spec.rb +228 -0
- data/spec/spec_helper.rb +15 -9
- data/spec/unit/api_spec.rb +5 -0
- data/spec/unit/connection_spec.rb +137 -0
- data/spec/unit/query_builder_spec.rb +75 -0
- data/spec/unit/resources/collection_spec.rb +36 -0
- data/spec/unit/resources/space_spec.rb +28 -0
- data/spec/unit/resources_base_spec.rb +185 -0
- data/spec/unit/schema/attribute_definition_spec.rb +18 -0
- data/spec/unit/schema/resource_definition_spec.rb +25 -0
- data/spec/unit/schema_spec.rb +3532 -0
- data/spec/unit/syncano_spec.rb +63 -0
- data/syncano.gemspec +8 -14
- metadata +85 -210
- data/lib/generators/syncano/install_generator.rb +0 -17
- data/lib/generators/syncano/templates/initializers/syncano.rb +0 -7
- data/lib/syncano/active_record/associations.rb +0 -112
- data/lib/syncano/active_record/base.rb +0 -318
- data/lib/syncano/batch_queue.rb +0 -58
- data/lib/syncano/batch_queue_element.rb +0 -33
- data/lib/syncano/clients/base.rb +0 -123
- data/lib/syncano/clients/rest.rb +0 -79
- data/lib/syncano/clients/sync.rb +0 -164
- data/lib/syncano/errors.rb +0 -17
- data/lib/syncano/jimson_client.rb +0 -66
- data/lib/syncano/packets/auth.rb +0 -27
- data/lib/syncano/packets/base.rb +0 -70
- data/lib/syncano/packets/call.rb +0 -34
- data/lib/syncano/packets/call_response.rb +0 -33
- data/lib/syncano/packets/error.rb +0 -19
- data/lib/syncano/packets/message.rb +0 -30
- data/lib/syncano/packets/notification.rb +0 -39
- data/lib/syncano/packets/ping.rb +0 -12
- data/lib/syncano/resources/admin.rb +0 -26
- data/lib/syncano/resources/api_key.rb +0 -108
- data/lib/syncano/resources/data_object.rb +0 -316
- data/lib/syncano/resources/folder.rb +0 -88
- data/lib/syncano/resources/notifications/base.rb +0 -103
- data/lib/syncano/resources/notifications/create.rb +0 -20
- data/lib/syncano/resources/notifications/destroy.rb +0 -20
- data/lib/syncano/resources/notifications/message.rb +0 -9
- data/lib/syncano/resources/notifications/update.rb +0 -24
- data/lib/syncano/resources/project.rb +0 -96
- data/lib/syncano/resources/role.rb +0 -11
- data/lib/syncano/resources/subscription.rb +0 -12
- data/lib/syncano/resources/user.rb +0 -65
- data/lib/syncano/response.rb +0 -22
- data/lib/syncano/sync_connection.rb +0 -133
- data/spec/admins_spec.rb +0 -16
- data/spec/api_keys_spec.rb +0 -34
- data/spec/collections_spec.rb +0 -67
- data/spec/data_objects_spec.rb +0 -113
- data/spec/folders_spec.rb +0 -39
- data/spec/notifications_spec.rb +0 -43
- data/spec/projects_spec.rb +0 -35
- data/spec/roles_spec.rb +0 -13
- data/spec/sync_resources_spec.rb +0 -35
- data/spec/syncano_spec.rb +0 -9
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'syncano/
|
1
|
+
require 'syncano/model/scope_builder'
|
2
2
|
|
3
|
-
|
4
|
-
module
|
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/
|
1
|
+
require 'syncano/model/associations/base'
|
2
2
|
|
3
|
-
|
4
|
-
module
|
3
|
+
module Syncano
|
4
|
+
module Model
|
5
5
|
module Association
|
6
6
|
# Class for belongs to association
|
7
|
-
class BelongsTo < Syncano::
|
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/
|
1
|
+
require 'syncano/model/associations/base'
|
2
2
|
|
3
|
-
|
4
|
-
module
|
3
|
+
module Syncano
|
4
|
+
module Model
|
5
5
|
module Association
|
6
6
|
# Class for has many association
|
7
|
-
class HasMany < Syncano::
|
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
|
-
|
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::
|
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/
|
1
|
+
require 'syncano/model/associations/base'
|
2
2
|
|
3
|
-
|
4
|
-
module
|
3
|
+
module Syncano
|
4
|
+
module Model
|
5
5
|
module Association
|
6
6
|
# Class for has one association
|
7
|
-
class HasOne < Syncano::
|
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
|
-
|
2
|
-
module
|
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
|
-
|
2
|
-
module
|
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::
|
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.
|
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
|
-
|
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
|
-
|
33
|
-
|
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(
|
57
|
-
raise 'Invalid params count in where clause!' unless
|
50
|
+
def where(conditions, *params)
|
51
|
+
raise 'Invalid params count in where clause!' unless conditions.count('?') == params.count
|
58
52
|
|
59
|
-
params
|
60
|
-
condition.sub!('?', param.to_s)
|
61
|
-
end
|
53
|
+
params = params.dup
|
62
54
|
|
63
|
-
conditions
|
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
|
-
|
66
|
-
|
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
|
-
|
73
|
-
parameters[method_name] = value
|
74
|
-
end
|
69
|
+
operator = self.class.where_mapping[operator]
|
75
70
|
|
76
|
-
|
77
|
-
|
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
|
-
|
92
|
-
|
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
|
-
|
86
|
+
attribute, order_type = order.gsub(/\s+/, ' ').split(' ')
|
110
87
|
end
|
111
|
-
self
|
112
|
-
end
|
113
88
|
|
114
|
-
|
115
|
-
|
116
|
-
|
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 :
|
106
|
+
attr_accessor :order_clause, :query, :model, :scopes
|
133
107
|
|
134
|
-
# Returns
|
108
|
+
# Returns Syncano::Resource class for current model
|
135
109
|
# @return [Syncano::Resources::Folder]
|
136
|
-
def
|
137
|
-
model.
|
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
|
-
{ '=' => '
|
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
|