-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
base.rb
145 lines (128 loc) · 3.53 KB
/
base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
require 'addressable/uri'
require 'forwardable'
require 'memoizable'
require 'twitter/null_object'
module Twitter
class Base
extend Forwardable
include Memoizable
attr_reader :attrs
alias to_h attrs
alias to_hash attrs
alias to_hsh attrs
class << self
# Construct an object from a response hash
#
# @param response [Hash]
# @return [Twitter::Base]
def from_response(response={})
new(response[:body])
end
# Define methods that retrieve the value from attributes
#
# @param attrs [Array, Symbol]
def attr_reader(*attrs)
attrs.each do |attr|
define_attribute_method(attr)
define_predicate_method(attr)
end
end
# Define object methods from attributes
#
# @param klass [Symbol]
# @param key1 [Symbol]
# @param key2 [Symbol]
def object_attr_reader(klass, key1, key2=nil)
define_attribute_method(key1, klass, key2)
define_predicate_method(key1)
end
# Define URI methods from attributes
#
# @param attrs [Array, Symbol]
def uri_attr_reader(*attrs)
attrs.each do |uri_key|
array = uri_key.to_s.split("_")
index = array.index("uri")
array[index] = "url"
url_key = array.join("_").to_sym
define_uri_method(uri_key, url_key)
alias_method(url_key, uri_key)
define_predicate_method(uri_key, url_key)
alias_method(:"#{url_key}?", :"#{uri_key}?")
end
end
# Define display_uri attribute methods
def display_uri_attr_reader
define_attribute_method(:display_url)
alias_method(:display_uri, :display_url)
define_predicate_method(:display_uri, :display_url)
alias_method(:display_url?, :display_uri?)
end
private
# Dynamically define a method for a URI
#
# @param key1 [Symbol]
# @param key2 [Symbol]
def define_uri_method(key1, key2)
define_method(key1) do ||
URI.parse(@attrs[key2]) if @attrs[key2]
end
memoize(key1)
end
# Dynamically define a method for an attribute
#
# @param key1 [Symbol]
# @param klass [Symbol]
# @param key2 [Symbol]
def define_attribute_method(key1, klass=nil, key2=nil)
define_method(key1) do ||
if klass.nil?
@attrs[key1]
else
if @attrs[key1]
attrs = attrs_for_object(key1, key2)
Twitter.const_get(klass).new(attrs)
else
NullObject.new
end
end
end
memoize(key1)
end
# Dynamically define a predicate method for an attribute
#
# @param key1 [Symbol]
# @param key2 [Symbol]
def define_predicate_method(key1, key2=key1)
define_method(:"#{key1}?") do ||
!!@attrs[key2]
end
memoize(:"#{key1}?")
end
end
# Initializes a new object
#
# @param attrs [Hash]
# @return [Twitter::Base]
def initialize(attrs={})
@attrs = attrs || {}
end
# Fetches an attribute of an object using hash notation
#
# @param method [String, Symbol] Message to send to the object
def [](method)
send(method.to_sym)
rescue NoMethodError
nil
end
private
def attrs_for_object(key1, key2=nil)
if key2.nil?
@attrs[key1]
else
attrs = @attrs.dup
attrs.delete(key1).merge(key2 => attrs)
end
end
end
end