structure 0.21.0 → 0.22.0
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/Gemfile +6 -1
- data/README.md +3 -3
- data/Rakefile +1 -1
- data/lib/structure/json.rb +58 -0
- data/lib/structure/version.rb +1 -1
- data/lib/structure.rb +124 -145
- data/structure.gemspec +2 -2
- data/test/structure_test.rb +49 -57
- metadata +8 -8
- data/lib/structure/ext/active_support.rb +0 -19
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
[](http://travis-ci.org/hakanensari/structure)
|
4
4
|
|
5
|
-
Structure is a typed
|
5
|
+
Structure is a typed key/value container.
|
6
6
|
|
7
7
|
class Person < Structure
|
8
|
-
key
|
9
|
-
|
8
|
+
key :name
|
9
|
+
key :friends, Array, []
|
10
10
|
end
|
11
11
|
|
12
12
|
Please see the [wiki] [1] for more detail.
|
data/Rakefile
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
begin
|
2
|
+
JSON::JSON_LOADED
|
3
|
+
rescue NameError
|
4
|
+
require 'json'
|
5
|
+
end
|
6
|
+
|
7
|
+
class Structure
|
8
|
+
module JSON
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
# Converts structure to its JSON representation
|
14
|
+
#
|
15
|
+
# @param [Hash] args
|
16
|
+
# @return [JSON] a JSON representation of the structure
|
17
|
+
def to_json(*args)
|
18
|
+
{ ::JSON.create_id => self.class.name }.
|
19
|
+
merge(@attributes).
|
20
|
+
to_json(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
if defined? ActiveSupport
|
24
|
+
# Converts structure to its JSON representation
|
25
|
+
#
|
26
|
+
# @param [Hash] options
|
27
|
+
# @return [JSON] a JSON representation of the structure
|
28
|
+
def as_json(options = nil)
|
29
|
+
subset = if options
|
30
|
+
if only = options[:only]
|
31
|
+
@attributes.slice(*Array.wrap(only))
|
32
|
+
elsif except = options[:except]
|
33
|
+
@attributes.except(*Array.wrap(except))
|
34
|
+
else
|
35
|
+
@attributes.dup
|
36
|
+
end
|
37
|
+
else
|
38
|
+
@attributes.dup
|
39
|
+
end
|
40
|
+
|
41
|
+
{ ::JSON.create_id => self.class.name }.
|
42
|
+
merge(subset)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module ClassMethods
|
47
|
+
# Builds a structure out of its JSON representation
|
48
|
+
#
|
49
|
+
# @param [Hash] hsh a hashified JSON
|
50
|
+
# @return [Structure] a structure
|
51
|
+
def json_create(hsh)
|
52
|
+
hsh.delete('json_class')
|
53
|
+
|
54
|
+
new(hsh)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/structure/version.rb
CHANGED
data/lib/structure.rb
CHANGED
@@ -1,211 +1,190 @@
|
|
1
|
-
|
2
|
-
JSON::JSON_LOADED
|
3
|
-
rescue NameError
|
4
|
-
require 'json'
|
5
|
-
end
|
6
|
-
|
7
|
-
# Structure is a nestable, typed key/value container.
|
1
|
+
# Structure is a typed key/value container
|
8
2
|
#
|
3
|
+
# @example
|
9
4
|
# class Person < Structure
|
10
|
-
# key
|
11
|
-
#
|
5
|
+
# key :name
|
6
|
+
# key :friends, Array, []
|
12
7
|
# end
|
13
8
|
#
|
14
9
|
class Structure
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
BasicObject = ::BlankSlate
|
25
|
-
else
|
26
|
-
class BasicObject
|
27
|
-
instance_methods.each do |mth|
|
28
|
-
undef_method(mth) unless mth =~ /\A(__|instance_eval)/
|
10
|
+
# Summon a Basic Object.
|
11
|
+
unless defined? BasicObject
|
12
|
+
if defined? BlankSlate
|
13
|
+
BasicObject = BlankSlate
|
14
|
+
else
|
15
|
+
class BasicObject
|
16
|
+
instance_methods.each do |mth|
|
17
|
+
undef_method(mth) unless mth =~ /__/
|
18
|
+
end
|
29
19
|
end
|
30
20
|
end
|
31
21
|
end
|
32
22
|
|
33
|
-
# A
|
34
|
-
# known as "lazy evaluation."
|
23
|
+
# A wrapper for lazy-evaluating undeclared classes
|
35
24
|
#
|
36
|
-
#
|
37
|
-
|
38
|
-
|
25
|
+
# @note Borrowed from the same-named class in Ohm
|
26
|
+
class Wrapper < BasicObject
|
27
|
+
# Wraps specified class in a wrapper if it is not already wrapped
|
28
|
+
#
|
29
|
+
# @param [Class] klass
|
30
|
+
# @return [Wrapper]
|
31
|
+
def self.wrap(klass)
|
32
|
+
klass.class == self ? klass : new(klass.to_s)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Creates a new wrapper for specified class name
|
36
|
+
#
|
37
|
+
# @param [#to_s] name
|
39
38
|
def initialize(name)
|
40
|
-
@name = name
|
39
|
+
@name = name.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Class] the class of the object
|
43
|
+
def class
|
44
|
+
Wrapper
|
41
45
|
end
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
# Unwraps wrapped class
|
48
|
+
#
|
49
|
+
# @return [Class] the unwrapped class
|
50
|
+
def unwrap
|
51
|
+
@name.split('::').inject(::Kernel) do |parent, child|
|
52
|
+
parent.const_get(child)
|
53
|
+
end
|
45
54
|
end
|
46
55
|
|
56
|
+
private
|
57
|
+
|
47
58
|
def method_missing(mth, *args, &block)
|
48
59
|
@unwrapped ? super : @unwrapped = true
|
49
60
|
::Kernel.const_get(@name).send(mth, *args, &block)
|
50
61
|
ensure
|
51
62
|
@unwrapped = false
|
52
|
-
end
|
63
|
+
end
|
53
64
|
end
|
54
65
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
66
|
+
# A key definition
|
67
|
+
class Definition
|
68
|
+
# Creates a key definition
|
69
|
+
#
|
70
|
+
# @param [Class] type the key type
|
71
|
+
# @param [Object] default an optional default value
|
72
|
+
def initialize(type, default = nil)
|
73
|
+
@wrapper = Wrapper.wrap(type)
|
74
|
+
@default = default
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return the default value for the key
|
78
|
+
attr :default
|
79
|
+
|
80
|
+
# @return [Class] the key type
|
81
|
+
def type
|
82
|
+
@type ||= @wrapper.unwrap
|
59
83
|
end
|
60
84
|
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
|
85
|
+
# Typecasts specified value
|
86
|
+
#
|
87
|
+
# @param [Object] val a value
|
88
|
+
# @raise [TypeError] value isn't a type
|
89
|
+
# @return [Object] a typecast value
|
90
|
+
def typecast(val)
|
91
|
+
if val.nil? || val.is_a?(type)
|
92
|
+
val.dup rescue val
|
93
|
+
elsif Kernel.respond_to?(type.to_s)
|
94
|
+
Kernel.send(type.to_s, val)
|
95
|
+
else
|
96
|
+
raise TypeError, "#{val} isn't a #{type}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class << self
|
102
|
+
# @return [Hash] a collection of keys and their definitions
|
103
|
+
def blueprint
|
104
|
+
@blueprint ||= {}
|
65
105
|
end
|
66
106
|
|
67
|
-
# Defines
|
107
|
+
# Defines a key
|
108
|
+
#
|
109
|
+
# @note Key type defaults to +String+ if not specified.
|
68
110
|
#
|
69
|
-
#
|
70
|
-
|
111
|
+
# @param [#to_sym] name the key name
|
112
|
+
# @param [Class] type an optional key type
|
113
|
+
# @param [Object] default an optional default value
|
114
|
+
# @raise [NameError] name is already taken
|
115
|
+
def key(name, type = String, default = nil)
|
71
116
|
name = name.to_sym
|
72
117
|
|
73
118
|
if method_defined?(name)
|
74
119
|
raise NameError, "#{name} is taken"
|
75
120
|
end
|
76
121
|
|
77
|
-
|
78
|
-
defaults[name] = default
|
79
|
-
else
|
122
|
+
if default && !default.is_a?(type)
|
80
123
|
raise TypeError, "#{default} isn't a #{type}"
|
81
124
|
end
|
82
125
|
|
83
|
-
|
126
|
+
# Add key to blueprint.
|
127
|
+
blueprint[name] = Definition.new(type, default)
|
84
128
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
val.dup rescue val
|
89
|
-
elsif Kernel.respond_to?(type.to_s)
|
90
|
-
Kernel.send(type.to_s, val)
|
91
|
-
else
|
92
|
-
raise TypeError, "#{val} isn't a #{type}"
|
93
|
-
end
|
129
|
+
# Define getter.
|
130
|
+
define_method(name) do
|
131
|
+
@attributes[name]
|
94
132
|
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Defines an attribute that is an array and defaults to an empty
|
98
|
-
# one.
|
99
|
-
def many(name)
|
100
|
-
key name, Array, []
|
101
|
-
end
|
102
133
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
hsh = hsh.inject({}) do |a, (k, v)|
|
107
|
-
a[Inflector.underscore(k)] =
|
108
|
-
case v
|
109
|
-
when Hash
|
110
|
-
Structure.new(v)
|
111
|
-
when Array
|
112
|
-
v.map { |e| e.is_a?(Hash) ? Structure.new(e) : e }
|
113
|
-
else
|
114
|
-
v
|
115
|
-
end
|
116
|
-
a
|
117
|
-
end
|
118
|
-
|
119
|
-
klass = Class.new(Structure) do
|
120
|
-
hsh.keys.each { |k| key k }
|
134
|
+
# Define setter.
|
135
|
+
define_method("#{name}=") do |val|
|
136
|
+
@attributes[name] = self.class.blueprint[name].typecast(val)
|
121
137
|
end
|
122
|
-
|
123
|
-
klass.new(hsh)
|
124
138
|
end
|
125
139
|
|
126
|
-
|
127
|
-
# assuming they will be defined later in the text.
|
128
|
-
def const_missing(name)
|
129
|
-
Double.new(name)
|
130
|
-
end; private :const_missing
|
140
|
+
private
|
131
141
|
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
end; private :inherited
|
142
|
+
def const_missing(name)
|
143
|
+
Wrapper.new(name)
|
144
|
+
end
|
137
145
|
end
|
138
146
|
|
139
|
-
#
|
147
|
+
# Builds a new structure
|
140
148
|
#
|
141
|
-
#
|
149
|
+
# @param [Hash] hsh a hash of key-value pairs
|
142
150
|
def initialize(hsh = {})
|
143
|
-
@attributes =
|
144
|
-
a[k] = v.dup rescue v
|
151
|
+
@attributes = blueprint.inject({}) do |a, (k, v)|
|
152
|
+
a[k] = v.default.dup rescue v.default
|
145
153
|
a
|
146
154
|
end
|
147
155
|
|
148
156
|
hsh.each { |k, v| self.send("#{k}=", v) }
|
149
157
|
end
|
150
158
|
|
151
|
-
#
|
152
|
-
attr :attributes
|
153
|
-
|
154
|
-
# Calls block once for each attribute in the structure, passing that
|
155
|
-
# attribute as a parameter.
|
156
|
-
def each(&block)
|
157
|
-
attributes.each { |v| block.call(v) }
|
158
|
-
end
|
159
|
-
|
160
|
-
# Converts structure to a hash.
|
159
|
+
# @return [Hash] a hash representation of the structure
|
161
160
|
def to_hash
|
162
|
-
attributes.inject({}) do |a, (k, v)|
|
163
|
-
a[k] =
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
161
|
+
@attributes.inject({}) do |a, (k, v)|
|
162
|
+
a[k] = if v.respond_to?(:to_hash)
|
163
|
+
v.to_hash
|
164
|
+
elsif v.is_a?(Array)
|
165
|
+
v.map { |e| e.respond_to?(:to_hash) ? e.to_hash : e }
|
166
|
+
else
|
167
|
+
v
|
168
|
+
end
|
171
169
|
|
172
170
|
a
|
173
171
|
end
|
174
172
|
end
|
175
173
|
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
# Compares this object with another object for equality. A Structure
|
184
|
-
# is equal to the other object when both are of the same class and
|
185
|
-
# the their attributes are the same.
|
174
|
+
# Compares this object with another object for equality
|
175
|
+
#
|
176
|
+
# A structure is equal to another object when both are of the same
|
177
|
+
# class and their attributes are the same.
|
178
|
+
#
|
179
|
+
# @param [Object] other another object
|
180
|
+
# @return [true, false]
|
186
181
|
def ==(other)
|
187
182
|
other.is_a?(self.class) && attributes == other.attributes
|
188
183
|
end
|
189
184
|
|
190
|
-
|
191
|
-
self.class.defaults
|
192
|
-
end; private :defaults
|
185
|
+
private
|
193
186
|
|
194
|
-
|
195
|
-
|
196
|
-
# string.
|
197
|
-
#
|
198
|
-
# You know where this is lifted from.
|
199
|
-
def self.underscore(camel_cased_word)
|
200
|
-
word = camel_cased_word.to_s.dup
|
201
|
-
word.gsub!(/::/, '/')
|
202
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
203
|
-
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
204
|
-
word.tr!("-", "_")
|
205
|
-
word.downcase!
|
206
|
-
word
|
207
|
-
end
|
187
|
+
def blueprint
|
188
|
+
self.class.blueprint
|
208
189
|
end
|
209
190
|
end
|
210
|
-
|
211
|
-
require 'structure/ext/active_support' if defined?(Rails)
|
data/structure.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ['Hakan Ensari']
|
10
10
|
s.email = ['code@papercavalier.com']
|
11
11
|
s.homepage = 'http://github.com/hakanensari/structure'
|
12
|
-
s.summary = 'A typed
|
13
|
-
s.description = 'Structure is a typed
|
12
|
+
s.summary = 'A typed key/value container'
|
13
|
+
s.description = 'Structure is a typed key/value container.'
|
14
14
|
|
15
15
|
s.rubyforge_project = 'structure'
|
16
16
|
|
data/test/structure_test.rb
CHANGED
@@ -1,51 +1,33 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
3
|
begin
|
4
4
|
require 'pry'
|
5
5
|
rescue LoadError
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
|
+
require 'structure'
|
9
|
+
require 'structure/json'
|
8
10
|
|
9
11
|
class Person < Structure
|
10
|
-
key
|
11
|
-
key
|
12
|
-
|
12
|
+
key :name
|
13
|
+
key :friends, Array, []
|
14
|
+
key :city, City
|
13
15
|
end
|
14
16
|
|
15
|
-
class
|
16
|
-
key :
|
17
|
-
key :lat, Float
|
17
|
+
class City < Structure
|
18
|
+
key :name
|
18
19
|
end
|
19
20
|
|
20
|
-
class TestStructure <
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
::Kernel.const_set(:Foo, 1)
|
26
|
-
assert_kind_of Fixnum, double
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_anonymous
|
30
|
-
hsh = { 'FirstName' => 'John', 'LastName' => 'Doe' }
|
31
|
-
str = Structure.new(hsh)
|
32
|
-
assert_equal hsh['FirstName'], str.first_name
|
33
|
-
assert_equal hsh['LastName'], str.last_name
|
34
|
-
assert_raise(NoMethodError) { str.FirstName }
|
35
|
-
end
|
21
|
+
class TestStructure < MiniTest::Unit::TestCase
|
22
|
+
def test_lazy_evaluation
|
23
|
+
wrapper = Structure::Wrapper.new(:Foo)
|
24
|
+
assert_raises(NameError) { wrapper.bar }
|
25
|
+
assert_raises(NameError) { wrapper.unwrap.bar }
|
36
26
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
}
|
42
|
-
str = Structure.new(hsh)
|
43
|
-
assert_equal hsh['Address']['City'], str.address.city
|
44
|
-
assert_equal hsh['Friends'].first['Name'], str.friends.first.name
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_enumeration
|
48
|
-
assert_respond_to Person.new, :map
|
27
|
+
klass = Class.new { def self.bar; end }
|
28
|
+
::Kernel.const_set(:Foo, klass)
|
29
|
+
assert_respond_to wrapper, :bar
|
30
|
+
assert_equal Foo, wrapper.unwrap
|
49
31
|
end
|
50
32
|
|
51
33
|
def test_accessors
|
@@ -54,24 +36,24 @@ class TestStructure < Test::Unit::TestCase
|
|
54
36
|
end
|
55
37
|
|
56
38
|
def test_key_errors
|
57
|
-
|
58
|
-
|
39
|
+
assert_raises(NameError) { Person.key :class }
|
40
|
+
assert_raises(TypeError) { Person.key :foo, Hash, 1 }
|
59
41
|
end
|
60
42
|
|
61
43
|
def test_key_defaults
|
62
44
|
assert_equal [], Person.new.friends
|
63
45
|
end
|
64
46
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
assert_kind_of
|
47
|
+
def test_typecasting
|
48
|
+
person = Person.new
|
49
|
+
person.name = 123
|
50
|
+
assert_kind_of String, person.name
|
69
51
|
|
70
|
-
|
71
|
-
assert_nil
|
52
|
+
person.name = nil
|
53
|
+
assert_nil person.name
|
72
54
|
end
|
73
55
|
|
74
|
-
def
|
56
|
+
def test_many_relationship
|
75
57
|
person = Person.new
|
76
58
|
assert_equal [], person.friends
|
77
59
|
|
@@ -80,26 +62,36 @@ class TestStructure < Test::Unit::TestCase
|
|
80
62
|
assert_equal 0, person.friends.first.friends.size
|
81
63
|
end
|
82
64
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
65
|
+
def test_new
|
66
|
+
person = Person.new(:name => 'John')
|
67
|
+
assert_equal 'John', person.name
|
68
|
+
|
69
|
+
other = Person.new(:name => 'Jane', :friends => [person])
|
70
|
+
assert_equal 'John', other.friends.first.name
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_to_hash
|
74
|
+
person = Person.new(:name => 'John')
|
75
|
+
person.friends << Person.new(:name => 'Jane')
|
76
|
+
hash = person.to_hash
|
77
|
+
|
78
|
+
assert_equal 'John', hash[:name]
|
79
|
+
assert_equal 'Jane', hash[:friends].first[:name]
|
80
|
+
end
|
89
81
|
|
90
82
|
def test_json
|
91
|
-
|
92
|
-
|
83
|
+
Person.send :include, Structure::JSON
|
84
|
+
|
85
|
+
person = Person.new(:name => 'John')
|
86
|
+
person.friends << Person.new(:name => 'Jane')
|
93
87
|
json = person.to_json
|
94
88
|
assert_kind_of Person, JSON.parse(json)
|
95
89
|
assert_kind_of Person, JSON.parse(json).friends.first
|
96
|
-
|
97
90
|
assert_equal false, person.respond_to?(:as_json)
|
98
91
|
|
99
92
|
require 'active_support/ordered_hash'
|
100
93
|
require 'active_support/json'
|
101
|
-
|
102
|
-
|
94
|
+
load 'structure/json.rb'
|
103
95
|
assert_equal true, person.as_json(:only => :name).has_key?(:name)
|
104
96
|
assert_equal false, person.as_json(:except => :name).has_key?(:name)
|
105
97
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: structure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,9 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: Structure is a typed
|
14
|
+
description: Structure is a typed key/value container.
|
15
15
|
email:
|
16
16
|
- code@papercavalier.com
|
17
17
|
executables: []
|
@@ -25,7 +25,7 @@ files:
|
|
25
25
|
- README.md
|
26
26
|
- Rakefile
|
27
27
|
- lib/structure.rb
|
28
|
-
- lib/structure/
|
28
|
+
- lib/structure/json.rb
|
29
29
|
- lib/structure/version.rb
|
30
30
|
- structure.gemspec
|
31
31
|
- test/structure_test.rb
|
@@ -43,7 +43,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
43
43
|
version: '0'
|
44
44
|
segments:
|
45
45
|
- 0
|
46
|
-
hash:
|
46
|
+
hash: 2031698207987898845
|
47
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
48
|
none: false
|
49
49
|
requirements:
|
@@ -52,12 +52,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
52
52
|
version: '0'
|
53
53
|
segments:
|
54
54
|
- 0
|
55
|
-
hash:
|
55
|
+
hash: 2031698207987898845
|
56
56
|
requirements: []
|
57
57
|
rubyforge_project: structure
|
58
|
-
rubygems_version: 1.8.
|
58
|
+
rubygems_version: 1.8.10
|
59
59
|
signing_key:
|
60
60
|
specification_version: 3
|
61
|
-
summary: A typed
|
61
|
+
summary: A typed key/value container
|
62
62
|
test_files:
|
63
63
|
- test/structure_test.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class Structure
|
2
|
-
# Converts structure to a JSON representation.
|
3
|
-
def as_json(options = nil)
|
4
|
-
subset = if options
|
5
|
-
if only = options[:only]
|
6
|
-
attributes.slice(*Array.wrap(only))
|
7
|
-
elsif except = options[:except]
|
8
|
-
attributes.except(*Array.wrap(except))
|
9
|
-
else
|
10
|
-
attributes.dup
|
11
|
-
end
|
12
|
-
else
|
13
|
-
attributes.dup
|
14
|
-
end
|
15
|
-
|
16
|
-
{ JSON.create_id => self.class.name }.
|
17
|
-
merge(subset)
|
18
|
-
end
|
19
|
-
end
|