parse_resource 1.6.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
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",