Class: ParseResource::Base
- Inherits:
-
Object
- Object
- ParseResource::Base
- Extended by:
- ActiveModel::Callbacks, ActiveModel::Naming
- Includes:
- ActiveModel::AttributeMethods, ActiveModel::Conversion, ActiveModel::Validations, QueryMethods
- Defined in:
- lib/parse_resource/base.rb
Direct Known Subclasses
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- HashWithIndifferentAccess =
ActiveSupport::HashWithIndifferentAccess
Instance Attribute Summary collapse
-
#error_instances ⇒ Object
Returns the value of attribute error_instances.
Class Method Summary collapse
-
.batch_save(save_objects, slice_size = 20, method = nil) ⇒ Object
Batch requests Sends multiple requests to /batch Set slice_size to send larger batches.
-
.belongs_to(parent, options = {}) ⇒ Object
Similar to its ActiveRecord counterpart.
- .chunk(attribute) ⇒ Object
-
.class_attributes ⇒ Object
Replaced with a batch destroy_all method.
-
.create(attributes = {}) ⇒ ParseResource
Create a ParseResource::Base object.
- .delete_all(o) ⇒ Object
- .destroy_all(objects = nil) ⇒ Object
-
.field(fname, val = nil) ⇒ Object
Explicitly adds a field to the model.
-
.fields(*args) ⇒ Object
Add multiple fields in one line.
-
.find(id) ⇒ ParseResource
Find a ParseResource::Base object by ID.
- .included(base) ⇒ Object
-
.load!(app_id, master_key) ⇒ Object
Explicitly set Parse.com API keys.
- .load_settings ⇒ Object
- .merge_all_attributes(objects, response) ⇒ Object
- .method_missing(method_name, *args) ⇒ Object
-
.model_base_uri ⇒ Object
Gets the current class’s Parse.com base_uri.
-
.model_name_uri ⇒ Object
Gets the current class’s model name for the URI.
-
.resource ⇒ Object
Creates a RESTful resource sends requests to [base_uri]/.
- .save_all(objects) ⇒ Object
- .settings ⇒ Object
- .to_date_object(date) ⇒ Object
-
.upload(file_instance, filename, options = {}) ⇒ Object
Creates a RESTful resource for file uploads sends requests to [base_uri]/files.
-
.where(*args) ⇒ Object
Find a ParseResource::Base object by chaining #where method calls.
Instance Method Summary collapse
-
#attributes ⇒ Object
provides access to @attributes for getting and setting.
-
#attributes=(n) ⇒ Object
AKN 2012-06-18: Shouldn’t this also be setting @unsaved_attributes?.
- #attributes_for_saving ⇒ Object
- #clean? ⇒ Boolean
- #create ⇒ Object
-
#create_getters!(k, v) ⇒ Object
Creates getter methods for model fields.
-
#create_setters!(k, v) ⇒ Object
Creates setter methods for model fields.
- #create_setters_and_getters! ⇒ Object
- #created_at ⇒ Object
- #destroy ⇒ Object
- #dirty? ⇒ Boolean
- #get_attribute(k) ⇒ Object
-
#id ⇒ Object
aliasing for idiomatic Ruby.
-
#initialize(attributes = {}, new = true) ⇒ ParseResource::Base
constructor
Instantiates a ParseResource::Base object.
-
#instance_resource ⇒ Object
create RESTful resource for the specific Parse object sends requests to [base_uri]//[objectId].
-
#merge_attributes(results) ⇒ Object
Merges in the return value of a save and resets the unsaved_attributes.
-
#model_base_uri ⇒ Object
Gets the current instance’s parent class’s Parse.com base_uri.
- #new? ⇒ Boolean
- #objectId ⇒ Object
- #persisted? ⇒ Boolean
- #pointerize(hash) ⇒ Object
- #post_result(resp, req, res, &block) ⇒ Object
- #reload ⇒ Object
-
#resource ⇒ Object
delegate from Class method.
- #save ⇒ Object
- #set_attribute(k, v) ⇒ Object
- #to_pointer ⇒ Object
- #update(attributes = {}) ⇒ Object
- #update_attributes(attributes = {}) ⇒ Object
- #updated_at ⇒ Object
Constructor Details
#initialize(attributes = {}, new = true) ⇒ ParseResource::Base
Instantiates a ParseResource::Base object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/parse_resource/base.rb', line 39 def initialize(attributes = {}, new=true) #attributes = HashWithIndifferentAccess.new(attributes) if new @unsaved_attributes = attributes @unsaved_attributes.stringify_keys! else @unsaved_attributes = {} end self.attributes = {} self.error_instances = [] self.attributes.merge!(attributes) self.attributes unless self.attributes.empty? create_setters_and_getters! end |
Instance Attribute Details
#error_instances ⇒ Object
Returns the value of attribute error_instances.
31 32 33 |
# File 'lib/parse_resource/base.rb', line 31 def error_instances @error_instances end |
Class Method Details
.batch_save(save_objects, slice_size = 20, method = nil) ⇒ Object
Batch requests Sends multiple requests to /batch Set slice_size to send larger batches. Defaults to 20 to prevent timeouts. Parse doesn’t support batches of over 20.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/parse_resource/base.rb', line 210 def self.batch_save(save_objects, slice_size = 20, method = nil) return true if save_objects.blank? load_settings base_uri = "https://api.parse.com/1/batch" app_id = @@settings['app_id'] master_key = @@settings['master_key'] res = RestClient::Resource.new(base_uri, app_id, master_key) # Batch saves seem to fail if they're too big. We'll slice it up into multiple posts if they are. save_objects.each_slice(slice_size) do |objects| # attributes_for_saving batch_json = { "requests" => [] } objects.each do |item| method ||= (item.new?) ? "POST" : "PUT" object_path = "/1/#{item.class.model_name_uri}" object_path = "#{object_path}/#{item.id}" if item.id json = { "method" => method, "path" => object_path } json["body"] = item.attributes_for_saving unless method == "DELETE" batch_json["requests"] << json end res.post(batch_json.to_json, :content_type => "application/json") do |resp, req, res, &block| response = JSON.parse(resp) rescue nil if resp.code == 400 puts resp return false end if response && response.is_a?(Array) && response.length == objects.length merge_all_attributes(objects, response) unless method == "DELETE" end end end true end |
.belongs_to(parent, options = {}) ⇒ Object
Similar to its ActiveRecord counterpart.
88 89 90 |
# File 'lib/parse_resource/base.rb', line 88 def self.belongs_to(parent, = {}) field(parent) end |
.chunk(attribute) ⇒ Object
326 327 328 |
# File 'lib/parse_resource/base.rb', line 326 def self.chunk(attribute) Query.new(self).chunk(attribute) end |
.class_attributes ⇒ Object
Replaced with a batch destroy_all method. def self.destroy_all(all)
all.each do |object|
object.destroy
end
end
348 349 350 |
# File 'lib/parse_resource/base.rb', line 348 def self.class_attributes @class_attributes ||= {} end |
.create(attributes = {}) ⇒ ParseResource
Create a ParseResource::Base object.
334 335 336 337 338 339 |
# File 'lib/parse_resource/base.rb', line 334 def self.create(attributes = {}) attributes = HashWithIndifferentAccess.new(attributes) obj = new(attributes) obj.save obj end |
.delete_all(o) ⇒ Object
268 269 270 |
# File 'lib/parse_resource/base.rb', line 268 def self.delete_all(o) raise StandardError.new("Parse Resource: delete_all doesn't exist. Did you mean destroy_all?") end |
.destroy_all(objects = nil) ⇒ Object
263 264 265 266 |
# File 'lib/parse_resource/base.rb', line 263 def self.destroy_all(objects=nil) objects ||= self.all batch_save(objects, 20, "DELETE") end |
.field(fname, val = nil) ⇒ Object
Explicitly adds a field to the model.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/parse_resource/base.rb', line 60 def self.field(fname, val=nil) fname = fname.to_sym class_eval do define_method(fname) do get_attribute("#{fname}") end end unless self.respond_to? "#{fname}=" class_eval do define_method("#{fname}=") do |val| set_attribute("#{fname}", val) val end end end end |
.fields(*args) ⇒ Object
Add multiple fields in one line. Same as ‘#field`, but accepts multiple args.
81 82 83 |
# File 'lib/parse_resource/base.rb', line 81 def self.fields(*args) args.each {|f| field(f)} end |
.find(id) ⇒ ParseResource
Find a ParseResource::Base object by ID
311 312 313 314 |
# File 'lib/parse_resource/base.rb', line 311 def self.find(id) raise RecordNotFound if id.blank? where(:objectId => id).first end |
.included(base) ⇒ Object
547 548 549 |
# File 'lib/parse_resource/base.rb', line 547 def self.included(base) base.extend(ClassMethods) end |
.load!(app_id, master_key) ⇒ Object
Explicitly set Parse.com API keys.
163 164 165 |
# File 'lib/parse_resource/base.rb', line 163 def self.load!(app_id, master_key) @@settings = {"app_id" => app_id, "master_key" => master_key} end |
.load_settings ⇒ Object
272 273 274 275 276 277 278 279 |
# File 'lib/parse_resource/base.rb', line 272 def self.load_settings @@settings ||= begin path = "config/parse_resource.yml" environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"] YAML.load(ERB.new(File.new(path).read).result)[environment] end @@settings end |
.merge_all_attributes(objects, response) ⇒ Object
250 251 252 253 254 255 256 257 |
# File 'lib/parse_resource/base.rb', line 250 def self.merge_all_attributes(objects, response) i = 0 objects.each do |item| item.merge_attributes(response[i]["success"]) if response[i] && response[i]["success"] i += 1 end nil end |
.method_missing(method_name, *args) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/parse_resource/base.rb', line 115 def self.method_missing(method_name, *args) method_name = method_name.to_s if method_name.start_with?("find_by_") attrib = method_name.gsub(/^find_by_/,"") finder_name = "find_all_by_#{attrib}" define_singleton_method(finder_name) do |target_value| where({attrib.to_sym => target_value}).first end send(finder_name, args[0]) elsif method_name.start_with?("find_all_by_") attrib = method_name.gsub(/^find_all_by_/,"") finder_name = "find_all_by_#{attrib}" define_singleton_method(finder_name) do |target_value| where({attrib.to_sym => target_value}).all end send(finder_name, args[0]) else super(method_name.to_sym, *args) end end |
.model_base_uri ⇒ Object
Gets the current class’s Parse.com base_uri
183 184 185 |
# File 'lib/parse_resource/base.rb', line 183 def self.model_base_uri "https://api.parse.com/1/#{model_name_uri}" end |
.model_name_uri ⇒ Object
Gets the current class’s model name for the URI
172 173 174 175 176 177 178 179 180 |
# File 'lib/parse_resource/base.rb', line 172 def self.model_name_uri if self.model_name == "User" "users" elsif self.model_name == "Installation" "installations" else "classes/#{self.model_name}" end end |
.resource ⇒ Object
Creates a RESTful resource sends requests to [base_uri]/
196 197 198 199 200 201 202 203 |
# File 'lib/parse_resource/base.rb', line 196 def self.resource load_settings #refactor to settings['app_id'] etc app_id = @@settings['app_id'] master_key = @@settings['master_key'] RestClient::Resource.new(self.model_base_uri, app_id, master_key) end |
.save_all(objects) ⇒ Object
259 260 261 |
# File 'lib/parse_resource/base.rb', line 259 def self.save_all(objects) batch_save(objects) end |
.settings ⇒ Object
167 168 169 |
# File 'lib/parse_resource/base.rb', line 167 def self.settings load_settings end |
.to_date_object(date) ⇒ Object
99 100 101 102 |
# File 'lib/parse_resource/base.rb', line 99 def self.to_date_object(date) date = date.to_time if date.respond_to?(:to_time) {"__type" => "Date", "iso" => date.iso8601} if date && (date.is_a?(Date) || date.is_a?(DateTime) || date.is_a?(Time)) end |
.upload(file_instance, filename, options = {}) ⇒ Object
Creates a RESTful resource for file uploads sends requests to [base_uri]/files
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/parse_resource/base.rb', line 285 def self.upload(file_instance, filename, ={}) load_settings base_uri = "https://api.parse.com/1/files" #refactor to settings['app_id'] etc app_id = @@settings['app_id'] master_key = @@settings['master_key'] [:content_type] ||= 'image/jpg' # TODO: Guess mime type here. file_instance = File.new(file_instance, 'rb') if file_instance.is_a? String filename = filename.parameterize private_resource = RestClient::Resource.new "#{base_uri}/#{filename}", app_id, master_key private_resource.post(file_instance, ) do |resp, req, res, &block| return false if resp.code == 400 return JSON.parse(resp) rescue {"code" => 0, "error" => "unknown error"} end false end |
Instance Method Details
#attributes ⇒ Object
provides access to @attributes for getting and setting
492 493 494 495 |
# File 'lib/parse_resource/base.rb', line 492 def attributes @attributes ||= self.class.class_attributes @attributes end |
#attributes=(n) ⇒ Object
AKN 2012-06-18: Shouldn’t this also be setting @unsaved_attributes?
498 499 500 501 |
# File 'lib/parse_resource/base.rb', line 498 def attributes=(n) @attributes = n @attributes end |
#attributes_for_saving ⇒ Object
451 452 453 454 455 456 457 458 |
# File 'lib/parse_resource/base.rb', line 451 def attributes_for_saving @unsaved_attributes = pointerize(@unsaved_attributes) put_attrs = @unsaved_attributes put_attrs.delete('objectId') put_attrs.delete('createdAt') put_attrs.delete('updatedAt') put_attrs end |
#clean? ⇒ Boolean
487 488 489 |
# File 'lib/parse_resource/base.rb', line 487 def clean? !dirty? end |
#create ⇒ Object
404 405 406 407 408 409 410 |
# File 'lib/parse_resource/base.rb', line 404 def create attrs = attributes_for_saving.to_json opts = {:content_type => "application/json"} result = self.resource.post(attrs, opts) do |resp, req, res, &block| return post_result(resp, req, res, &block) end end |
#create_getters!(k, v) ⇒ Object
Creates getter methods for model fields
142 143 144 145 146 147 148 |
# File 'lib/parse_resource/base.rb', line 142 def create_getters!(k,v) unless self.respond_to? "#{k}" self.class.send(:define_method, "#{k}") do get_attribute("#{k}") end end end |
#create_setters!(k, v) ⇒ Object
Creates setter methods for model fields
105 106 107 108 109 110 111 112 113 |
# File 'lib/parse_resource/base.rb', line 105 def create_setters!(k,v) unless self.respond_to? "#{k}=" self.class.send(:define_method, "#{k}=") do |val| set_attribute("#{k}", val) val end end end |
#create_setters_and_getters! ⇒ Object
150 151 152 153 154 155 |
# File 'lib/parse_resource/base.rb', line 150 def create_setters_and_getters! @attributes.each_pair do |k,v| create_setters!(k,v) create_getters!(k,v) end end |
#created_at ⇒ Object
543 |
# File 'lib/parse_resource/base.rb', line 543 def created_at; get_attribute("createdAt"); end |
#destroy ⇒ Object
464 465 466 467 468 469 470 471 |
# File 'lib/parse_resource/base.rb', line 464 def destroy if self.instance_resource.delete @attributes = {} @unsaved_attributes = {} return true end false end |
#dirty? ⇒ Boolean
483 484 485 |
# File 'lib/parse_resource/base.rb', line 483 def dirty? @unsaved_attributes.length > 0 end |
#get_attribute(k) ⇒ Object
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/parse_resource/base.rb', line 503 def get_attribute(k) attrs = @unsaved_attributes[k.to_s] ? @unsaved_attributes : @attributes case attrs[k] when Hash klass_name = attrs[k]["className"] klass_name = "User" if klass_name == "_User" case attrs[k]["__type"] when "Pointer" result = klass_name.constantize.find(attrs[k]["objectId"]) when "Object" result = klass_name.constantize.new(attrs[k], false) when "Date" result = DateTime.parse(attrs[k]["iso"]).to_time_in_current_zone when "File" result = attrs[k]["url"] when "GeoPoint" result = ParseGeoPoint.new(attrs[k]) end #todo: support other types https://www.parse.com/docs/rest#objects-types else result = attrs["#{k}"] end result end |
#id ⇒ Object
aliasing for idiomatic Ruby
540 |
# File 'lib/parse_resource/base.rb', line 540 def id; get_attribute("objectId") rescue nil; end |
#instance_resource ⇒ Object
create RESTful resource for the specific Parse object sends requests to [base_uri]//[objectId]
371 372 373 |
# File 'lib/parse_resource/base.rb', line 371 def instance_resource self.class.resource["#{self.id}"] end |
#merge_attributes(results) ⇒ Object
Merges in the return value of a save and resets the unsaved_attributes
426 427 428 429 430 431 432 |
# File 'lib/parse_resource/base.rb', line 426 def merge_attributes(results) @attributes.merge!(results) @attributes.merge!(@unsaved_attributes) @unsaved_attributes = {} create_setters_and_getters! @attributes end |
#model_base_uri ⇒ Object
Gets the current instance’s parent class’s Parse.com base_uri
188 189 190 |
# File 'lib/parse_resource/base.rb', line 188 def model_base_uri self.class.send(:model_base_uri) end |
#new? ⇒ Boolean
360 361 362 |
# File 'lib/parse_resource/base.rb', line 360 def new? !persisted? end |
#objectId ⇒ Object
541 |
# File 'lib/parse_resource/base.rb', line 541 def objectId; get_attribute("objectId") rescue nil; end |
#persisted? ⇒ Boolean
352 353 354 355 356 357 358 |
# File 'lib/parse_resource/base.rb', line 352 def persisted? if id true else false end end |
#pointerize(hash) ⇒ Object
375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/parse_resource/base.rb', line 375 def pointerize(hash) new_hash = {} hash.each do |k, v| if v.respond_to?(:to_pointer) new_hash[k] = v.to_pointer elsif v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime) new_hash[k] = self.class.to_date_object(v) else new_hash[k] = v end end new_hash end |
#post_result(resp, req, res, &block) ⇒ Object
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 |
# File 'lib/parse_resource/base.rb', line 434 def post_result(resp, req, res, &block) if resp.code.to_s == "200" || resp.code.to_s == "201" merge_attributes(JSON.parse(resp)) return true else error_response = JSON.parse(resp) if error_response["error"] pe = ParseError.new(error_response["code"], error_response["error"]) else pe = ParseError.new(resp.code.to_s) end self.errors.add(pe.code.to_s.to_sym, pe.msg) self.error_instances << pe return false end end |
#reload ⇒ Object
473 474 475 476 477 478 479 480 481 |
# File 'lib/parse_resource/base.rb', line 473 def reload return false if new? fresh_object = self.class.find(id) @attributes.update(fresh_object.instance_variable_get('@attributes')) @unsaved_attributes = {} self end |
#resource ⇒ Object
delegate from Class method
365 366 367 |
# File 'lib/parse_resource/base.rb', line 365 def resource self.class.resource end |
#save ⇒ Object
389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'lib/parse_resource/base.rb', line 389 def save if valid? run_callbacks :save do if new? return create else return update end end else false end rescue false end |
#set_attribute(k, v) ⇒ Object
527 528 529 530 531 532 533 534 535 536 |
# File 'lib/parse_resource/base.rb', line 527 def set_attribute(k, v) if v.is_a?(Date) || v.is_a?(Time) || v.is_a?(DateTime) v = self.class.to_date_object(v) elsif v.respond_to?(:to_pointer) v = v.to_pointer end @unsaved_attributes[k.to_s] = v unless v == @attributes[k.to_s] # || @unsaved_attributes[k.to_s] @attributes[k.to_s] = v v end |
#to_pointer ⇒ Object
92 93 94 95 96 97 |
# File 'lib/parse_resource/base.rb', line 92 def to_pointer klass_name = self.class.model_name klass_name = "_User" if klass_name == "User" klass_name = "_Installation" if klass_name == "Installation" {"__type" => "Pointer", "className" => klass_name.to_s, "objectId" => self.id} end |
#update(attributes = {}) ⇒ Object
412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/parse_resource/base.rb', line 412 def update(attributes = {}) attributes = HashWithIndifferentAccess.new(attributes) @unsaved_attributes.merge!(attributes) put_attrs = attributes_for_saving.to_json opts = {:content_type => "application/json"} result = self.instance_resource.put(put_attrs, opts) do |resp, req, res, &block| return post_result(resp, req, res, &block) end end |
#update_attributes(attributes = {}) ⇒ Object
460 461 462 |
# File 'lib/parse_resource/base.rb', line 460 def update_attributes(attributes = {}) self.update(attributes) end |
#updated_at ⇒ Object
545 |
# File 'lib/parse_resource/base.rb', line 545 def updated_at; get_attribute("updatedAt"); rescue nil; end |