Class: ParseResource::Base

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Callbacks, ActiveModel::Naming
Includes:
ActiveModel::AttributeMethods, ActiveModel::Conversion, ActiveModel::Validations, ActiveModel::Validations::Callbacks, QueryMethods
Defined in:
lib/parse_resource/base.rb

Direct Known Subclasses

ParseRole, ParseUser

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

HashWithIndifferentAccess =
ActiveSupport::HashWithIndifferentAccess
@@has_many_relations =

ParseResource::Base provides an easy way to use Ruby to interace with a Parse.com backend Usage:

class Post < ParseResource::Base
  fields :title, :author, :body
end
[]
@@belongs_to_relations =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, new = true) ⇒ ParseResource::Base

Instantiates a ParseResource::Base object


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/parse_resource/base.rb', line 44

def initialize(attributes = {}, new=true)
  #attributes = HashWithIndifferentAccess.new(attributes)

  if new
    @unsaved_attributes = attributes
    @unsaved_attributes.stringify_keys!
  else
    @unsaved_attributes = {}
  end
  @attributes = {}
  self.error_instances = []

  self.attributes.merge!(attributes)
  self.attributes unless self.attributes.empty?
  create_setters_and_getters!
end

Instance Attribute Details

#error_instancesObject

Returns the value of attribute error_instances


36
37
38
# File 'lib/parse_resource/base.rb', line 36

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.


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/parse_resource/base.rb', line 230

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
        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.


93
94
95
96
# File 'lib/parse_resource/base.rb', line 93

def self.belongs_to(parent, options = {})
  field(parent)
  @@belongs_to_relations << parent
end

.belongs_to_relationsObject


681
682
683
# File 'lib/parse_resource/base.rb', line 681

def self.belongs_to_relations
  @@belongs_to_relations
end

.chunk(attribute) ⇒ Object


365
366
367
# File 'lib/parse_resource/base.rb', line 365

def self.chunk(attribute)
  Query.new(self).chunk(attribute)
end

.class_attributesObject

Replaced with a batch destroy_all method. def self.destroy_all(all)

all.each do |object|
  object.destroy
end

end


387
388
389
# File 'lib/parse_resource/base.rb', line 387

def self.class_attributes
  @class_attributes ||= {}
end

.create(attributes = {}) ⇒ ParseResource

Create a ParseResource::Base object.


373
374
375
376
377
378
# File 'lib/parse_resource/base.rb', line 373

def self.create(attributes = {})
  attributes = HashWithIndifferentAccess.new(attributes)
  obj = new(attributes)
  obj.save
  obj
end

.delete_all(o) ⇒ Object

Raises:

  • (StandardError)

287
288
289
# File 'lib/parse_resource/base.rb', line 287

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


282
283
284
285
# File 'lib/parse_resource/base.rb', line 282

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.


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/parse_resource/base.rb', line 65

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.


86
87
88
# File 'lib/parse_resource/base.rb', line 86

def self.fields(*args)
  args.each {|f| field(f)}
end

.find(id) ⇒ ParseResource

Find a ParseResource::Base object by ID

Raises:


339
340
341
342
343
344
# File 'lib/parse_resource/base.rb', line 339

def self.find(id)
  raise RecordNotFound, "Couldn't find #{name} without an ID" if id.blank?
  record = where(:objectId => id).first
  raise RecordNotFound, "Couldn't find #{name} with id: #{id}" if record.blank?
  record
end

.find_by(*args) ⇒ Object

Find a ParseResource::Base object by given key/value pair

Raises:


348
349
350
351
352
353
# File 'lib/parse_resource/base.rb', line 348

def self.find_by(*args)
  raise RecordNotFound, "Couldn't find an object without arguments" if args.blank?
  key, value = args.first.first
  record = where(key => value).first
  record
end

.has_many(parent, options = {}) ⇒ Object

Creates setter and getter in order access the specified relation for this Model


101
102
103
104
# File 'lib/parse_resource/base.rb', line 101

def self.has_many(parent, options = {})
  field(parent)
  @@has_many_relations << parent
end

.has_many_relationsObject


677
678
679
# File 'lib/parse_resource/base.rb', line 677

def self.has_many_relations
  @@has_many_relations
end

.included(base) ⇒ Object


694
695
696
# File 'lib/parse_resource/base.rb', line 694

def self.included(base)
  base.extend(ClassMethods)
end

.load!(app_id, master_key) ⇒ Object

Explicitly set Parse.com API keys.


178
179
180
# File 'lib/parse_resource/base.rb', line 178

def self.load!(app_id, master_key)
  @@settings = {"app_id" => app_id, "master_key" => master_key}
end

.load_settingsObject


291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/parse_resource/base.rb', line 291

def self.load_settings
  @@settings ||= begin
    path = "config/parse_resource.yml"
    environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"]
    if FileTest.exist? (path)
      YAML.load(ERB.new(File.new(path).read).result)[environment]
    elsif ENV["PARSE_RESOURCE_APPLICATION_ID"] && ENV["PARSE_RESOURCE_MASTER_KEY"]
      settings = HashWithIndifferentAccess.new
      settings['app_id'] = ENV["PARSE_RESOURCE_APPLICATION_ID"]
      settings['master_key'] = ENV["PARSE_RESOURCE_MASTER_KEY"]
      settings
    else
      raise "Cannot load parse_resource.yml and API keys are not set in environment"
    end
  end
  @@settings
end

.merge_all_attributes(objects, response) ⇒ Object


269
270
271
272
273
274
275
276
# File 'lib/parse_resource/base.rb', line 269

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


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/parse_resource/base.rb', line 130

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_uriObject

Gets the current class's Parse.com base_uri


203
204
205
# File 'lib/parse_resource/base.rb', line 203

def self.model_base_uri
  "https://api.parse.com/1/#{model_name_uri}"
end

.model_name_uriObject

Gets the current class's model name for the URI


187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/parse_resource/base.rb', line 187

def self.model_name_uri
  # This is a workaround to allow the user to specify a custom class
  if defined?(self.parse_class_name)
    "classes/#{self.parse_class_name}"
  elsif self.model_name.to_s == "User"
    "users"
  elsif self.model_name.to_s == "Installation"
    "installations"
  elsif self.model_name.to_s == "Role"
    "roles"
  else
    "classes/#{self.model_name.to_s}"
  end
end

.resourceObject

Creates a RESTful resource sends requests to [base_uri]/


216
217
218
219
220
221
222
223
# File 'lib/parse_resource/base.rb', line 216

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


278
279
280
# File 'lib/parse_resource/base.rb', line 278

def self.save_all(objects)
  batch_save(objects)
end

.settingsObject


182
183
184
# File 'lib/parse_resource/base.rb', line 182

def self.settings
  load_settings
end

.to_date_object(date) ⇒ Object


114
115
116
117
# File 'lib/parse_resource/base.rb', line 114

def self.to_date_object(date)
  date = date.to_time if date.respond_to?(:to_time)
  {"__type" => "Date", "iso" => date.getutc.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


313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/parse_resource/base.rb', line 313

def self.upload(file_instance, filename, options={})
  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']

  options[: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, options) do |resp, req, res, &block|
    return false if resp.code == 400
    return JSON.parse(resp) rescue {"code" => 0, "error" => "unknown error"}
  end
  false
end

.where(*args) ⇒ Object

Find a ParseResource::Base object by chaining #where method calls.


357
358
359
# File 'lib/parse_resource/base.rb', line 357

def self.where(*args)
  Query.new(self).where(*args)
end

Instance Method Details

#==(another_object) ⇒ Object

if we are comparing objects, use id if they are both ParseResource objects


702
703
704
705
706
707
708
# File 'lib/parse_resource/base.rb', line 702

def ==(another_object)
  if another_object.class <= ParseResource::Base
    self.id == another_object.id
  else
    super
  end
end

#attributesObject

provides access to @attributes for getting and setting


613
614
615
616
# File 'lib/parse_resource/base.rb', line 613

def attributes
  @attributes ||= self.class.class_attributes
  @attributes
end

#attributes=(value) ⇒ Object


618
619
620
621
622
623
624
625
# File 'lib/parse_resource/base.rb', line 618

def attributes=(value)
  if value.is_a?(Hash) && value.present?
    value.each do |k, v|
      send "#{k}=", v
    end
  end
  @attributes
end

#attributes_for_savingObject


506
507
508
509
510
511
512
513
514
515
516
# File 'lib/parse_resource/base.rb', line 506

def attributes_for_saving
  @unsaved_attributes = pointerize(@unsaved_attributes)
  put_attrs = @unsaved_attributes

  put_attrs = relations_for_saving(put_attrs)

  put_attrs.delete('objectId')
  put_attrs.delete('createdAt')
  put_attrs.delete('updatedAt')
  put_attrs
end

#clean?Boolean


608
609
610
# File 'lib/parse_resource/base.rb', line 608

def clean?
  !dirty?
end

#createObject


444
445
446
447
448
449
450
# File 'lib/parse_resource/base.rb', line 444

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


157
158
159
160
161
162
163
# File 'lib/parse_resource/base.rb', line 157

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


120
121
122
123
124
125
126
127
128
# File 'lib/parse_resource/base.rb', line 120

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


165
166
167
168
169
170
# File 'lib/parse_resource/base.rb', line 165

def create_setters_and_getters!
  @attributes.each_pair do |k,v|
    create_setters!(k,v)
    create_getters!(k,v)
  end
end

#created_atObject


690
# File 'lib/parse_resource/base.rb', line 690

def created_at; get_attribute("createdAt"); end

#destroyObject


585
586
587
588
589
590
591
592
# File 'lib/parse_resource/base.rb', line 585

def destroy
  if self.instance_resource.delete
    @attributes = {}
    @unsaved_attributes = {}
    return true
  end
  false
end

#dirty?Boolean


604
605
606
# File 'lib/parse_resource/base.rb', line 604

def dirty?
  @unsaved_attributes.length > 0
end

#get_attribute(k) ⇒ Object


627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# File 'lib/parse_resource/base.rb', line 627

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.to_s.constantize.find(attrs[k]["objectId"])
    when "Object"
      result = klass_name.to_s.constantize.new(attrs[k], false)
    when "Date"
      result = DateTime.parse(attrs[k]["iso"]).in_time_zone
    when "File"
      result = attrs[k]["url"]
    when "GeoPoint"
      result = ParseGeoPoint.new(attrs[k])
    when "Relation"
      objects_related_to_self = klass_name.constantize.where("$relatedTo" => {"object" => {"__type" => "Pointer", "className" => self.class.to_s, "objectId" => self.objectId}, "key" => k}).all
      attrs[k] = RelationArray.new self, objects_related_to_self, k, klass_name
      @unsaved_attributes[k] = RelationArray.new self, objects_related_to_self, k, klass_name
      result = @unsaved_attributes[k]
    end #todo: support other types https://www.parse.com/docs/rest#objects-types
  else
    #relation will assign itself if an array, this will add to unsave_attributes
     if @@has_many_relations.index(k.to_s.to_sym)
      if attrs[k].nil?
        result = nil
      else
        @unsaved_attributes[k] = attrs[k].clone
        result = @unsaved_attributes[k]
      end
    else
      result =  attrs["#{k}"]
    end
  end
  result
end

#idObject

aliasing for idiomatic Ruby


687
# File 'lib/parse_resource/base.rb', line 687

def id; get_attribute("objectId") rescue nil; end

#instance_resourceObject

create RESTful resource for the specific Parse object sends requests to [base_uri]//[objectId]


410
411
412
# File 'lib/parse_resource/base.rb', line 410

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


466
467
468
469
470
471
472
473
474
475
476
# File 'lib/parse_resource/base.rb', line 466

def merge_attributes(results)
  @attributes.merge!(results)
  @attributes.merge!(@unsaved_attributes)

  merge_relations
  @unsaved_attributes = {}


  create_setters_and_getters!
  @attributes
end

#merge_relationsObject


478
479
480
481
482
483
484
485
# File 'lib/parse_resource/base.rb', line 478

def merge_relations
  # KK 11-17-2012 The response after creation does not return full description of
  # the object nor the relations it contains. Make another request here.
  if @@has_many_relations.map { |relation| relation.to_s.to_sym }
    #todo: make this a little smarter by checking if there are any Pointer objects in the objects attributes.
    @attributes = self.class.to_s.constantize.where(:objectId => @attributes["objectId"]).first.attributes
  end
end

#model_base_uriObject

Gets the current instance's parent class's Parse.com base_uri


208
209
210
# File 'lib/parse_resource/base.rb', line 208

def model_base_uri
  self.class.send(:model_base_uri)
end

#new?Boolean


399
400
401
# File 'lib/parse_resource/base.rb', line 399

def new?
  !persisted?
end

#objectIdObject


688
# File 'lib/parse_resource/base.rb', line 688

def objectId; get_attribute("objectId") rescue nil; end

#persisted?Boolean


391
392
393
394
395
396
397
# File 'lib/parse_resource/base.rb', line 391

def persisted?
  if id
    true
  else
    false
  end
end

#pointerize(hash) ⇒ Object


414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/parse_resource/base.rb', line 414

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


487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# File 'lib/parse_resource/base.rb', line 487

def post_result(resp, req, res, &block)
  if resp.code.to_s == "200" || resp.code.to_s == "201"
    puts "request: #{req.inspect}"
    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

#relations_for_saving(put_attrs) ⇒ Object


518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
# File 'lib/parse_resource/base.rb', line 518

def relations_for_saving(put_attrs)
  all_add_item_queries = {}
  all_remove_item_queries = {}
  @unsaved_attributes.each_pair do |key, value|
    next if !value.is_a? Array

    # Go through the array in unsaved and check if they are in array in attributes (saved stuff)
    add_item_ops = []
    @unsaved_attributes[key].each do |item|
      found_item_in_saved = false
      @attributes[key].each do |item_in_saved|
        if !!(defined? item.attributes) && item.attributes["objectId"] == item_in_saved.attributes["objectId"]
          found_item_in_saved = true
        end
      end

      if !found_item_in_saved && !!(defined? item.objectId)
        # need to send additem operation to parse
        put_attrs.delete(key) # arrays should not be sent along with REST to parse api
        add_item_ops << {"__type" => "Pointer", "className" => item.class.to_s, "objectId" => item.objectId}
      end
    end
    all_add_item_queries.merge!({key => {"__op" => "Add", "objects" => add_item_ops}}) if !add_item_ops.empty?

    # Go through saved and if it isn't in unsaved perform a removeitem operation
    remove_item_ops = []
    unless @unsaved_attributes.empty?
      @attributes[key].each do |item|
        found_item_in_unsaved = false
        @unsaved_attributes[key].each do |item_in_unsaved|
          if !!(defined? item.attributes) && item.attributes["objectId"] == item_in_unsaved.attributes["objectId"]
            found_item_in_unsaved = true
          end
        end

        if !found_item_in_unsaved  && !!(defined? item.objectId)
          # need to send removeitem operation to parse
          remove_item_ops << {"__type" => "Pointer", "className" => item.class.to_s, "objectId" => item.objectId}
        end
      end
    end
    all_remove_item_queries.merge!({key => {"__op" => "Remove", "objects" => remove_item_ops}}) if !remove_item_ops.empty?
  end

  # TODO figure out a more elegant way to get this working. the remove_item merge overwrites the add.
  # Use a seperate query to add objects to the relation.
  #if !all_add_item_queries.empty?
  #  #result = self.instance_resource.put(all_add_item_queries.to_json, {:content_type => "application/json"}) do |resp, req, res, &block|
  #  #  return puts(resp, req, res, false, &block)
  #  #end
  #  puts result
  #end

  put_attrs.merge!(all_add_item_queries) unless all_add_item_queries.empty?
  put_attrs.merge!(all_remove_item_queries) unless all_remove_item_queries.empty?
  put_attrs
end

#reloadObject


594
595
596
597
598
599
600
601
602
# File 'lib/parse_resource/base.rb', line 594

def reload
  return false if new?

  fresh_object = self.class.find(id)
  @attributes.update(fresh_object.instance_variable_get('@attributes'))
  @unsaved_attributes = {}

  self
end

#resourceObject

delegate from Class method


404
405
406
# File 'lib/parse_resource/base.rb', line 404

def resource
  self.class.resource
end

#saveObject


428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/parse_resource/base.rb', line 428

def save
  if valid?
    run_callbacks :save do
      if new?
        create
      else
        update
      end
    end
  else
    false
  end
rescue
  false
end

#set_attribute(k, v) ⇒ Object


666
667
668
669
670
671
672
673
674
675
# File 'lib/parse_resource/base.rb', line 666

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_pointerObject


106
107
108
109
110
111
112
# File 'lib/parse_resource/base.rb', line 106

def to_pointer
  klass_name = self.class.model_name.to_s
  klass_name = "_User" if klass_name == "User"
  klass_name = "_Installation" if klass_name == "Installation"
  klass_name = "_Role" if klass_name == "Role"
  {"__type" => "Pointer", "className" => klass_name.to_s, "objectId" => self.id}
end

#update(attributes = {}) ⇒ Object


452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/parse_resource/base.rb', line 452

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_attribute(key, value) ⇒ Object


580
581
582
583
# File 'lib/parse_resource/base.rb', line 580

def update_attribute(key, value)
  send(key.to_s + '=', value)
  update
end

#update_attributes(attributes = {}) ⇒ Object


576
577
578
# File 'lib/parse_resource/base.rb', line 576

def update_attributes(attributes = {})
  self.update(attributes)
end

#updated_atObject


692
# File 'lib/parse_resource/base.rb', line 692

def updated_at; get_attribute("updatedAt"); rescue nil; end