lib/yammer/base.rb in yammer-client-0.1.1 vs lib/yammer/base.rb in yammer-client-0.1.2

- old
+ new

@@ -1,117 +1,148 @@ module Yammer class Base + class << self - def self.attr_accessor_deffered(*symbols) - symbols.each do |key| - fetchable_keys[key] = true - - define_method (key.to_s) do - if self.class.fetchable_keys.has_key?(key) && !@attrs.has_key?(key) && @id - load! - end - instance_variable_get("@#{key}") + # Returns the non-qualified class name + # @!scope class + def base_name + @base_name ||= begin + word = "#{name.split(/::/).last}" + word.gsub!(/::/, '/') + word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') + word.tr!("-", "_") + word.downcase! + word end + end - define_method ("#{key}=") do |value| - if @attrs.fetch(key, false) && !new_record? - @modified_attributes[key] = value - else - @attrs[key] = value + # Fetches JSON reprsentation for object model with provided `id` + # and returns a model instance with attributes + # @return [Yammer::Base] + # @param id [Integer] + # @!scope class + def get(id) + attrs = fetch(id) + attrs ? new(attrs) : nil + end + + + # @!scope class + def fetch(id) + return unless identity_map + attributes = identity_map.get("#{base_name}_#{id}") + unless attributes + result = Yammer.send("get_#{base_name}", id) + attributes = result.empty? ? nil : result.body + unless attributes.empty? + identity_map.put("#{base_name}_#{id}", attributes) end - instance_variable_set("@#{key}", value) end + attributes end - end - # @!scope class - def self.fetchable_keys - @fetchable_keys ||= {} - return @fetchable_keys - end + # @!scope class + def identity_map + @identity_map ||= Yammer::IdentityMap.new + end - # @!scope class - def self.identity_map - @identity_map ||= Yammer::IdentityMap.new - end + # Returns a hash of all attributes that are meant to trigger an HTTP request + # @!scope class + def fetchable_attrs + @fetchable_keys ||= {} + end - # @!scope class - def self.base_name - word = "#{self.name.split(/::/).last}" - word.gsub!(/::/, '/') - word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') - word.tr!("-", "_") - word.downcase! - word - end + protected - # @!scope class - def self.fetch(id) - return unless identity_map - attributes = identity_map.get("#{self.base_name}_#{id}") - unless attributes - result = Yammer.send("get_#{self.base_name}", id) - attributes = result.body || {} - unless attributes.empty? - identity_map.put("#{self.base_name}_#{id}", attributes) + def attr_accessor_deffered(*symbols) + symbols.each do |key| + # track attributes the trigger fetch + fetchable_attrs[key] = false + + # getter + define_method(key.to_s) do + load_deferred_attribute!(key) + instance_variable_get("@#{key}") + end + + # setter + define_method("#{key}=") do |value| + load_deferred_attribute!(key) + if persisted? && loaded? + @modified_attributes[key] = value + else + @attrs[key] = value + end + instance_variable_set("@#{key}", value) + end end end - attributes end - # @!scope class - def self.get(id) - new(fetch(id)) - end - attr_reader :id, :attrs def initialize(props={}) @modified_attributes = {} - @attrs = {} - @new_record = true - self.id = props.delete(:id) - self.update(props) + @new_record = true + @loaded = false + @attrs = props + self.id = @attrs.delete(:id) + self.update(@attrs) end def base_name self.class.base_name end def new_record? @new_record end + def persisted? + !new_record? + end + def changes @modified_attributes end def modified? !changes.empty? end + def loaded? + @loaded + end + def load! - result = self.class.fetch(@id) - update(result) + @attrs = self.class.fetch(@id) + @loaded = true + update(@attrs) + self end - alias_method :reload!, :load! + def reload! + reset! + load! + end + def save - return self if ((!new_record? && @modified_attributes.empty?) || @attrs.empty?) + return self if ((persisted? && @modified_attributes.empty?) || @attrs.empty?) + result = if new_record? - Yammer.send("create_#{self.base_name}", @attrs) + Yammer.send("create_#{base_name}", @attrs) else - Yammer.send("update_#{self.base_name}", @id, @modified_attributes) + Yammer.send("update_#{base_name}", @id, @modified_attributes) end @modified_attributes = {} self end def delete! return if new_record? - result = Yammer.send("delete_#{self.base_name}", @id) + result = Yammer.send("delete_#{base_name}", @id) result.success? end private @@ -119,13 +150,37 @@ return if model_id.nil? @id = model_id.to_i @new_record = false end + # clear the entire class + def reset! + @modified_attributes = {} + @attrs = {} + @new_record = true + @loaded = false + end + protected - def update(props={}) - props.each do |key, value| + # loads model + def load_deferred_attribute!(key) + if @attrs.empty? && persisted? && !loaded? + load! + if !@attrs.has_key?(key) + raise "The key: #{key} appears not to be supported for model: #{self.base_name} \n #{@attrs.keys.inspect}" + end + end + end + + # set all fetchable attributes + def update(attrs={}) + attrs.each do |key, value| send("#{key}=", value) + end + if persisted? && !loaded? + @loaded = self.class.fetchable_attrs.keys.inject(true) do |result, key| + result && @attrs.has_key?(key) + end end end end end \ No newline at end of file