diff --git a/lib/parse/datatypes.rb b/lib/parse/datatypes.rb index 9e0cfad..ccc7ef7 100644 --- a/lib/parse/datatypes.rb +++ b/lib/parse/datatypes.rb @@ -14,6 +14,18 @@ def initialize(data) @parse_object_id = data[Protocol::KEY_OBJECT_ID] end + def eql?(other) + self.class.equal?(other.class) && + class_name == other.class_name && + parse_object_id == other.parse_object_id + end + + alias == eql? + + def hash + class_name.hash ^ parse_object_id.hash + end + def as_json(*a) { Protocol::KEY_TYPE => Protocol::TYPE_POINTER, @@ -21,7 +33,7 @@ def as_json(*a) Protocol::KEY_OBJECT_ID => @parse_object_id } end - + def to_json(*a) as_json.to_json(*a) end @@ -48,13 +60,36 @@ def initialize(data) end end + def eql?(other) + self.class.equal?(other.class) && + value == other.value + end + + alias == eql? + + def hash + value.hash + end + + def method_missing(method, *args, &block) + if value.respond_to?(method) + value.send(method, *args, &block) + else + super(method) + end + end + + def respond_to?(method, include_private = false) + super || value.respond_to?(method, include_private) + end + def as_json(*a) { Protocol::KEY_TYPE => Protocol::TYPE_DATE, "iso" => value.iso8601 } end - + def to_json(*a) as_json.to_json(*a) end @@ -71,78 +106,135 @@ def initialize(data) @value = Base64.decode64(bytes) end + def eql?(other) + self.class.equal?(other.class) && + value == other.value + end + + alias == eql? + + def hash + value.hash + end + + def method_missing(method, *args, &block) + if value.respond_to?(method) + value.send(method, *args, &block) + else + super(method) + end + end + + def respond_to?(method, include_private = false) + super || value.respond_to?(method, include_private) + end + def as_json(*a) { Protocol::KEY_TYPE => Protocol::TYPE_BYTES, "base64" => Base64.encode64(@value) } end - + def to_json(*a) as_json.to_json(*a) end end - + # Increment and Decrement # ------------------------------------------------------------ - + class Increment # '{"score": {"__op": "Increment", "amount": 1 } }' attr_accessor :amount - + def initialize(amount) @amount = amount end - + + def eql?(other) + self.class.equal?(other.class) && + amount == other.amount + end + + alias == eql? + + def hash + amount.hash + end + def as_json(*a) { Protocol::KEY_OP => Protocol::KEY_INCREMENT, Protocol::KEY_AMOUNT => @amount } end - + def to_json(*a) as_json.to_json(*a) end end - + class Decrement # '{"score": {"__op": "Decrement", "amount": 1 } }' attr_accessor :amount - + def initialize(amount) @amount = amount end - + + def eql?(other) + self.class.equal?(other.class) && + amount == other.amount + end + + alias == eql? + + def hash + amount.hash + end + def as_json(*a) { Protocol::KEY_OP => Protocol::KEY_DECREMENT, Protocol::KEY_AMOUNT => @amount } end - + def to_json(*a) as_json.to_json(*a) end end - + # GeoPoint # ------------------------------------------------------------ - + class GeoPoint # '{"location": {"__type":"GeoPoint", "latitude":40.0, "longitude":-30.0}}' attr_accessor :longitude, :latitude - + def initialize(data) @longitude = data["longitude"] @latitude = data["latitude"] - + if !@longitude && !@latitude @longitude = data[:longitude] @latitude = data[:latitude] end end - + + def eql?(other) + self.class.equal?(other.class) && + longitude == other.longitude && + latitude == other.latitude + end + + alias == eql? + + def hash + longitude.hash ^ latitude.hash + end + def as_json(*a) { Protocol::KEY_TYPE => Protocol::TYPE_GEOPOINT, @@ -150,11 +242,11 @@ def as_json(*a) "longitude" => @longitude } end - + def to_json(*a) as_json.to_json(*a) end end - + end \ No newline at end of file diff --git a/lib/parse/util.rb b/lib/parse/util.rb index dd6c7a7..f0e2311 100644 --- a/lib/parse/util.rb +++ b/lib/parse/util.rb @@ -9,9 +9,6 @@ def Parse.parse_json(class_name, obj) if obj.nil? nil - # String - elsif obj.is_a? String - parse_json class_name, JSON.parse(obj) # Array elsif obj.is_a? Array @@ -25,10 +22,11 @@ def Parse.parse_json(class_name, obj) parse_datatype obj elsif obj.size == 1 && obj.has_key?(Protocol::KEY_RESULTS) && obj[Protocol::KEY_RESULTS].is_a?(Array) obj[Protocol::KEY_RESULTS].collect { |o| parse_json(class_name, o) } - else # otherwise it must be a regular object - Parse::Object.new class_name, obj + else # otherwise it must be a regular object, so deep parse it avoiding re-JSON.parsing raw Strings + Parse::Object.new class_name, Hash[obj.map{|k,v| [k, parse_json(nil, v)]}] end + # primitive else obj end @@ -44,6 +42,8 @@ def Parse.parse_datatype(obj) Parse::Bytes.new obj when Protocol::TYPE_DATE Parse::Date.new obj + when Protocol::TYPE_GEOPOINT + Parse::GeoPoint.new obj end end end diff --git a/test/test_datatypes.rb b/test/test_datatypes.rb index aaac52a..38d7be3 100644 --- a/test/test_datatypes.rb +++ b/test/test_datatypes.rb @@ -7,19 +7,19 @@ def test_pointer Parse::Protocol::KEY_OBJECT_ID => "12345abcd" } p = Parse::Pointer.new data - - assert_equal p.to_json, "{\"__type\":\"Pointer\",\"#{Parse::Protocol::KEY_CLASS_NAME}\":\"DatatypeTestClass\",\"#{Parse::Protocol::KEY_OBJECT_ID}\":\"12345abcd\"}" + + assert_equal p.to_json, "{\"__type\":\"Pointer\",\"#{Parse::Protocol::KEY_CLASS_NAME}\":\"DatatypeTestClass\",\"#{Parse::Protocol::KEY_OBJECT_ID}\":\"12345abcd\"}" end - + def test_date date_time = DateTime.now data = date_time parse_date = Parse::Date.new data - + assert_equal parse_date.value, date_time assert_equal JSON.parse(parse_date.to_json)["iso"], date_time.iso8601 end - + def test_bytes data = { "base64" => Base64.encode64("testing bytes!") @@ -30,21 +30,21 @@ def test_bytes assert_equal JSON.parse(byte.to_json)[Parse::Protocol::KEY_TYPE], Parse::Protocol::TYPE_BYTES assert_equal JSON.parse(byte.to_json)["base64"], Base64.encode64("testing bytes!") end - + def test_increment amount = 5 increment = Parse::Increment.new amount - + assert_equal increment.to_json, "{\"__op\":\"Increment\",\"amount\":#{amount}}" end - + def test_decrement amount = 5 increment = Parse::Decrement.new amount - + assert_equal increment.to_json, "{\"__op\":\"Decrement\",\"amount\":#{amount}}" end - + def test_geopoint # '{"location": {"__type":"GeoPoint", "latitude":40.0, "longitude":-30.0}}' data = { @@ -52,9 +52,15 @@ def test_geopoint "latitude" => -30.0 } gp = Parse::GeoPoint.new data - - assert_equal JSON.parse(gp.to_json)["longitude"], data["longitude"] + + assert_equal JSON.parse(gp.to_json)["longitude"], data["longitude"] assert_equal JSON.parse(gp.to_json)["latitude"], data["latitude"] assert_equal JSON.parse(gp.to_json)[Parse::Protocol::KEY_TYPE], Parse::Protocol::TYPE_GEOPOINT + + post = Parse::Object.new("Post") + post["location"] = gp + post.save + q = Parse.get("Post", post.id) + assert_equal gp, q["location"] end end diff --git a/test/test_object.rb b/test/test_object.rb index 4d8a73e..baa6a35 100644 --- a/test/test_object.rb +++ b/test/test_object.rb @@ -64,4 +64,16 @@ def test_parse_delete end end + def test_deep_parse + other = Parse::Object.new "Post" + other.save + post = Parse::Object.new "Post" + post["other"] = other.pointer + post.save + + q = Parse.get("Post", post.id) + assert_equal Parse::Pointer, q["other"].class + assert_equal other.pointer, q["other"] + end + end