parse_resource 1.6.0 → 1.6.1

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.
data/README.md CHANGED
@@ -44,7 +44,7 @@ Installation
44
44
  Include in your `Gemfile`:
45
45
 
46
46
  ```ruby
47
- gem "parse_resource", "~> 1.5.11"
47
+ gem "parse_resource", "~> 1.6.0"
48
48
  ```
49
49
 
50
50
  Or just gem install:
@@ -75,7 +75,7 @@ In a non-Rails app, include this somewhere (preferable in an initializer):
75
75
 
76
76
 
77
77
  ```ruby
78
- ParseResource.load!("your_app_id", "your_master_key")
78
+ ParseResource::Base.load!("your_app_id", "your_master_key")
79
79
  ```
80
80
 
81
81
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.0
1
+ 1.6.1
data/lib/base.rb CHANGED
@@ -5,285 +5,276 @@ require "erb"
5
5
  require "rest-client"
6
6
  require "json"
7
7
  require "active_support/hash_with_indifferent_access"
8
+ require "criteria"
8
9
 
9
10
  module ParseResource
10
11
 
11
12
  class Base
12
- # ParseResource::Base provides an easy way to use Ruby to interace with a Parse.com backend
13
- # Usage:
14
- # class Post < ParseResource::Base
15
- # fields :title, :author, :body
16
- # end
17
-
18
- include ActiveModel::Validations
19
- include ActiveModel::Conversion
20
- include ActiveModel::AttributeMethods
21
- extend ActiveModel::Naming
22
- extend ActiveModel::Callbacks
23
- HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
24
-
25
- # define_model_callbacks :initialize, :find, :only => :after
26
- define_model_callbacks :save, :create, :update, :destroy
27
-
28
-
29
- # Instantiates a ParseResource::Base object
30
- #
31
- # @params [Hash], [Boolean] a `Hash` of attributes and a `Boolean` that should be false only if the object already exists
32
- # @return [ParseResource::Base] an object that subclasses `Parseresource::Base`
33
- def initialize(attributes = {}, new=true)
34
- attributes = HashWithIndifferentAccess.new(attributes)
35
- if new
36
- @unsaved_attributes = attributes
37
- else
38
- @unsaved_attributes = {}
39
- end
40
- self.attributes = {}
41
- self.attributes.merge!(attributes)
42
- self.attributes unless self.attributes.empty?
43
- create_setters!
44
- end
45
-
46
- # Explicitly adds a field to the model.
47
- #
48
- # @param [Symbol] name the name of the field, eg `:author`.
49
- # @param [Boolean] val the return value of the field. Only use this within the class.
50
- def self.field(name, val=nil)
51
- class_eval do
52
- define_method(name) do
53
- @attributes[name] ? @attributes[name] : @unsaved_attributes[name]
13
+ # ParseResource::Base provides an easy way to use Ruby to interace with a Parse.com backend
14
+ # Usage:
15
+ # class Post < ParseResource::Base
16
+ # fields :title, :author, :body
17
+ # end
18
+
19
+ include ActiveModel::Validations
20
+ include ActiveModel::Conversion
21
+ include ActiveModel::AttributeMethods
22
+ extend ActiveModel::Naming
23
+ extend ActiveModel::Callbacks
24
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
25
+
26
+ define_model_callbacks :save, :create, :update, :destroy
27
+
28
+
29
+ # Instantiates a ParseResource::Base object
30
+ #
31
+ # @params [Hash], [Boolean] a `Hash` of attributes and a `Boolean` that should be false only if the object already exists
32
+ # @return [ParseResource::Base] an object that subclasses `Parseresource::Base`
33
+ def initialize(attributes = {}, new=true)
34
+ attributes = HashWithIndifferentAccess.new(attributes)
35
+ if new
36
+ @unsaved_attributes = attributes
37
+ else
38
+ @unsaved_attributes = {}
39
+ end
40
+ self.attributes = {}
41
+ self.attributes.merge!(attributes)
42
+ self.attributes unless self.attributes.empty?
43
+ create_setters!
54
44
  end
55
- define_method("#{name}=") do |val|
56
- @attributes[name] = val
57
- @unsaved_attributes[name] = val
58
- val
45
+
46
+ # Explicitly adds a field to the model.
47
+ #
48
+ # @param [Symbol] name the name of the field, eg `:author`.
49
+ # @param [Boolean] val the return value of the field. Only use this within the class.
50
+ def self.field(name, val=nil)
51
+ class_eval do
52
+ define_method(name) do
53
+ @attributes[name] ? @attributes[name] : @unsaved_attributes[name]
54
+ end
55
+ define_method("#{name}=") do |val|
56
+ @attributes[name] = val
57
+ @unsaved_attributes[name] = val
58
+ val
59
+ end
60
+ end
59
61
  end
60
- end
61
- end
62
62
 
63
- # Add multiple fields in one line. Same as `#field`, but accepts multiple args.
64
- #
65
- # @param [Array] *args an array of `Symbol`s, `eg :author, :body, :title`.
66
- def self.fields(*args)
67
- args.each {|f| field(f)}
68
- end
63
+ # Add multiple fields in one line. Same as `#field`, but accepts multiple args.
64
+ #
65
+ # @param [Array] *args an array of `Symbol`s, `eg :author, :body, :title`.
66
+ def self.fields(*args)
67
+ args.each {|f| field(f)}
68
+ end
69
69
 
70
- # Creates getter and setter methods for model fields
71
- #
72
- def create_setters!
73
- @attributes.each_pair do |k,v|
74
- self.class.send(:define_method, "#{k}=") do |val|
75
- if k.is_a?(Symbol)
76
- k = k.to_s
70
+ # Creates getter and setter methods for model fields
71
+ #
72
+ def create_setters!
73
+ @attributes.each_pair do |k,v|
74
+ self.class.send(:define_method, "#{k}=") do |val|
75
+ if k.is_a?(Symbol)
76
+ k = k.to_s
77
+ end
78
+ @attributes[k.to_s] = val
79
+ @unsaved_attributes[k.to_s] = val
80
+ val
81
+ end
82
+ self.class.send(:define_method, "#{k}") do
83
+ if k.is_a?(Symbol)
84
+ k = k.to_s
85
+ end
86
+
87
+ @attributes[k.to_s]
88
+ end
77
89
  end
78
- @attributes[k.to_s] = val
79
- @unsaved_attributes[k.to_s] = val
80
- val
81
90
  end
82
- self.class.send(:define_method, "#{k}") do
83
- if k.is_a?(Symbol)
84
- k = k.to_s
85
- end
86
91
 
87
- @attributes[k.to_s]
88
- end
89
- end
90
- end
92
+ class << self
91
93
 
92
- class << self
93
- def has_one(child_name)
94
- class_eval do
94
+ @@settings ||= nil
95
95
 
96
- define_method("#{child_name}") do
97
- child_name
96
+ # Explicitly set Parse.com API keys.
97
+ #
98
+ # @param [String] app_id the Application ID of your Parse database
99
+ # @param [String] master_key the Master Key of your Parse database
100
+ def load!(app_id, master_key)
101
+ @@settings = {"app_id" => app_id, "master_key" => master_key}
98
102
  end
99
103
 
100
- define_method("#{child_name}=") do |child_object|
101
- [child_object, child_name]
104
+ # Creates a RESTful resource
105
+ # sends requests to [base_uri]/[classname]
106
+ #
107
+ def resource
108
+ if @@settings.nil?
109
+ path = "config/parse_resource.yml"
110
+ environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"]
111
+ @@settings = YAML.load(ERB.new(File.new(path).read).result)[environment]
112
+ end
113
+ base_uri = "https://api.parse.com/1/classes/#{model_name}"
114
+ app_id = @@settings['app_id']
115
+ master_key = @@settings['master_key']
116
+ RestClient::Resource.new(base_uri, app_id, master_key)
102
117
  end
103
118
 
104
- end
105
- end
106
-
107
- def belongs_to(name)
108
- class_eval do
119
+ # Find a ParseResource::Base object by ID
120
+ #
121
+ # @param [String] id the ID of the Parse object you want to find.
122
+ # @return [ParseResource] an object that subclasses ParseResource.
123
+ def find(id)
124
+ where(:objectId => id).first
125
+ end
109
126
 
110
- define_method("#{parent_name}") do
111
- name
127
+ # Find a ParseResource::Base object by chaining #where method calls.
128
+ #
129
+ def where(*args)
130
+ Criteria.new(self).where(*args)
112
131
  end
113
132
 
114
- define_method("#{parent_name}=") do |parent_object|
115
- [parent_name, parent_object]
133
+ # Add this at the end of a method chain to get the count of objects, instead of an Array of objects
134
+ def count
135
+ #https://www.parse.com/docs/rest#queries-counting
136
+ Criteria.new(self).count(1)
116
137
  end
117
138
 
118
- end
119
- end
139
+ # Find all ParseResource::Base objects for that model.
140
+ #
141
+ # @return [Array] an `Array` of objects that subclass `ParseResource`.
142
+ def all
143
+ Criteria.new(self).all
144
+ end
120
145
 
146
+ # Find the first object. Fairly random, not based on any specific condition.
147
+ #
148
+ def first
149
+ Criteria.new(self).limit(1).first
150
+ end
121
151
 
122
- @@settings ||= nil
152
+ # Limits the number of objects returned
153
+ #
154
+ def limit(n)
155
+ Criteria.new(self).limit(n)
156
+ end
123
157
 
124
- # Explicitly set Parse.com API keys.
125
- #
126
- # @param [String] app_id the Application ID of your Parse database
127
- # @param [String] master_key the Master Key of your Parse database
128
- def load!(app_id, master_key)
129
- @@settings = {"app_id" => app_id, "master_key" => master_key}
130
- end
158
+ # Create a ParseResource::Base object.
159
+ #
160
+ # @param [Hash] attributes a `Hash` of attributes
161
+ # @return [ParseResource] an object that subclasses `ParseResource`. Or returns `false` if object fails to save.
162
+ def create(attributes = {})
163
+ attributes = HashWithIndifferentAccess.new(attributes)
164
+ new(attributes).save
165
+ end
131
166
 
132
- # Creates a RESTful resource
133
- # sends requests to [base_uri]/[classname]
134
- #
135
- def resource
136
- if @@settings.nil?
137
- path = "config/parse_resource.yml"
138
- environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"]
139
- @@settings = YAML.load(ERB.new(File.new(path).read).result)[environment]
140
- end
141
- base_uri = "https://api.parse.com/1/classes/#{model_name}"
142
- app_id = @@settings['app_id']
143
- master_key = @@settings['master_key']
144
- RestClient::Resource.new(base_uri, app_id, master_key)
145
- end
167
+ def destroy_all
168
+ all.each do |object|
169
+ object.destroy
170
+ end
171
+ end
146
172
 
147
- # Find a ParseResource::Baseobject by ID
148
- #
149
- # @param [String] id the ID of the Parse object you want to find.
150
- # @return [ParseResource] an object that subclasses ParseResource.
151
- def find(id)
152
- where(:objectId => id).first
153
- end
173
+ def class_attributes
174
+ @class_attributes ||= {}
175
+ end
154
176
 
155
- # Find a ParseResource::Baseobject by a `Hash` of conditions.
156
- #
157
- # @param [Hash] parameters a `Hash` of conditions.
158
- # @return [Array] an `Array` of objects that subclass `ParseResource`.
159
- def where(parameters)
160
- resp = resource.get(:params => {:where => parameters.to_json})
161
- results = JSON.parse(resp)['results']
162
- results.map {|r| model_name.constantize.new(r, false)}
163
- end
177
+ end
164
178
 
165
- # Find all ParseResource::Baseobjects for that model.
166
- #
167
- # @return [Array] an `Array` of objects that subclass `ParseResource`.
168
- def all
169
- resp = resource.get
170
- results = JSON.parse(resp)['results']
171
- results.map {|r| model_name.constantize.new(r, false)}
172
- end
179
+ def persisted?
180
+ if id
181
+ true
182
+ else
183
+ false
184
+ end
185
+ end
173
186
 
174
- # Create a ParseResource::Baseobject.
175
- #
176
- # @param [Hash] attributes a `Hash` of attributes
177
- # @return [ParseResource] an object that subclasses `ParseResource`. Or returns `false` if object fails to save.
178
- def create(attributes = {})
179
- attributes = HashWithIndifferentAccess.new(attributes)
180
- new(attributes).save
181
- end
187
+ def new?
188
+ !persisted?
189
+ end
182
190
 
183
- # Find the first object. Fairly random, not based on any specific condition.
184
- #
185
- def first
186
- all.first
187
- end
191
+ # delegate from Class method
192
+ def resource
193
+ self.class.resource
194
+ end
188
195
 
189
- def class_attributes
190
- @class_attributes ||= {}
191
- end
196
+ # create RESTful resource for the specific Parse object
197
+ # sends requests to [base_uri]/[classname]/[objectId]
198
+ def instance_resource
199
+ self.class.resource["#{self.id}"]
200
+ end
192
201
 
193
- end
202
+ def create
203
+ resp = self.resource.post(@unsaved_attributes.to_json, :content_type => "application/json")
204
+ @attributes.merge!(JSON.parse(resp))
205
+ @attributes.merge!(@unsaved_attributes)
206
+ attributes = HashWithIndifferentAccess.new(attributes)
207
+ @unsaved_attributes = {}
208
+ create_setters!
209
+ self
210
+ end
194
211
 
195
- def persisted?
196
- if id
197
- true
198
- else
199
- false
200
- end
201
- end
212
+ def save
213
+ if valid?
214
+ run_callbacks :save do
215
+ new? ? create : update
216
+ end
217
+ else
218
+ false
219
+ end
220
+ rescue false
221
+ end
202
222
 
203
- def new?
204
- !persisted?
205
- end
223
+ def update(attributes = {})
224
+ attributes = HashWithIndifferentAccess.new(attributes)
225
+ @unsaved_attributes.merge!(attributes)
206
226
 
207
- # delegate from Class method
208
- def resource
209
- self.class.resource
210
- end
227
+ put_attrs = @unsaved_attributes
228
+ put_attrs.delete('objectId')
229
+ put_attrs.delete('createdAt')
230
+ put_attrs.delete('updatedAt')
231
+ put_attrs = put_attrs.to_json
211
232
 
212
- # create RESTful resource for the specific Parse object
213
- # sends requests to [base_uri]/[classname]/[objectId]
214
- def instance_resource
215
- self.class.resource["#{self.id}"]
216
- end
233
+ resp = self.instance_resource.put(put_attrs, :content_type => "application/json")
217
234
 
218
- def create
219
- resp = self.resource.post(@unsaved_attributes.to_json, :content_type => "application/json")
220
- @attributes.merge!(JSON.parse(resp))
221
- @attributes.merge!(@unsaved_attributes)
222
- attributes = HashWithIndifferentAccess.new(attributes)
223
- @unsaved_attributes = {}
224
- create_setters!
225
- self
226
- end
235
+ @attributes.merge!(JSON.parse(resp))
236
+ @attributes.merge!(@unsaved_attributes)
237
+ @unsaved_attributes = {}
238
+ create_setters!
227
239
 
228
- def save
229
- if valid?
230
- run_callbacks :save do
231
- new? ? create : update
240
+ self
232
241
  end
233
- else
234
- false
235
- end
236
- rescue false
237
- end
238
-
239
- def update(attributes = {})
240
- attributes = HashWithIndifferentAccess.new(attributes)
241
- @unsaved_attributes.merge!(attributes)
242
-
243
- put_attrs = @unsaved_attributes
244
- put_attrs.delete('objectId')
245
- put_attrs.delete('createdAt')
246
- put_attrs.delete('updatedAt')
247
- put_attrs = put_attrs.to_json
248
242
 
249
- resp = self.instance_resource.put(put_attrs, :content_type => "application/json")
250
-
251
- @attributes.merge!(JSON.parse(resp))
252
- @attributes.merge!(@unsaved_attributes)
253
- @unsaved_attributes = {}
254
- create_setters!
243
+ def update_attributes(attributes = {})
244
+ self.update(attributes)
245
+ end
255
246
 
256
- self
257
- end
247
+ def destroy
248
+ self.instance_resource.delete
249
+ @attributes = {}
250
+ @unsaved_attributes = {}
251
+ nil
252
+ end
258
253
 
259
- def update_attributes(attributes = {})
260
- self.update(attributes)
261
- end
254
+ # provides access to @attributes for getting and setting
255
+ def attributes
256
+ @attributes ||= self.class.class_attributes
257
+ @attributes
258
+ end
262
259
 
263
- def destroy
264
- self.instance_resource.delete
265
- @attributes = {}
266
- @unsaved_attributes = {}
267
- nil
268
- end
260
+ def attributes=(n)
261
+ @attributes = n
262
+ @attributes
263
+ end
269
264
 
270
- # provides access to @attributes for getting and setting
271
- def attributes
272
- @attributes ||= self.class.class_attributes
273
- @attributes
274
- end
265
+ # aliasing for idiomatic Ruby
266
+ def id; self.objectId rescue nil; end
275
267
 
276
- def attributes=(n)
277
- @attributes = n
278
- @attributes
279
- end
268
+ def created_at; self.createdAt; end
280
269
 
281
- # aliasing for idiomatic Ruby
282
- def id; self.objectId rescue nil; end
270
+ def updated_at; self.updatedAt rescue nil; end
283
271
 
284
- def created_at; self.createdAt; end
272
+ def self.included(base)
273
+ base.extend(ClassMethods)
274
+ end
285
275
 
286
- def updated_at; self.updatedAt rescue nil; end
276
+ module ClassMethods
277
+ end
287
278
 
288
279
  end
289
280
  end
data/lib/criteria.rb ADDED
@@ -0,0 +1,79 @@
1
+ class Criteria
2
+
3
+ def initialize(klass)
4
+ @klass = klass
5
+ end
6
+
7
+ def criteria
8
+ @criteria ||= { :conditions => {} }
9
+ end
10
+
11
+ def where(args)
12
+ criteria[:conditions].merge!(args)
13
+ self
14
+ end
15
+
16
+ def limit(limit)
17
+ criteria[:limit] = limit
18
+ self
19
+ end
20
+
21
+ #TODO: make this work
22
+ #def skip(skip)
23
+ # criteria[:skip] = skip
24
+ # self
25
+ #end
26
+
27
+ def count(count)
28
+ criteria[:count] = count
29
+ #self
30
+ all
31
+ end
32
+
33
+ #def each(&block)
34
+ # resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
35
+ # results = JSON.parse(resp)['results']
36
+ # results.map {|r| @klass.model_name.constantize.new(r, false)}.each(&block)
37
+ #end
38
+
39
+ #def first
40
+ # resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
41
+ # results = JSON.parse(resp)['results']
42
+ # results.map {|r| @klass.model_name.constantize.new(r, false)}.first
43
+ #end
44
+
45
+ #def length
46
+ # resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
47
+ # results = JSON.parse(resp)['results']
48
+ # results.length
49
+ #end
50
+
51
+ def all
52
+ params = {}
53
+ params.merge!({:where => criteria[:conditions].to_json}) if criteria[:conditions]
54
+ params.merge!({:limit => criteria[:limit].to_json}) if criteria[:limit]
55
+ params.merge!({:skip => criteria[:skip].to_json}) if criteria[:skip]
56
+ params.merge!({:count => criteria[:count].to_json}) if criteria[:count]
57
+
58
+ resp = @klass.resource.get(:params => params)
59
+
60
+ if criteria[:count] == 1
61
+ results = JSON.parse(resp)['count']
62
+ return results.to_i
63
+ else
64
+ results = JSON.parse(resp)['results']
65
+ return results.map {|r| @klass.model_name.constantize.new(r, false)}
66
+ end
67
+ end
68
+
69
+ def method_missing(meth)
70
+ if Array.method_defined?(meth)
71
+ all.send(meth)
72
+ else
73
+ super
74
+ end
75
+ end
76
+
77
+
78
+
79
+ end
@@ -1,4 +1,5 @@
1
1
  require 'base'
2
+ require 'criteria'
2
3
 
3
4
  module ParseResource
4
5
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "parse_resource"
8
- s.version = "1.6.0"
8
+ s.version = "1.6.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alan deLevie"]
12
- s.date = "2011-12-07"
12
+ s.date = "2011-12-09"
13
13
  s.description = ""
14
14
  s.email = "adelevie@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
25
25
  "Rakefile",
26
26
  "VERSION",
27
27
  "lib/base.rb",
28
+ "lib/criteria.rb",
28
29
  "lib/examples/post.rb",
29
30
  "lib/parse_resource.rb",
30
- "lib/parse_resource_old.rb",
31
31
  "parse_resource.gemspec",
32
32
  "rdoc/ParseResource.html",
33
33
  "rdoc/created.rid",