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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8fa33e829552d449652567e0ccf85426f4b31d9e
4
+ data.tar.gz: 877390535ea162188215684f8b7f58adb788b45b
5
+ SHA512:
6
+ metadata.gz: 8d4a6780ef77bda1100d9f09d5b833e9659890ca318442887a55d6aab5b6685cff320a13912376ba35547db826edd6ae82cec55be4b0a593274252941d68b415
7
+ data.tar.gz: 7077b7034ae4bf1189367c5582996579313d630330729d1cc800ab4ca5a71c3a5acf9a5558c8da89e51d391e633a9fce587bb7ae4fca9940a5fffa4092ced573
data/.gitignore CHANGED
@@ -22,4 +22,7 @@ tmp
22
22
  mkmf.log
23
23
  .DS_Store
24
24
  .com.apple.timemachine.supported
25
- .idea/*
25
+ .idea/*
26
+ .ruby-gemset
27
+ .env
28
+ profiles
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ AllCops:
2
+ Exclude:
3
+ - syncano.gemspec
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.5
data/Gemfile CHANGED
@@ -1,4 +1,28 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in syncano.gemspec
4
3
  gemspec
4
+
5
+ group :console do
6
+ gem 'pry'
7
+ end
8
+
9
+ group :test do
10
+ gem 'dotenv'
11
+ gem 'rspec'
12
+ gem 'webmock'
13
+ gem 'shoulda-matchers', require: false
14
+ gem 'rspec-prof', git: 'https://github.com/sinisterchipmunk/rspec-prof.git'
15
+ end
16
+
17
+ group :tools do
18
+ gem 'guard'
19
+ gem 'guard-rspec'
20
+ gem 'guard-rubocop'
21
+
22
+ gem 'rubocop', require: false
23
+
24
+ platform :mri do
25
+ gem 'mutant'
26
+ gem 'mutant-rspec'
27
+ end
28
+ end
data/Guardfile CHANGED
@@ -1,5 +1,23 @@
1
- guard :rspec do
2
- watch(%r{^spec/.+_spec\.rb$})
3
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
1
+ guard :rspec, cmd: 'bundle exec rspec' do
2
+ require 'guard/rspec/dsl'
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ # Feel free to open issues for suggestions and improvements
6
+
7
+ # RSpec files
8
+ rspec = dsl.rspec
9
+ watch('spec/spec_helper.rb') { rspec.spec_dir }
10
+ watch('spec/**/*_spec.rb') { rspec.spec_dir }
11
+ watch(rspec.spec_files)
12
+
13
+ # Ruby files
14
+ ruby = dsl.ruby
15
+ dsl.watch_spec_files_for(ruby.lib_files)
16
+
17
+ watch(ruby.lib_files) { rspec.spec_dir }
5
18
  end
19
+
20
+ # guard :rubocop do
21
+ # watch(%r{.+\.rb$})
22
+ # watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
23
+ # end
data/README.md CHANGED
@@ -1,503 +1,124 @@
1
- # Syncano
1
+ # Syncano 4.0 ruby gem
2
2
 
3
- Syncano ruby gem provides communication with Syncano ([www.syncano.com](http://www.syncano.com)) via HTTPS RESTful interface and TCP sockets.
4
-
5
- The full source code can be found on [Github](https://github.com/Syncano/syncano-ruby) - feel free to browse or contribute.
6
-
7
- Click here to learn more about [Syncano](http://www.syncano.com) or [create an account](https://login.syncano.com/sign_up)!
8
3
 
9
4
  ## Installation
10
5
 
11
- Add this line to your application's Gemfile:
12
-
13
- gem 'syncano', '~> 3.1'
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install syncano -v 3.1.3
22
-
23
- At the end generate initializer with api key and api instance name:
24
-
25
- $ rails g syncano:install
26
-
27
- Initializer is not obligatory - you can provide both parameters directly in the client's constructor.
28
-
29
- ## Usage
30
-
31
- ### Clients
32
-
33
- There are two different class of clients. One for JSON RPC interface and one for socket connections with Sync Server. You can use both in quite similar way:
34
-
35
- ```ruby
36
- client = Syncano.client
37
-
38
- client = Syncano.sync_client
39
- ```
40
-
41
- You can provide specific api credentials when you are initializing your client:
42
-
43
- ```ruby
44
- client = Syncano.client(api_key: 'api key', instance_name: 'instance name')
45
-
46
- client = Syncano.sync_client(api_key: 'api key', instance_name: 'instance name')
47
- ```
48
-
49
- Sync client has some additional features like:
50
-
51
- * managing connections
52
- ```ruby
53
- client.connect
54
- client.reconnect
55
- client.disconnect
56
- ```
57
- * managing callbacks for handling notifications (it is described later in this document)
58
-
59
- #### User api key
60
-
61
- If you want to use an user api key, you have to pass auth key or username and password to the client's constructor.
62
-
63
- ```ruby
64
- client = Syncano.client(api_key: 'api key', instance_name: 'instance name', auth_key: 'auth key')
65
- ```
66
-
67
- ```ruby
68
- client = Syncano.client(api_key: 'api key', instance_name: 'instance name', username: 'username', password: 'password')
69
- ```
70
-
71
- ### Resources
72
-
73
- Syncano gem utilizes an ActiveRecord pattern for managing resources. You can use it in similar way with both type of clients.
74
-
75
- Below is a list of standard methods implemented in resources.
76
-
77
- * objects.all(parameters)
78
- * objects.count(parameters)
79
- * objects.first(parameters)
80
- * objects.last(parameters)
81
- * objects.find(id)
82
- * objects.new(attributes)
83
- * objects.create(attributes)
84
- * object.update(attributes)
85
- * object.save
86
- * object.destroy
87
-
88
- Some of resources do not implement all standard methods and others have some custom methods, ie. data_object.copy.
89
-
90
- Every resource has attributes which can be accessed as a hash ie.:
91
-
92
- * object[:attribute]
93
- * object[:attribute] = 'value'
94
- * object.attributes = { attribute: 'value' }
95
-
96
- Below is a list of all implemented resources with information about what methods are implemented and usage examples.
97
-
98
- #### Project
99
-
100
- Implements all standard methods and following custom:
101
-
102
- * project.authorize(api_key_id, permission)
103
-
104
- ##### Examples
105
-
106
- * Getting all projects
107
-
108
- ```ruby
109
- Syncano.projects.all
110
- ```
111
-
112
- * Creating a project
113
-
114
- ```ruby
115
- Syncano.projects.create(name: 'Project name')
116
- ```
117
-
118
- * Updating a project
119
-
120
- ```ruby
121
- project[:description] = 'Lorem ipsum'
122
- project.save
123
- ```
124
-
125
- * Authorizing user api key with read permission
126
-
127
- ```ruby
128
- project.authorize(api_key_id, 'read_data')
129
- ```
130
-
131
- #### Collection
132
-
133
- Implements all standard methods and following custom:
134
-
135
- * collections.find_by_key(collection_key)
136
- * collection.activate
137
- * collection.deactivate
138
- * collection.add_tag(tag, weight, remove_others)
139
- * collection.delete_tag(tag)
140
- * collection.authorize(api_key_id, permission)
141
-
142
- ##### Examples
143
-
144
- * Getting all
145
-
146
- ```ruby
147
- project.collections.all
148
- ```
149
-
150
- * Finding by key
6
+ Using gems:
151
7
 
152
- ```ruby
153
- project.collections.find_by_key(collection_key)
154
- ```
155
-
156
- * Activating
157
-
158
- ```ruby
159
- collection.activate
160
- ```
161
-
162
- * Adding tags
163
-
164
- ```ruby
165
- collection1.add_tags(['tag1', 'tag2'], 3)
166
- collection2.add_tags('tag3', 1, true)
8
+ ```bash
9
+ $ gem install syncano --pre
167
10
  ```
168
11
 
169
- #### Folder
170
-
171
- Implements all standard methods and following custom:
172
-
173
- * folders.find_by_name(folder_name)
174
- * folder.authorize(api_key_id, permission)
175
-
176
- Find method uses folder name as a key.
12
+ ## First steps
177
13
 
178
- ##### Examples
179
-
180
- * Getting one
181
-
182
- ```ruby
183
- collection.folders.find(folder_name)
184
- collection.folders.find_by_name(folder_name)
185
- ```
186
-
187
- #### Data object
188
-
189
- Implements all standard methods and following custom:
190
-
191
- * data_objects.find_by_key(data_object_key)
192
- * data_objects.move(data_object_ids, new_folder, new_state)
193
- * data_object.move(new_folder, new_state)
194
- * data_objects.copy(data_object_ids)
195
- * data_object.copy
196
- * data_object.add_parent(parent_id, remove_other)
197
- * data_object.remove_parent(parent_id)
198
- * data_object.add_child(parent_id, remove_other)
199
- * data_object.remove_child(parent_id)
200
-
201
- ##### Examples
202
-
203
- * Moving data object to the new folder
204
-
205
- ```ruby
206
- data_object.move('new_folder')
207
- ```
14
+ After installation, you have to set a path for api root for syncano.
208
15
 
209
- * Copying two data objects
16
+ If you want to use staging, export:
210
17
 
211
- ```ruby
212
- collection.data_objects.copy([112, 3871])
18
+ ```bash
19
+ $ export API_ROOT=https://v4.hydraengine.com
213
20
  ```
214
21
 
215
- * Adding parent to the data object
22
+ If you're less adventurous, use our production api servers:
216
23
 
217
- ```ruby
218
- data_object.add_parent(parent_object_id, true)
24
+ ```bash
25
+ $ export=API_ROOT=https://api.syncano.io
219
26
  ```
220
27
 
221
- #### Admin
222
-
223
- Implements all standard methods and following custom:
224
-
225
- * admin.find_by_email(email)
226
-
227
- #### Api key
228
-
229
- Implements all standard methods.
230
-
231
- #### Role
232
-
233
- Implements only following standard methods:
234
-
235
- * role.all
236
- * role.first
237
- * role.last
238
- * role.count
239
-
240
- #### User
241
-
242
- Implements all standard methods.
243
-
244
- ### Batch requests
245
-
246
- It is possible to make batch requests to the JSON RPC endpoint. You do not have to care about batch requests limits specified in the Syncano api docs. This library will care about queuing for you.
28
+ Ok, now we can start coding!
247
29
 
248
30
  ```ruby
249
- client = Syncano.client
250
- responses = client.batch do |queue|
251
- queue << collection.batch.save
252
- queue << collection.data_objects.batch.create(title: 'Lorem ipsum')
253
- queue.add(data_object.batch.destroy)
254
- end
255
- ```
31
+ require 'syncano'
256
32
 
257
- There is no difference between "queue.add" and "queue <<" methods.
33
+ syncano = Syncano.connect(api_key: 'your-api-key')
258
34
 
259
- In the above example variable responses will contain three Syncano::Response objects.
260
- Remember that batch responses do not change objects used in batch requests. If you want to see changes you have to reload them:
261
-
262
- ```ruby
263
- collection.reload
35
+ syncano.instances.all.each { |instance| puts instance }
264
36
  ```
265
37
 
266
- ### Notifications
267
-
268
- Main advantage of using Sync Server are real time notifications. This concept is well described in the Syncano api documentation.
38
+ You can either pass your API key to the connect method as above or set
39
+ `ENV['SYNCANO_API_KEY']` and call just `Syncano.connect`.
269
40
 
270
- #### Subscriptions
41
+ ## API basics
271
42
 
272
- Before you will receive any notification, you have to subscribe to some project or collection:
273
-
274
- ```ruby
275
- client = Syncano.sync_client
276
- project = client.project.find(project_id)
277
- project.subscribe
278
- ```
279
-
280
- If you want to stop receiving notifications, you have to unsubscribe:
281
- ```ruby
282
- project.unsubscribe
283
- ```
43
+ Syncano API is a nested API - all the endpointes are scoped by an instances, ex.
44
+ codeboxes path is `/instance/your_instance_name/codeboxes/`. Syncano instances
45
+ is more less a schema is in relation databases. **Your instance name must be
46
+ unique across all existing Syncano instnaces, not only limitted to your account.**
284
47
 
285
- You can also list all active subscriptions:
286
- ```ruby
287
- client.subscriptions.all
288
- ```
289
48
 
290
- #### Handling notifications
49
+ # Instances
291
50
 
292
- Notifications are handled by callbacks passed to the sync client:
51
+ In order to do anything with Syncano, you have to create an instances. Choose a
52
+ globally unique name and call:
293
53
 
294
54
  ```ruby
295
- client.append_callback(:callback_name) do |notification|
296
- p "We have received a new notification #{notification.inspect}! Yaaay!"
297
- end
298
- ```
299
-
300
- Callbacks form a queue. You can add new callback to the end of the queue (like above) or to the beginning:
55
+ instances = syncano.instances.create name: 'my_instances_name'
56
+ instance.first
301
57
 
302
- ```ruby
303
- client.prepend_callback(:callback_name) do |notification|
304
- p "We have received a new notification #{notification.inspect}! Yaaay!"
305
- end
58
+ #=> #<Syncano::Resources::Instance created_at: Sun, 26 Apr 2015 18:09:46 +0000, description: "", metadata: {}, name: "my_instance_name", owner: nil, role: "full", updated_at: Sun, 26 Apr 2015 18:09:46 +0000>
306
59
  ```
307
60
 
308
- To delete callback from the queue just call remove_callback method:
309
-
310
- ```ruby
311
- client.remove_callback(:callback_name)
312
- ```
61
+ # Classes and objects
313
62
 
314
- To list notifications ie. after connection use all method:
63
+ In order to save objects in Syncano, first you need to create a class. A class
64
+ defines objects' attributes in the class' schema. The attribute definition has two
65
+ mandatory (`name`, `type`) and two optional fields (`filter_index`, `order_index`).
66
+ What these fields are for is rather obvious - `name` defines objects' attribute
67
+ name, and `type` defines type (you can read more about available types in the
68
+ [API docs](http://docs.syncano.com/v0.1/docs/instancesinstanceclasses-2)). `*_index`
69
+ fields are indexing. `order_index` allows you order returned collections,
70
+ `filter_index` allows filtering in a various ways. There will be a few examples
71
+ in this README, but you can read in the
72
+ [API docs](http://docs.syncano.com/v0.1/docs/filtering-data-objects).
315
73
 
316
74
  ```ruby
317
- client.notifications.all
75
+ stock = instance.classes.create name: 'stock_items',
76
+ schema: [{ name: 'name', type: 'string',
77
+ filter_index: true },
78
+ { name: 'amount', type: 'integer',
79
+ filter_index: true,
80
+ order_index: true }]
318
81
  ```
319
82
 
320
- #### Sending notifications
321
-
322
- To send notification just create new notification object:
83
+ Once we have a class, we can start creating objects.
323
84
 
324
85
  ```ruby
325
- client.notifications.create(key: 'value')
86
+ chorizo = stock.objects.create name: 'Chorizo', amount: 100
87
+ black_pudding = stock.objects.create name: 'Black pudding', amount: 200
88
+ curry_wurts = stock.objects.create name: 'Curry wurst', amount: 150
89
+ kabanos = stock.objects.create name: 'Kabanos'
90
+ something = stock.objects.create amount: 3
326
91
  ```
327
92
 
328
- You can also pass additional attributes specified for api 'notification.send' method:
93
+ Now we have a few items in stock, let's try filtering.
329
94
 
330
95
  ```ruby
331
- client.notifications.create(key: 'value', api_client_id: 512)
96
+ stock.objects.all(order_by: '-amount', query: { amount: { _lte: 150 }, name: { _exists: true } })
97
+ #=> #<Syncano::Resources::Collection:0x007fc18b9c7698 @next=false, @prev=false, @collection=[#<Syncano::Resources::Object amount: 150, channel: nil, channel_room: nil, created_at: Mon, 27 Apr 2015 05:21:31 +0000, group: nil, group_permissions: "none", id: 12, name: "Curry wurst", other_permissions: "none", owner: nil, owner_permissions: "none", revision: 1, updated_at: Mon, 27 Apr 2015 05:21:31 +0000>, #<Syncano::Resources::Object amount: 100, channel: nil, channel_room: nil, created_at: Mon, 27 Apr 2015 05:21:30 +0000, group: nil, group_permissions: "none", id: 10, name: "Chorizo", other_permissions: "none", owner: nil, owner_permissions: "none", revision: 1, updated_at: Mon, 27 Apr 2015 05:21:30 +0000>]>
332
98
  ```
333
99
 
334
- ### Errors and exceptions
335
-
336
- This library does not implement any validations. All errors from the api will cause throwing an exception.
337
- It is thought that user will create his own validation mechanisms specific not only for restrictions imposed by the Syncano, but also for his own logic.
338
- It can be compared to the exceptions after violating constraints in the MySQL database.
339
-
340
- ### Integration with Ruby on Rails
341
-
342
- Syncano gem provides handy class for implementing model with ActiveRecord pattern. See example below:
100
+ Let's give `something` a name and try again.
343
101
 
344
102
  ```ruby
345
- class Category < Syncano::ActiveRecord::Base
346
- has_many :articles
103
+ something.name = 'Unidentified sausage'
104
+ something.save
347
105
 
348
- attribute :name, type: String
349
- validates :name, presence: true
350
- end
351
-
352
- class Article < Syncano::ActiveRecord::Base
353
- belongs_to :category
354
-
355
- attribute :title, type: String
356
- attribute :text, type: String
357
- attribute :promoted, type: Integer, filterable: :data1
358
- validates :title, presence: true
359
- validates :text, presence: true
360
-
361
- scope :promoted, -> { where('promoted = ?', 1) }
362
-
363
- before_save :sanitize_content
364
-
365
- private
366
-
367
- def sanitize_content
368
- self.title = Sanitize.clean(title)
369
- self.text = Sanitize.clean(text)
370
- end
371
- end
372
- ```
373
-
374
- #### Attributes
375
-
376
- As you can see above every attribute has to be declared with a type. Every ActiveRecord class has also three standard attributes:
377
- - :id, type: Integer
378
- - :created_at, type: DateTime
379
- - :updated_at, type: DateTime
380
-
381
- There can be up to three filterable attributes (mapped to the Syncano data1, data2, data3 attributes), which can be used in where and order clauses. They always should have Integer type.
382
-
383
- Attributes can be validated like in standard ActiveRecord.
384
-
385
- #### Scopes and query building
386
-
387
- You can sort and filter by filterable attributes:
388
-
389
- ```ruby
390
- where('attribute1 > ? AND attribute2 <= ?', 0, 30).order('attribute3 ASC').where('attribute 2 > ?', 5)
391
- ```
392
-
393
- As you can see methods can be chained.
394
-
395
- #### Callbacks
396
-
397
- There are available ten different callbacks fired in the following sequence:
398
-
399
- 1. before_validation
400
- 2. after_validation
401
- 3. before_save
402
- 4. before_create / before_update
403
- 5. after_create / after_save
404
- 6. after_save
405
-
406
- 1. before_destroy
407
- 2. after_destroy
408
-
409
- #### Associations
410
-
411
- There are three types of relations (belongs_to, has_one, has_many) which are based on Syncano parent - child mechanism.
412
-
413
- ##### belongs_to :category
414
-
415
- Adds following methods:
416
-
417
- ```ruby
418
- self.category
419
- self.category = Category.first
420
- self.category_id
421
- self.category_id = Category.first.id
422
- ```
423
-
424
- Remember to always declare belongs_to association! It creates proper attribute in model.
425
-
426
- ##### has_one :article
427
-
428
- ```ruby
429
- self.article
430
- self.article = Article.first # this method updates article object
431
- self.build_article(article_attributes)
432
- self.create_article(article_attributes)
433
- ```
434
-
435
- ##### has_many :articles
436
-
437
- ```ruby
438
- self.articles
439
- self.articles = Article.first(5) # this method updates each article object
440
- self.articles << Article.first # this method updates article object
441
- self.articles.build(article_attributes)
442
- self.articles.create(article_attributes)
443
- ```
444
-
445
- You can also call scope builder methods on has_many collection:
446
-
447
- ```ruby
448
- self.articles.promoted.all
449
- ```
450
-
451
- #### Other useful methods in examples
452
-
453
- ```ruby
454
- Article.promoted.find(id)
455
- Article.where('promoted = ?', 0).count
456
- Article.since(min_id).before(max_id)
457
- Article.since(Time.now - 10.days)
106
+ stock.objects.all(order_by: '-amount', query: { amount: { _lte: 150 }, name: { _exists: true } })
107
+ #=> #<Syncano::Resources::Collection:0x007fc18d58a628 @next=false, @prev=false, @collection=[#<Syncano::Resources::Object amount: 150, channel: nil, channel_room: nil, created_at: Mon, 27 Apr 2015 05:21:31 +0000, group: nil, group_permissions: \"none\", id: 12, name: \"Curry wurst\", other_permissions: \"none\", owner: nil, owner_permissions: \"none\", revision: 1, updated_at: Mon, 27 Apr 2015 05:21:31 +0000>, #<Syncano::Resources::Object amount: 100, channel: nil, channel_room: nil, created_at: Mon, 27 Apr 2015 05:21:30 +0000, group: nil, group_permissions: \"none\", id: 10, name: \"Chorizo\", other_permissions: \"none\", owner: nil, owner_permissions: \"none\", revision: 1, updated_at: Mon, 27 Apr 2015 05:21:30 +0000>, #<Syncano::Resources::Object amount: 3, channel: nil, channel_room: nil, created_at: Mon, 27 Apr 2015 05:30:18 +0000, group: nil, group_permissions: \"none\", id: 15, name: \"Unidentified sausage\", other_permissions: \"none\", owner: nil, owner_permissions: \"none\", revision: 2, updated_at: Mon, 27 Apr 2015 05:30:48 +0000>]>
458
108
  ```
459
109
 
460
- For all methods please see reference for Syncano::ActiveRecord::Base class.
110
+ Now it matches the query and appears in the result.
461
111
 
462
- #### Collection and folders
112
+ # Codeboxes
463
113
 
464
- Classes which inherit from Syncano::ActiveRecord::Base needs a collection and a folders in Syncano.
465
-
466
- Collection can be configured as constant in initializer:
467
-
468
- ```ruby
469
- SYNCANO_ACTIVERECORD_COLLECTION = Syncano.client.project.first.collection.first
470
- ```
114
+ Codeboxes are small pieces of code that run on Syncano servers. You can run them
115
+ manually using the API, you can create a schedule to run them periodically, you
116
+ can create a Webhook (and optionally make it public) to run them from the web,
117
+ you can create a trigger to run one after a class' object is created, updated or
118
+ deleted. There are three runtimes available: Ruby, Python and Node. This gem is
119
+ available in Ruby runtime (just needs to be required).
471
120
 
472
- or it can be overwritten in selected model:
473
121
 
474
- ```ruby
475
- class Article < Syncano::ActiveRecord::Base
476
-
477
- private
478
-
479
- def self.collection
480
- Syncano.client.project.first.collection.first
481
- end
482
- end
483
- ```
484
-
485
- Folders are used as classes - each model as his own folder (ie. Articles). Folder is automatically created and used without any additional configuration, but you can customize convention by overwriting folder_name or folder method:
486
-
487
- ```ruby
488
- class Article < Syncano::ActiveRecord::Base
489
-
490
- private
491
-
492
- def self.folder_name
493
- 'Posts'
494
- end
495
-
496
- def self.folder
497
- collection.folders.find_by_name(folder_name)
498
- end
499
- end
500
- ```
501
122
 
502
123
  ## Contributing
503
124