Permalink
Browse files

Refactor code common to Twitter::Base#attr_reader and object_attr_reader

  • Loading branch information...
1 parent 11fa58a commit 3f05440f1e0dc443fbd250c8b3c58e6239576091 @sferik committed Jul 28, 2013
Showing with 53 additions and 35 deletions.
  1. +53 −35 lib/twitter/base.rb
View
@@ -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]
@@ -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]

0 comments on commit 3f05440

Please sign in to comment.