pinkman 0.9.0

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +41 -0
  8. data/Rakefile +28 -0
  9. data/app/assets/javascripts/pinkman.js +10 -0
  10. data/app/assets/javascripts/pinkman_base/ajax.coffee +90 -0
  11. data/app/assets/javascripts/pinkman_base/collection.coffee +387 -0
  12. data/app/assets/javascripts/pinkman_base/common.coffee +56 -0
  13. data/app/assets/javascripts/pinkman_base/controller.coffee +164 -0
  14. data/app/assets/javascripts/pinkman_base/glue.coffee +15 -0
  15. data/app/assets/javascripts/pinkman_base/handlebars.js +4608 -0
  16. data/app/assets/javascripts/pinkman_base/hogan.js +576 -0
  17. data/app/assets/javascripts/pinkman_base/markup.js +483 -0
  18. data/app/assets/javascripts/pinkman_base/mixins.coffee +37 -0
  19. data/app/assets/javascripts/pinkman_base/object.js.coffee.erb +195 -0
  20. data/app/assets/javascripts/pinkman_base/pinkman.coffee +131 -0
  21. data/app/assets/javascripts/pinkman_base/render.coffee.erb +80 -0
  22. data/app/assets/javascripts/pinkman_base/tools.coffee +4 -0
  23. data/app/helpers/pinkman_helper.rb +48 -0
  24. data/bin/console +14 -0
  25. data/bin/setup +8 -0
  26. data/lib/generators/pinkman/USAGE +16 -0
  27. data/lib/generators/pinkman/api_generator.rb +60 -0
  28. data/lib/generators/pinkman/install_generator.rb +25 -0
  29. data/lib/generators/pinkman/model_generator.rb +41 -0
  30. data/lib/generators/pinkman/resource_generator.rb +15 -0
  31. data/lib/generators/pinkman/serializer_generator.rb +33 -0
  32. data/lib/generators/pinkman/templates/api.rb.erb +87 -0
  33. data/lib/generators/pinkman/templates/api_controller.rb +2 -0
  34. data/lib/generators/pinkman/templates/collection.js.erb +5 -0
  35. data/lib/generators/pinkman/templates/object.js.erb +3 -0
  36. data/lib/generators/pinkman/templates/serializer.rb.erb +15 -0
  37. data/lib/pinkman.rb +57 -0
  38. data/lib/pinkman/serializer.rb +6 -0
  39. data/lib/pinkman/serializer/base.rb +42 -0
  40. data/lib/pinkman/serializer/scope.rb +48 -0
  41. data/lib/pinkman/version.rb +3 -0
  42. data/pinkman.gemspec +46 -0
  43. data/public/javascripts/pinkman.min.js +1 -0
  44. data/public/jquery.pinkman.min.js +0 -0
  45. data/public/pinkman.min.js +29 -0
  46. metadata +242 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c608ca91577bd19a8d7014ddd49c49d58f9ef12a
4
+ data.tar.gz: 14851ec0f71e7a62df16622c525ad42efdb32114
5
+ SHA512:
6
+ metadata.gz: 2f0636432c7af59425a2f87d803798b837eb745de32200f71cd05d58bef06aff4bb8369c2c6955de367db62b75e3b8da5927c6810650566d1444543f5e5d2fe8
7
+ data.tar.gz: c957e9f96a1c2d4c1fd41ebb3463059075cf182d2011444643be516931ec9f339222184eaff8a99164662389c9d13b271d4b4b1b86ef72a53d41a903e27edda4
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /dummy/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pinkman.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Agilso Oliveira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ # Pinkman
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pinkman`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'pinkman'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install pinkman
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pinkman.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
@@ -0,0 +1,28 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require 'pinkman'
4
+ require Pinkman.root.join('spec/support/sprockets')
5
+
6
+ task :default => :spec
7
+ require 'jasmine'
8
+ load 'jasmine/tasks/jasmine.rake'
9
+ RSpec::Core::RakeTask.new(:spec)
10
+
11
+ namespace :pinkman do
12
+ desc 'Precompile pinkman.js'
13
+ task :precompile do
14
+ f = File.open(Pinkman.root.join('public','pinkman.min.js'),'w+') {|f| f.write Assets.app_environment['pinkman'].to_s }
15
+ end
16
+ end
17
+
18
+ namespace :spec do
19
+
20
+ desc 'Compile spec.js and coffeescripts specs to js'
21
+ task precompile: ['pinkman:precompile'] do
22
+ f = File.open(Pinkman.root.join('spec','javascripts','spec.js'),'w+') {|f| f.write Assets.spec_environment['support/spec_helper'].to_s }
23
+ end
24
+
25
+ desc 'Run JS (Jasmine) Specs'
26
+ task :js => ['spec:precompile', 'jasmine']
27
+
28
+ end
@@ -0,0 +1,10 @@
1
+ //= require pinkman_base/handlebars
2
+ //= require pinkman_base/tools
3
+ //= require pinkman_base/pinkman
4
+ //= require pinkman_base/mixins
5
+ //= require pinkman_base/common
6
+ //= require pinkman_base/object
7
+ //= require pinkman_base/collection
8
+ //= require pinkman_base/render
9
+ //= require pinkman_base/controller
10
+ //= require pinkman_base/ajax
@@ -0,0 +1,90 @@
1
+ # @ajax:
2
+ # get: (options) ->
3
+ # if options.url?
4
+ # ajax = jQuery.ajax options.url,
5
+ # type: "GET"
6
+ # dataType: 'json'
7
+ # ajax.done (response) =>
8
+ # if response.errors?
9
+ # options.error(response) if options.error? and typeof options.error == 'function'
10
+ # return false
11
+ # else
12
+ # options.success(response) if options.success? and typeof options.success == 'function'
13
+ # options.complete(response) if options.complete? and typeof options.complete == 'function'
14
+ # return this
15
+ # else
16
+ # return false
17
+
18
+ # post: (options) ->
19
+ # if options.url?
20
+ # ajax = jQuery.ajax options.url,
21
+ # beforeSend: (xhr) ->
22
+ # xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
23
+ # type: "POST"
24
+ # dataType: 'json'
25
+ # data: options.data
26
+ # ajax.done (response) =>
27
+ # if response.errors?
28
+ # options.error(this) if options.error? and typeof options.error == 'function'
29
+ # return false
30
+ # else
31
+ # options.success(response) if options.success? and typeof options.success == 'function'
32
+ # options.complete(response) if options.complete? and typeof options.complete == 'function'
33
+ # return this
34
+ # else
35
+ # return false
36
+
37
+ # put: (options) ->
38
+ # if options.url?
39
+ # ajax = jQuery.ajax options.url,
40
+ # beforeSend: (xhr) ->
41
+ # xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
42
+ # type: "PUT"
43
+ # dataType: 'json'
44
+ # data: options.data
45
+ # ajax.done (response) =>
46
+ # if response.errors?
47
+ # options.error(this) if options.error? and typeof options.error == 'function'
48
+ # return false
49
+ # else
50
+ # options.success(response) if options.success? and typeof options.success == 'function'
51
+ # options.complete(response) if options.complete? and typeof options.complete == 'function'
52
+ # return this
53
+ # else
54
+ # return false
55
+
56
+
57
+ # file: (options) ->
58
+ # if options.url?
59
+ # ajax = jQuery.ajax options.url,
60
+ # beforeSend: (xhr) ->
61
+ # xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
62
+ # xhr: ->
63
+ # myXhr = $.ajaxSettings.xhr()
64
+ # myXhr.upload.addEventListener 'progress', (e) ->
65
+ # if e.lengthComputable
66
+ # options.progress e.loaded/e.total if options.progress?
67
+ # , false
68
+ # myXhr.addEventListener 'progress', (e) ->
69
+ # if e.lengthComputable
70
+ # options.progress e.loaded/e.total if options.progress?
71
+ # , false
72
+ # return myXhr
73
+ # type: "POST"
74
+ # dataType: 'json'
75
+ # data: options.data
76
+ # processData: false
77
+ # contentType: false
78
+ # ajax.done (response) =>
79
+ # if response? and response.errors?
80
+ # options.error(this) if options.error? and typeof options.error == 'function'
81
+ # return false
82
+ # else
83
+ # options.success(response) if options.success? and typeof options.success == 'function'
84
+ # options.complete(response) if options.complete? and typeof options.complete == 'function'
85
+ # return this
86
+ # else
87
+ # return false
88
+
89
+ # upload: (options...) ->
90
+ # @file(options...)
@@ -0,0 +1,387 @@
1
+ class window.PinkmanCollection extends window.PinkmanCommon
2
+
3
+ @pinkmanType = 'collection'
4
+
5
+ config:
6
+ memberClass: PinkmanObject
7
+
8
+ constructor: () ->
9
+
10
+ @isPink = true
11
+ @isCollection = true
12
+ @pinkmanType = 'collection'
13
+
14
+ @collection = []
15
+ @pinkey = Pinkman.all.length
16
+
17
+ Pinkman.collections.push(this)
18
+ Pinkman.all.push(this)
19
+
20
+ # Desc: return an array of all members
21
+ # this behaviour makes life easier... trust me
22
+ attributes: ->
23
+ return @collection
24
+
25
+ # Desc: collection size
26
+ count: (criteria='') ->
27
+ if criteria? and typeof criteria == 'function'
28
+ count = 0
29
+ (count++ if criteria(object)) for object in @collection
30
+ count
31
+ else
32
+ @collection.length
33
+
34
+ # Desc: Alias for count
35
+ size: (criteria='') ->
36
+ @count(criteria)
37
+
38
+ # Desc: Alias for count
39
+ length: (criteria='') ->
40
+ @count(criteria)
41
+
42
+ # rails/ruby equivalent: each
43
+ # Desc: receive a function and apply it to all members
44
+ # tip: you can chain functions. Example: collection.each(transform).first()
45
+ each: (transformation='') ->
46
+ if transformation? and typeof transformation=='function'
47
+ transformation(o) for o in @collection
48
+ return this
49
+
50
+ # rails/ruby equivalent: where/select
51
+ # Desc: returns a new collection of all members that satisfies a criteria (criteria(obj) returns true)
52
+ # new version: accepts a object to match against the object attributes
53
+ select: (criteria,callback='') ->
54
+ selection = new @constructor
55
+ # function version
56
+ if typeof criteria == 'function'
57
+ @each (object) ->
58
+ selection.push(object) if criteria(object)
59
+
60
+ # object version
61
+ else if typeof criteria == 'object'
62
+ @each (object) ->
63
+ value = true
64
+ (value = false if object[k] != v) for k,v of criteria
65
+ selection.push(object) if value
66
+
67
+ callback(selection) if typeof callback == 'function'
68
+ return(selection)
69
+
70
+ # Desc: insert in last position
71
+ push: (arg) ->
72
+ if Pinkman.isArray(arg)
73
+ @pushIndividually(item) for item in arg
74
+ return(@include(arg))
75
+ else
76
+ @pushIndividually(arg)
77
+
78
+ # Desc: insert in first position
79
+ unshift: (object) ->
80
+ if Pinkman.isArray(object)
81
+ @unshiftIndividually(item) for item in object
82
+ return(@include(object))
83
+ else
84
+ @unshiftIndividually(object)
85
+
86
+ pushIndividually: (object) ->
87
+ if object? and typeof object == 'object' and not @include(object)
88
+ @beforeInsertionPrep object, (object) =>
89
+ @collection.push(object)
90
+ object.collections.push(this) if object.isObject and object.collections?
91
+ return true
92
+ else
93
+ return false
94
+
95
+ directPush: (object) ->
96
+ @collection.push(object) unless @include(object)
97
+
98
+ forcePush: (object) ->
99
+ @collection.push(object)
100
+
101
+ unshiftIndividually: (object) ->
102
+ if object? and typeof object == 'object' and not @include(object)
103
+ @beforeInsertionPrep object, (object) =>
104
+ @collection.unshift(object)
105
+ object.collections.push(this) if object.isObject and object.collections?
106
+ return true
107
+ else
108
+ return false
109
+
110
+ beforeInsertionPrep: (object,callback='') ->
111
+ unless object.isPink
112
+ pinkObject = @new()
113
+ pinkObject.assign(object)
114
+ object = pinkObject
115
+ callback(object) if typeof callback == 'function'
116
+ return(object)
117
+
118
+ # Desc: removes from last position and returns it
119
+ pop: ->
120
+ @remove(@last())
121
+
122
+ # Desc: removes from first position and returns it
123
+ shift: ->
124
+ @remove(@first())
125
+
126
+ # Desc: remove a object from the collection
127
+ remove: (object) ->
128
+ if object?
129
+ i = @collection.indexOf object
130
+ @collection.splice(i,1)
131
+ return object
132
+
133
+ # Desc: remove the first object that matches
134
+ removeBy: (attribute,value) ->
135
+ if attribute? and value?
136
+ @remove(@getBy(attribute,value))
137
+
138
+ # Desc: remove everyone from this collection
139
+ removeAll: ->
140
+ if @any()
141
+ @remove(@first())
142
+ @removeAll()
143
+ else
144
+ return(true)
145
+
146
+ # Desc: return true if object is in this collection and false if anything else.
147
+ # Also accepts an array as argument. Return true if
148
+ include: (args) ->
149
+ if args? and Pinkman.isArray(args)
150
+ value = true
151
+ for item in args
152
+ value=false unless @include(item)
153
+ return(value)
154
+ else if args? and typeof args == 'object'
155
+ if args.id?
156
+ @any (o) ->
157
+ args.id == o.id
158
+ else
159
+ @collection.indexOf(args) isnt -1
160
+ else
161
+ false
162
+
163
+ first: (n=1) ->
164
+ if n==1
165
+ return @collection[0]
166
+ else
167
+ return @collection[0..(n-1)]
168
+
169
+ last: (n=1) ->
170
+ if n==1
171
+ return @collection[@collection.length - 1]
172
+ else
173
+ return @collection[(@collection.length - n - 1)..]
174
+
175
+ # Desc: return trues if has at least one member. If a criteria is specificied, returns true if at least one member satisfies it.
176
+ any: (criteria='') ->
177
+ if criteria? and typeof criteria == 'function'
178
+ @select(criteria).count() > 0
179
+ else
180
+ @count() > 0
181
+
182
+ # Desc: return the first object that matches
183
+ getBy: (attribute, value) ->
184
+ if attribute? and value?
185
+ object = new Object
186
+ object[attribute] = value
187
+ return(@getByAttributes(object))
188
+
189
+ # Desc: return the first that matches
190
+ getByAttributes: (object) ->
191
+ if object? and typeof object == 'object' and @any()
192
+ for member in @collection
193
+ match = true
194
+ for key,value of object
195
+ match = false if member[key]!=value
196
+ return(member) if match
197
+ else
198
+ return null
199
+
200
+ # Desc: get by pinkey
201
+ getByPinkey: (pinkey) ->
202
+ @getBy('pinkey',pinkey)
203
+
204
+ # Desc: sinthetize getByPinkey, getBy, and getByAttributes in one method
205
+ get: (args...) ->
206
+ if args.length > 0
207
+ if Pinkman.isNumber(args[0])
208
+ @getByPinkey(args[0])
209
+ else if args.length == 2
210
+ @getBy(args...)
211
+ else if typeof args[0] == 'object'
212
+ @getByAttributes(args[0])
213
+
214
+ # Desc: find by id
215
+ find: (id) ->
216
+ if id?
217
+ object = @getBy('id',id)
218
+ return(object)
219
+
220
+ # Desc: return the next (after) object
221
+ next: (object) ->
222
+ i = @collection.indexOf object
223
+ @collection[i+1]
224
+
225
+ # Desc: return the previous (before) object
226
+ prev: (object) ->
227
+ i = @collection.indexOf object
228
+ @collection[i-1]
229
+
230
+ # Desc: log every member pinkey in the console
231
+ logPinkeys: () ->
232
+ @each (object) ->
233
+ console.log object.pinkey
234
+
235
+ # Desc: removes duplicated records (same id or same pinkey)
236
+ uniq: (callback='') ->
237
+ duplicated = []
238
+ @each (object) =>
239
+ @each (matching) ->
240
+ duplicated.push(matching) if object.pinkey? and (object.pinkey == matching.pinkey) and (object isnt matching)
241
+ duplicated.push(matching) if object.id? and (object.id == matching.id) and (object isnt matching)
242
+ for d in duplicated
243
+ @remove(d)
244
+ return(this)
245
+
246
+ # Desc: fetch from array ... T_T
247
+ fetchFromArray: (array) ->
248
+ for a in array
249
+ object = @beforeInsertionPrep(a)
250
+ # if object already is in this collection, overwrite its values
251
+ if object? and @find(object.id)?
252
+ @find(object.id).assign(object.attributes())
253
+ # else, inserts it
254
+ else
255
+ @push(object)
256
+ return(this)
257
+
258
+ # Desc: merges this collection with another
259
+ merge: (collection) ->
260
+ if Pinkman.isArray(collection)
261
+ @fetchFromArray(collection)
262
+ else if typeof collection == 'object' and collection.isPink and collection.isCollection
263
+ @fetchFromArray(collection.collection)
264
+
265
+ # Desc: returns a new object associated with this collection
266
+ new: (attributes) ->
267
+ object = new (@config.memberClass)
268
+ object.initialize(attributes)
269
+ object
270
+
271
+ # Desc: reload every object in this collection
272
+ reload: (callback='') ->
273
+ if @any()
274
+ @each (object) =>
275
+ if object.id?
276
+ object.reload (object) =>
277
+ if object.pinkey == @last().pinkey and callback == 'function'
278
+ callback(this)
279
+
280
+ # Desc: create a index for objects
281
+ makeIndex: ->
282
+ if @any()
283
+ i = 1
284
+ for object in @collection
285
+ object.set("index",i)
286
+ i++
287
+ return true
288
+ else
289
+ return false
290
+
291
+ # Desc: exactly what it suggests
292
+ shuffle: () ->
293
+ if @any?
294
+ currentIndex = @collection.length
295
+
296
+ # // While there remain elements to shuffle...
297
+ while (0 != currentIndex)
298
+ # // Pick a remaining element...
299
+ randomIndex = Math.floor(Math.random() * currentIndex)
300
+ currentIndex = currentIndex - 1
301
+
302
+ # // And swap it with the current element.
303
+ temporaryValue = @collection[currentIndex]
304
+ @collection[currentIndex] = @collection[randomIndex]
305
+ @collection[randomIndex] = temporaryValue
306
+
307
+ # Desc: filters collection whose attribute matches the query
308
+ filter: (attribute,query,callback) ->
309
+ if attribute? and query? and query!="" and (typeof(attribute) == "string")
310
+ if @any()
311
+ filter = new @constructor
312
+ for obj in @collection
313
+ if obj[attribute] == query
314
+ filter.push obj
315
+ else if obj[attribute]? and (typeof obj[attribute] == "string") and (obj[attribute]!="") and (typeof query == "string") and (query!="") and (obj[field].toLowerCase().indexOf(query.toLowerCase()) > -1)
316
+ filter.push obj
317
+ callback(filter) if callback? and typeof callback == 'function'
318
+ return filter
319
+ else
320
+ return false
321
+
322
+
323
+ # --- Ajax related --- #
324
+
325
+ # Desc: Fetch records from API_URL
326
+ # request: get /api/API_URL/
327
+ # in rails: api::controller#index
328
+ fetch: (callback = '') ->
329
+ @fetchFromUrl url: @api(), callback: callback
330
+
331
+ # Desc: Fetch records from another action of this model api
332
+ # request: get /api/API_URL/:action/#id
333
+ # in rails: api::controller#action
334
+
335
+ # Example: fetching all orders of a user
336
+ # coffee: orders.fetchFrom 'user', user.id
337
+ # api::controler#order: render json: User.find(params[:id]).orders.to_json
338
+ fetchFrom: (action,id,callback = '') ->
339
+ if action? and id?
340
+ @fetchFromUrl(@api() + "#{action}/#{id}", callback)
341
+ else
342
+ return false
343
+
344
+
345
+ # Desc: Fetch records from URL
346
+ # request: get /api/API_URL/
347
+ fetchFromUrl: (options) ->
348
+ if options? and typeof options == 'object' and options.url?
349
+ limit = if options.limit? then options.limit else 1000
350
+ offset = if options.offset? then options.offset else 0
351
+ @fetchingFrom = options.url
352
+ Pinkman.ajax.get
353
+ url: options.url + "?limit=#{limit}&offset=#{offset}"
354
+ complete: (response) =>
355
+ if response.errors? or response.error?
356
+ [@errors, @error] = [response.errors, response.error]
357
+ if response.errors? then (throw new Error('Oh no... I could not fetch your records, bitch. (jk... about the "bitch" part)')) else (throw new Error(response.error))
358
+ return false
359
+ else
360
+ @fetchFromArray(response).emptyResponse = response.length == 0
361
+ options.callback(this) if options.callback? and typeof options.callback == 'function'
362
+ return(this)
363
+
364
+ # Desc: Fetch next records from last fetched URL or main API_URl
365
+ # request: get /api/API_URL/?offset="COLLECTION_SIZE"&limit=n
366
+ # in rails: api::controller#index
367
+ fetchMore: (n=10,callback='') ->
368
+ if @fetchingFrom?
369
+ @fetchFromUrl url: @fetchingFrom, limit: n, offset: @count(), callback: callback
370
+ else
371
+ @fetchFromUrl url: @api(), limit: n, offset: @count(), callback: callback
372
+
373
+ # Desc: Fetch next n records from a action
374
+ # request: get /api/API_URL/:action/?offset="COLLECTION_SIZE"&limit=n
375
+ # in rails: api::controller#action
376
+ fetchMoreFrom: (n,action,id,callback='') ->
377
+ @fetchFromUrl {url: @api() + "#{action}/#{id}", limit: n, offset: @count(), callback: callback}
378
+
379
+ # Desc: Connect to api to search in this model a query
380
+ # request: get /api/API_URL/search?query=YOUR_QUERY
381
+ # in rails: api::controller#search
382
+ # assume models to have a Model.search("YOUR_QUERY") method.
383
+ search: (query,callback='') ->
384
+ @removeAll()
385
+ @fetchFromUrl { url: @api() + "search?query=#{query}", callback: callback }
386
+
387
+ window.Pinkman.collection = window.PinkmanCollection