lib/spaceship/base.rb in spaceship-0.0.15 vs lib/spaceship/base.rb in spaceship-0.1.0
- old
+ new
@@ -17,18 +17,48 @@
# })
# end
#
# When you want to instantiate a model pass in the parsed response: `Widget.new(widget_json)`
class Base
+ class DataHash
+ def initialize(hash)
+ @hash = hash
+ end
+
+ def get(*keys)
+ lookup(keys)
+ end
+ alias [] get
+
+ def set(keys, value)
+ last = keys.pop
+ ref = lookup(keys) || @hash
+ ref[last] = value
+ end
+
+ def lookup(keys)
+ head, *tail = *keys
+ if tail.empty?
+ @hash[head]
+ else
+ DataHash.new(@hash[head]).lookup(tail)
+ end
+ end
+
+ def to_json
+ @hash.to_json
+ end
+ end
+
class << self
attr_accessor :client
##
# The client used to make requests.
- # @return (Spaceship::Client) Defaults to the singleton `Spaceship.client`
+ # @return (Spaceship::Client) Defaults to the singleton
def client
- @client || Spaceship.client
+ raise "`client` must be implemented in subclasses"
end
##
# Sets client and returns self for chaining.
# @return (Spaceship::Base)
@@ -36,22 +66,29 @@
self.client = client
self
end
##
- # Remaps the attributes passed into the initializer to the model
- # attributes using the map defined by `attr_map`.
+ # Binds attributes getters and setters to underlying data returned from the API.
+ # Setting any properties will alter the `raw_data` hash.
#
- # This method consumes the input parameter meaning attributes that were
- # remapped are deleted.
- #
- # @return (Hash) the attribute mapping used by `remap_keys!`
- def remap_keys!(attrs)
- return if attr_mapping.nil?
+ # @return (Module) with the mapped getters and setters defined. Can be `include`, `extend`, or `prepend` into a class or object
+ def mapping_module(attr_mapping)
+ Module.new do
+ attr_mapping.each do |source, dest|
+ getter = dest.to_sym
+ setter = "#{dest}=".to_sym
- attr_mapping.each do |from, to|
- attrs[to] = attrs.delete(from)
+ define_method(getter) do
+ raw_data.get(*source.split('.'))
+ end
+
+ define_method(setter) do |value|
+ self.raw_data ||= DataHash.new({})
+ raw_data.set(source.split('.'), value)
+ end
+ end
end
end
##
# Defines the attribute mapping between the response from Apple and our model objects.
@@ -68,16 +105,24 @@
# })
# end
def attr_mapping(attr_map = nil)
if attr_map
@attr_mapping = attr_map
+ @attr_mapping.values.each do |method_name|
+ getter = method_name.to_sym
+ setter = "#{method_name}=".to_sym
+ remove_method(getter) if public_instance_methods.include?(getter)
+ remove_method(setter) if public_instance_methods.include?(setter)
+ end
+ include(mapping_module(@attr_mapping))
else
begin
- @attr_mapping ||= ancestors[1].attr_mapping
+ @attr_mapping ||= ancestors[1].attr_mapping
rescue NameError, NoMethodError
end
end
+ return @attr_mapping
end
##
# Call a method to return a subclass constant.
#
@@ -107,19 +152,31 @@
end
end
end
##
+ # @return (Hash/Array) Holds the raw data we got from Apple's
+ # server to use it later
+ attr_accessor :raw_data
+
+ ##
# The initialize method accepts a parsed response from Apple and sets all
# attributes that are defined by `attr_mapping`
#
# Do not override `initialize` in your own models.
def initialize(attrs = {})
- self.class.remap_keys!(attrs)
attrs.each do |key, val|
self.send("#{key}=", val) if respond_to?("#{key}=")
end
+ self.raw_data = DataHash.new(attrs)
@client = self.class.client
+ self.setup
+ end
+
+ # This method can be used by subclasses to do additional initialisation
+ # using the `raw_data`
+ def setup
+
end
##
# @return (Spaceship::Client) The current spaceship client used by the model to make requests.
def client