Skip to content

Commit

Permalink
Refactor code common to Twitter::Base#attr_reader and object_attr_reader
Browse files Browse the repository at this point in the history
  • Loading branch information
sferik committed Jul 28, 2013
1 parent 11fa58a commit 3f05440
Showing 1 changed file with 53 additions and 35 deletions.
88 changes: 53 additions & 35 deletions lib/twitter/base.rb
Expand Up @@ -12,57 +12,68 @@ class Base

# Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
#
# @param attrs [Array, Set, Symbol]
# @param attrs [Array, Symbol]
def self.attr_reader(*attrs)
mod = Module.new do
attrs.each do |attribute|
define_method attribute do
@attrs[attribute.to_sym]
end
define_method "#{attribute}?" do
!!@attrs[attribute.to_sym]
end
end
attrs.each do |attr|
define_attribute_method(attr)
define_predicate_method(attr)
end
const_set(:Attributes, mod)
include mod
end

# Construct an object from a response hash
# Create a new object (or NullObject) from attributes
#
# @param response [Hash]
# @return [Twitter::Base]
def self.from_response(response={})
new(response[:body])
# @param klass [Symbol]
# @param key1 [Symbol]
# @param key2 [Symbol]
def self.object_attr_reader(klass, key1, key2=nil)
define_attribute_method(key1, klass, key2)
define_predicate_method(key1)
end

# Create a new object (or NullObject) from attributes
# Dynamically define a method for an attribute
#
# @param klass [Class]
# @param key1 [Symbol]
# @param klass [Symbol]
# @param key2 [Symbol]
def self.object_attr_reader(klass, key1, key2=nil)
define_method key1 do
ivar = :"@#{key1}"
return instance_variable_get(ivar) if instance_variable_defined?(ivar)
object = if @attrs[key1]
if key2.nil?
Twitter.const_get(klass).new(@attrs[key1])
def self.define_attribute_method(key1, klass=nil, key2=nil)
define_method(key1) do
memoize(key1) do
if klass.nil?
@attrs[key1]
else
attrs = @attrs.dup
value = attrs.delete(key1)
Twitter.const_get(klass).new(value.update(key2 => attrs))
if @attrs[key1]
if key2.nil?
Twitter.const_get(klass).new(@attrs[key1])
else
attrs = @attrs.dup
value = attrs.delete(key1)
Twitter.const_get(klass).new(value.update(key2 => attrs))
end
else
Twitter::NullObject.new
end
end
else
Twitter::NullObject.new
end
instance_variable_set(ivar, object)
end
define_method "#{key1}?" do
!!self.send(key1)
end

# Dynamically define a predicate method for an attribute
#
# @param key [Symbol]
def self.define_predicate_method(key)
define_method(:"#{key}?") do
!!send(key)
end
end

# Construct an object from a response hash
#
# @param response [Hash]
# @return [Twitter::Base]
def self.from_response(response={})
new(response[:body])
end

# Initializes a new object
#
# @param attrs [Hash]
Expand All @@ -75,11 +86,18 @@ def initialize(attrs={})
#
# @param method [String, Symbol] Message to send to the object
def [](method)
send(method.to_sym)
send(method)
rescue NoMethodError
nil
end

def memoize(key, &block)
ivar = :"@#{key}"
return instance_variable_get(ivar) if instance_variable_defined?(ivar)
result = block.call
instance_variable_set(ivar, result)
end

private

# @param attr [Symbol]
Expand Down

0 comments on commit 3f05440

Please sign in to comment.