lib/cfoundry/v2/model.rb in cfoundry-0.3.54 vs lib/cfoundry/v2/model.rb in cfoundry-0.3.55

- old
+ new

@@ -39,26 +39,44 @@ def defaults @defaults ||= {} end + def attributes + @attributes ||= {} + end + + def to_one_relations + @to_one_relations ||= {} + end + + def to_many_relations + @to_many_relations ||= {} + end + def attribute(name, type, opts = {}) + attributes[name] = opts + default = opts[:default] if has_default = opts.key?(:default) defaults[name] = default end define_method(name) { - manifest[:entity][name] || default + return @cache[name] if @cache.key?(name) + + @cache[name] = manifest[:entity][name] || default } define_method(:"#{name}=") { |val| unless has_default && val == default Model.validate_type(val, type) end + @cache[name] = val + @manifest ||= {} @manifest[:entity] ||= {} @manifest[:entity][name] = val @diff[name] = val } @@ -71,10 +89,12 @@ def scoped_to_space(relation = :space) @scoped_space = relation end def to_one(name, opts = {}) + to_one_relations[name] = opts + obj = opts[:as] || name kls = obj.to_s.capitalize.gsub(/(.)_(.)/) do $1 + $2.upcase end @@ -83,17 +103,20 @@ if has_default = opts.key?(:default) defaults[:"#{name}_guid"] = default end define_method(name) { - if @manifest && @manifest[:entity].key?(name) - @client.send(:"make_#{obj}", @manifest[:entity][name]) - elsif url = send("#{name}_url") - @client.send(:"#{obj}_from", url, opts[:depth] || 1) - else - default - end + return @cache[name] if @cache.key?(name) + + @cache[name] = + if @manifest && @manifest[:entity].key?(name) + @client.send(:"make_#{obj}", @manifest[:entity][name]) + elsif url = send("#{name}_url") + @client.send(:"#{obj}_from", url, opts[:depth] || 1) + else + default + end } define_method(:"#{name}_url") { manifest[:entity][:"#{name}_url"] } @@ -101,28 +124,36 @@ define_method(:"#{name}=") { |x| unless has_default && x == default Model.validate_type(x, CFoundry::V2.const_get(kls)) end + @cache[name] = x + @manifest ||= {} @manifest[:entity] ||= {} @manifest[:entity][:"#{name}_guid"] = @diff[:"#{name}_guid"] = x && x.guid } end def to_many(plural, opts = {}) + to_many_relations[plural] = opts + singular = plural.to_s.sub(/s$/, "").to_sym object = opts[:as] || singular plural_object = :"#{object}s" kls = object.to_s.capitalize.gsub(/(.)_(.)/) do $1 + $2.upcase end define_method(plural) { |*args| + if cache = @cache[plural] + return cache + end + depth, query = args if @manifest && @manifest[:entity].key?(plural) && !depth objs = @manifest[:entity][plural] @@ -130,70 +161,129 @@ find_by = query.keys.first find_val = query.values.first objs = objs.select { |o| o[:entity][find_by] == find_val } end - objs.collect do |json| - @client.send(:"make_#{object}", json) - end + @cache[plural] = + objs.collect do |json| + @client.send(:"make_#{object}", json) + end else - @client.send( - :"#{plural_object}_from", - "/v2/#{object_name}s/#@guid/#{plural}", - depth || opts[:depth], - query) + @cache[plural] = + @client.send( + :"#{plural_object}_from", + "/v2/#{object_name}s/#@guid/#{plural}", + depth || opts[:depth], + query) end } define_method(:"#{plural}_url") { manifest[:entity][:"#{plural}_url"] } define_method(:"add_#{singular}") { |x| - # TODO: reflect this change in the app manifest? Model.validate_type(x, CFoundry::V2.const_get(kls)) + if cache = @cache[plural] + cache << x unless cache.include?(x) + end + @client.base.request_path( Net::HTTP::Put, ["v2", "#{object_name}s", @guid, plural, x.guid], :accept => :json) } define_method(:"remove_#{singular}") { |x| - # TODO: reflect this change in the app manifest? Model.validate_type(x, CFoundry::V2.const_get(kls)) + if cache = @cache[plural] + cache.delete(x) + end + @client.base.request_path( Net::HTTP::Delete, ["v2", "#{object_name}s", @guid, plural, x.guid], :accept => :json) } define_method(:"#{plural}=") { |xs| Model.validate_type(xs, [CFoundry::V2.const_get(kls)]) + @cache[plural] = xs + @manifest ||= {} @manifest[:entity] ||= {} @manifest[:entity][:"#{singular}_guids"] = @diff[:"#{singular}_guids"] = xs.collect(&:guid) } end + + def has_summary(actions = {}) + define_method(:summary) do + @client.base.request_path( + Net::HTTP::Get, + ["v2", "#{object_name}s", @guid, "summary"], + :accept => :json) + end + + define_method(:summarize!) do |*args| + body, _ = args + + body ||= summary + + body.each do |key, val| + if act = actions[key] + instance_exec(val, &act) + + elsif self.class.attributes[key] + self.send(:"#{key}=", val) + + elsif self.class.to_many_relations[key] + singular = key.to_s.sub(/s$/, "").to_sym + + vals = val.collect { |sub| + obj = @client.send(singular, sub[:guid], true) + obj.summarize! sub + obj + } + + self.send(:"#{key}=", vals) + + elsif self.class.to_one_relations[key] + obj = @client.send(key, val[:guid], true) + obj.summarize! val + + self.send(:"#{key}=", obj) + end + end + + nil + end + end end - attr_reader :guid + attr_accessor :guid, :cache - def initialize(guid, client, manifest = nil) + def initialize(guid, client, manifest = nil, partial = false) @guid = guid @client = client @manifest = manifest + @partial = partial + @cache = {} @diff = {} end def manifest @manifest ||= @client.base.send(object_name, @guid) end + def partial? + @partial + end + def inspect "\#<#{self.class.name} '#@guid'>" end def object_name @@ -203,9 +293,11 @@ '\1_\2').downcase end def invalidate! @manifest = nil + @partial = false + @cache = {} @diff = {} end # this does a bit of extra processing to allow for # `delete!' followed by `create!'