object_struct 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +5 -0
- data/lib/object_struct/object_struct.rb +3 -3
- metadata +2 -3
- data/lib/object_struct/#object_struct.rb# +0 -154
data/CHANGELOG
CHANGED
@@ -25,7 +25,7 @@
|
|
25
25
|
# @abstract You probably want to subclass ObjectStruct, to reflect your business
|
26
26
|
# entities. See the README for example use.
|
27
27
|
class ObjectStruct < OpenStruct
|
28
|
-
VERSION = '0.0.
|
28
|
+
VERSION = '0.0.3'
|
29
29
|
|
30
30
|
# Delegated to Hash#each
|
31
31
|
def each &blk
|
@@ -74,10 +74,10 @@ class ObjectStruct < OpenStruct
|
|
74
74
|
if name =~ /^has_([a-z_]+)\?$/
|
75
75
|
if respond_to? (field = $1.to_sym)
|
76
76
|
result = (send field)
|
77
|
-
if result.respond_to?(:count) && result.method(:count).arity
|
77
|
+
if result.respond_to?(:count) && result.method(:count).arity < 1
|
78
78
|
(result.count > 0)
|
79
79
|
else
|
80
|
-
result
|
80
|
+
result ? true : false
|
81
81
|
end
|
82
82
|
end
|
83
83
|
else
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Quid, Inc.
|
@@ -52,7 +52,6 @@ extra_rdoc_files: []
|
|
52
52
|
|
53
53
|
files:
|
54
54
|
- lib/object_struct/object_struct.rb
|
55
|
-
- lib/object_struct/#object_struct.rb#
|
56
55
|
- lib/object_struct.rb
|
57
56
|
- test/test_data.json
|
58
57
|
- test/test_object_struct.rb
|
@@ -1,154 +0,0 @@
|
|
1
|
-
# ---------------------------------------------------------------------------
|
2
|
-
# Copyright 2010, Quid, Inc.
|
3
|
-
#
|
4
|
-
# object_struct is free software: you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation, either version 3 of the License, or
|
7
|
-
# (at your option) any later version.
|
8
|
-
#
|
9
|
-
# object_struct is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with object_struct. If not, see <http://www.gnu.org/licenses/>.
|
16
|
-
#
|
17
|
-
# ---------------------------------------------------------------------------
|
18
|
-
|
19
|
-
|
20
|
-
# Inherit from ObjectStruct to allow object-style accesses to a hash parameter
|
21
|
-
# passed to {ObjectStruct#initialize initialize}. Properties are lazy-loaded.
|
22
|
-
#
|
23
|
-
# @see OpenStruct
|
24
|
-
#
|
25
|
-
# @abstract You probably want to subclass ObjectStruct, to reflect your business
|
26
|
-
# entities. See the README for example use.
|
27
|
-
class ObjectStruct < OpenStruct
|
28
|
-
VERSION = '0.0.2 '
|
29
|
-
|
30
|
-
# Delegated to Hash#each
|
31
|
-
def each &blk
|
32
|
-
to_h.each &blk
|
33
|
-
end
|
34
|
-
|
35
|
-
# Delegated to Hash#values
|
36
|
-
def values
|
37
|
-
to_h.values
|
38
|
-
end
|
39
|
-
|
40
|
-
# Specify the type of a particular property.
|
41
|
-
#
|
42
|
-
# @param [Hash] options The options hash. Pass any :property_name => ClassName
|
43
|
-
# to enforce that type.
|
44
|
-
#
|
45
|
-
# @option options [Boolean] :plural (false) Whether the property is plural,
|
46
|
-
# e.g. an Array of the class specified. (Yes, this means that if you have a
|
47
|
-
# property named :plural, you cannot specify its type.)
|
48
|
-
def self.property_type(options)
|
49
|
-
plural = options.delete(:plural)
|
50
|
-
property, type = *options.first
|
51
|
-
class_name = plural ? property.to_s.classify : property.to_s.camelize
|
52
|
-
Object.const_set class_name, Class.new(type)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Create a new ObjectStruct.
|
56
|
-
#
|
57
|
-
# @param [Hash] data a Hash representing your data. Keys are used to identify
|
58
|
-
# the type of the property.
|
59
|
-
def initialize(data)
|
60
|
-
@table = Hash.new {|h, k| raise NoMethodError, "undefined property #{k} for #{self}"}
|
61
|
-
data = {'data' => data} unless data.respond_to? :each
|
62
|
-
for k,v in data
|
63
|
-
@table[k.to_sym] = self.class.value_maybe_promise(k, v)
|
64
|
-
new_ostruct_member(k)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Provides has_property_name? methods. Intercepts messages matching
|
69
|
-
# /^has_[a-z_]+\?$/. If the method matches this regex, ObjectStruct will see
|
70
|
-
# if it responds to such a property. If that property responds to a count
|
71
|
-
# method, it will furthermore make sure #count is greater than zero.
|
72
|
-
# @return the property, if it exists, nil otherwise
|
73
|
-
def method_missing(name, *args)
|
74
|
-
if name =~ /^has_([a-z_]+)\?$/
|
75
|
-
if respond_to? (field = $1.to_sym)
|
76
|
-
result = (send field)
|
77
|
-
if result.respond_to?(:count) && result.method(:count).arity == 0
|
78
|
-
(result.count > 0)
|
79
|
-
else
|
80
|
-
result
|
81
|
-
end
|
82
|
-
end
|
83
|
-
else
|
84
|
-
super(name, *args)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# Specifically provide the object_id. If your objects have IDs, choose a more
|
89
|
-
# descriptive name.
|
90
|
-
def id
|
91
|
-
object_id
|
92
|
-
end
|
93
|
-
|
94
|
-
protected
|
95
|
-
|
96
|
-
def new_ostruct_member(name)
|
97
|
-
name = name.to_sym
|
98
|
-
unless self.respond_to?(name)
|
99
|
-
class << self; self; end.class_eval do
|
100
|
-
define_method(name) { ObjectStruct.demand @table[name] }
|
101
|
-
define_method("#{name}=") { |x| @table[name] = x }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
name
|
105
|
-
end
|
106
|
-
|
107
|
-
# Recursively convert a value to an ObjectStruct (or a class matching the
|
108
|
-
# type, if it exists).
|
109
|
-
#
|
110
|
-
# @param [Array, Hash] value the value to convert. Arrays are converted
|
111
|
-
# recursively, each value to the requested type. Hashes are converted
|
112
|
-
# directly to the requested type.
|
113
|
-
#
|
114
|
-
# @param [String, #to_s] type the type of the value (or values in the array).
|
115
|
-
# This method falls back to ObjectStruct if it cannot find a class matching
|
116
|
-
# the type.
|
117
|
-
#
|
118
|
-
# @return [type/ObjectStruct, Array<type/ObjectStruct>, value] the type
|
119
|
-
# requested, or an ObjectStruct; or an Array thereof; or the value if it
|
120
|
-
# neither an Array nor Hash.
|
121
|
-
def self.convert(value, type = nil)
|
122
|
-
klass = ((value.is_a? Array) ? type.to_s.classify : type.to_s.camelize).constantize rescue ObjectStruct
|
123
|
-
|
124
|
-
case value
|
125
|
-
when Array
|
126
|
-
value.map{|e| convert(e, klass.to_s)}
|
127
|
-
when Hash
|
128
|
-
klass.new(value)
|
129
|
-
else
|
130
|
-
value
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
private
|
135
|
-
|
136
|
-
def to_h
|
137
|
-
result = {}
|
138
|
-
@table.each {|name, value| result[name.to_s] = value}
|
139
|
-
result
|
140
|
-
end
|
141
|
-
|
142
|
-
def self.value_maybe_promise(key, value)
|
143
|
-
case value
|
144
|
-
when Array, Hash
|
145
|
-
Lazy::Promise.new {convert(value, key)}
|
146
|
-
else
|
147
|
-
value
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.demand value
|
152
|
-
(value.is_a? Lazy::Promise) ? value.__result__ : value
|
153
|
-
end
|
154
|
-
end
|