cloudinary 1.29.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,284 +0,0 @@
1
- #
2
- # = ostruct.rb: OpenStruct implementation
3
- #
4
- # Author:: Yukihiro Matsumoto
5
- # Documentation:: Gavin Sinclair
6
- #
7
- # OpenStruct allows the creation of data objects with arbitrary attributes.
8
- # See OpenStruct for an example.
9
- #
10
-
11
- #
12
- # An OpenStruct is a data structure, similar to a Hash, that allows the
13
- # definition of arbitrary attributes with their accompanying values. This is
14
- # accomplished by using Ruby's metaprogramming to define methods on the class
15
- # itself.
16
- #
17
- # == Examples:
18
- #
19
- # require 'ostruct'
20
- #
21
- # person = OpenStruct.new
22
- # person.name = "John Smith"
23
- # person.age = 70
24
- # person.pension = 300
25
- #
26
- # puts person.name # -> "John Smith"
27
- # puts person.age # -> 70
28
- # puts person.address # -> nil
29
- #
30
- # An OpenStruct employs a Hash internally to store the methods and values and
31
- # can even be initialized with one:
32
- #
33
- # australia = OpenStruct.new(:country => "Australia", :population => 20_000_000)
34
- # p australia # -> <OpenStruct country="Australia" population=20000000>
35
- #
36
- # Hash keys with spaces or characters that would normally not be able to use for
37
- # method calls (e.g. ()[]*) will not be immediately available on the
38
- # OpenStruct object as a method for retrieval or assignment, but can be still be
39
- # reached through the Object#send method.
40
- #
41
- # measurements = OpenStruct.new("length (in inches)" => 24)
42
- # measurements.send("length (in inches)") # -> 24
43
- #
44
- # data_point = OpenStruct.new(:queued? => true)
45
- # data_point.queued? # -> true
46
- # data_point.send("queued?=",false)
47
- # data_point.queued? # -> false
48
- #
49
- # Removing the presence of a method requires the execution the delete_field
50
- # method as setting the property value to +nil+ will not remove the method.
51
- #
52
- # first_pet = OpenStruct.new(:name => 'Rowdy', :owner => 'John Smith')
53
- # first_pet.owner = nil
54
- # second_pet = OpenStruct.new(:name => 'Rowdy')
55
- #
56
- # first_pet == second_pet # -> false
57
- #
58
- # first_pet.delete_field(:owner)
59
- # first_pet == second_pet # -> true
60
- #
61
- #
62
- # == Implementation:
63
- #
64
- # An OpenStruct utilizes Ruby's method lookup structure to and find and define
65
- # the necessary methods for properties. This is accomplished through the method
66
- # method_missing and define_method.
67
- #
68
- # This should be a consideration if there is a concern about the performance of
69
- # the objects that are created, as there is much more overhead in the setting
70
- # of these properties compared to using a Hash or a Struct.
71
- #
72
- class OpenStruct
73
- #
74
- # Creates a new OpenStruct object. By default, the resulting OpenStruct
75
- # object will have no attributes.
76
- #
77
- # The optional +hash+, if given, will generate attributes and values
78
- # (can be a Hash, an OpenStruct or a Struct).
79
- # For example:
80
- #
81
- # require 'ostruct'
82
- # hash = { "country" => "Australia", :population => 20_000_000 }
83
- # data = OpenStruct.new(hash)
84
- #
85
- # p data # -> <OpenStruct country="Australia" population=20000000>
86
- #
87
- def initialize(hash=nil)
88
- @table = {}
89
- if hash
90
- hash.each_pair do |k, v|
91
- k = k.to_sym
92
- @table[k] = v
93
- new_ostruct_member(k)
94
- end
95
- end
96
- end
97
-
98
- # Duplicate an OpenStruct object members.
99
- def initialize_copy(orig)
100
- super
101
- @table = @table.dup
102
- @table.each_key{|key| new_ostruct_member(key)}
103
- end
104
-
105
- #
106
- # Converts the OpenStruct to a hash with keys representing
107
- # each attribute (as symbols) and their corresponding values
108
- # Example:
109
- #
110
- # require 'ostruct'
111
- # data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
112
- # data.to_h # => {:country => "Australia", :population => 20000000 }
113
- #
114
- def to_h
115
- @table.dup
116
- end
117
-
118
- #
119
- # Yields all attributes (as a symbol) along with the corresponding values
120
- # or returns an enumerator if not block is given.
121
- # Example:
122
- #
123
- # require 'ostruct'
124
- # data = OpenStruct.new("country" => "Australia", :population => 20_000_000)
125
- # data.each_pair.to_a # => [[:country, "Australia"], [:population, 20000000]]
126
- #
127
- def each_pair
128
- return to_enum __method__ unless block_given?
129
- @table.each_pair{|p| yield p}
130
- end
131
-
132
- #
133
- # Provides marshalling support for use by the Marshal library.
134
- #
135
- def marshal_dump
136
- @table
137
- end
138
-
139
- #
140
- # Provides marshalling support for use by the Marshal library.
141
- #
142
- def marshal_load(x)
143
- @table = x
144
- @table.each_key{|key| new_ostruct_member(key)}
145
- end
146
-
147
- #
148
- # Used internally to check if the OpenStruct is able to be
149
- # modified before granting access to the internal Hash table to be modified.
150
- #
151
- def modifiable
152
- begin
153
- @modifiable = true
154
- rescue
155
- raise TypeError, "can't modify frozen #{self.class}", caller(3)
156
- end
157
- @table
158
- end
159
- protected :modifiable
160
-
161
- #
162
- # Used internally to defined properties on the
163
- # OpenStruct. It does this by using the metaprogramming function
164
- # define_singleton_method for both the getter method and the setter method.
165
- #
166
- def new_ostruct_member(name)
167
- name = name.to_sym
168
- unless respond_to?(name)
169
- define_singleton_method(name) { @table[name] }
170
- define_singleton_method("#{name}=") { |x| modifiable[name] = x }
171
- end
172
- name
173
- end
174
- protected :new_ostruct_member
175
-
176
- def method_missing(mid, *args) # :nodoc:
177
- mname = mid.id2name
178
- len = args.length
179
- if mname.chomp!('=')
180
- if len != 1
181
- raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
182
- end
183
- modifiable[new_ostruct_member(mname)] = args[0]
184
- elsif len == 0
185
- @table[mid]
186
- else
187
- raise NoMethodError, "undefined method `#{mid}' for #{self}", caller(1)
188
- end
189
- end
190
-
191
- # Returns the value of a member.
192
- #
193
- # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
194
- # person[:age] # => 70, same as ostruct.age
195
- #
196
- def [](name)
197
- @table[name.to_sym]
198
- end
199
-
200
- #
201
- # Sets the value of a member.
202
- #
203
- # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
204
- # person[:age] = 42 # => equivalent to ostruct.age = 42
205
- # person.age # => 42
206
- #
207
- def []=(name, value)
208
- modifiable[new_ostruct_member(name)] = value
209
- end
210
-
211
- #
212
- # Remove the named field from the object. Returns the value that the field
213
- # contained if it was defined.
214
- #
215
- # require 'ostruct'
216
- #
217
- # person = OpenStruct.new('name' => 'John Smith', 'age' => 70)
218
- #
219
- # person.delete_field('name') # => 'John Smith'
220
- #
221
- def delete_field(name)
222
- sym = name.to_sym
223
- singleton_class.__send__(:remove_method, sym, "#{name}=")
224
- @table.delete sym
225
- end
226
-
227
- InspectKey = :__inspect_key__ # :nodoc:
228
-
229
- #
230
- # Returns a string containing a detailed summary of the keys and values.
231
- #
232
- def inspect
233
- str = "#<#{self.class}"
234
-
235
- ids = (Thread.current[InspectKey] ||= [])
236
- if ids.include?(object_id)
237
- return str << ' ...>'
238
- end
239
-
240
- ids << object_id
241
- begin
242
- first = true
243
- for k,v in @table
244
- str << "," unless first
245
- first = false
246
- str << " #{k}=#{v.inspect}"
247
- end
248
- return str << '>'
249
- ensure
250
- ids.pop
251
- end
252
- end
253
- alias :to_s :inspect
254
-
255
- attr_reader :table # :nodoc:
256
- protected :table
257
-
258
- #
259
- # Compares this object and +other+ for equality. An OpenStruct is equal to
260
- # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
261
- # equal.
262
- #
263
- def ==(other)
264
- return false unless other.kind_of?(OpenStruct)
265
- @table == other.table
266
- end
267
-
268
- #
269
- # Compares this object and +other+ for equality. An OpenStruct is eql? to
270
- # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
271
- # eql?.
272
- #
273
- def eql?(other)
274
- return false unless other.kind_of?(OpenStruct)
275
- @table.eql?(other.table)
276
- end
277
-
278
- # Compute a hash-code for this OpenStruct.
279
- # Two hashes with the same content will have the same hash code
280
- # (and will be eql?).
281
- def hash
282
- @table.hash
283
- end
284
- end