structure 0.24.0 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9d097be9799d796318524e7594f98050b1d41be8
4
+ data.tar.gz: 710fa928be479806b678fc9c17ae3222d71f059b
5
+ SHA512:
6
+ metadata.gz: 1c5f7f760400a8eb044df7efaa9a2d08ed8b0128db23659f64bbf4a98b9d2311f4772176a93c52c90745a0da4658aeba9cd85eaaf8719dfce2e3caa5b07973bf
7
+ data.tar.gz: 1d1a43d8aac01183286e82832f38540b03f5a5d7c2f2487fefc5cf2ad422b03e433de0c7f0394663a06b0948b91dbafa2b0993a7f77e3cbe25ed9c9a92d0dd4b
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.gem
2
2
  .bundle
3
+ coverage
3
4
  pkg/*
4
5
  Gemfile.lock
data/Gemfile CHANGED
@@ -1,11 +1,2 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'activesupport' # Required for testing Rails compatibility
5
- gem 'pry' unless ENV['CI']
6
- gem 'rake'
7
-
8
- if RUBY_VERSION.include? '1.8'
9
- gem 'json'
10
- gem 'minitest'
11
- end
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2011 Hakan Ensari
3
+ Copyright (c) 2013 Hakan Ensari
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,8 +1,30 @@
1
- ![structure](http://f.cl.ly/items/2u2v0e3k2I3w1A0y2e25/ruby.png)
1
+ # Structure
2
2
 
3
- > Machines only work when they break down and by continually breaking
4
- > down.
3
+ Turn data (e.g. API responses) into immutable value objects in Ruby.
5
4
 
6
- [Read the API.](http://rubydoc.info/github/hakanensari/structure/master/Structure)
5
+ ## Usage
7
6
 
8
- [![travis](https://secure.travis-ci.org/hakanensari/structure.png?branch=master)](http://travis-ci.org/hakanensari/structure)
7
+ Mix in Structure and define values with `.value`.
8
+
9
+ ```ruby
10
+ class Location
11
+ include Structure
12
+
13
+ attr :res
14
+
15
+ def initialize(res)
16
+ @res = res
17
+ end
18
+
19
+ value :latitude do
20
+ res.fetch(:lat)
21
+ end
22
+
23
+ value :longitude do
24
+ res.fetch(:lng)
25
+ end
26
+ end
27
+
28
+ location = Location.new(lat: 10, lng: 100)
29
+ location.to_h # {:latitude=>10, :longitude=>100}
30
+ ```
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/testtask'
3
3
 
4
- task :default => :test
5
-
6
- Rake::TestTask.new do |test|
7
- test.libs += %w{lib test}
8
- test.test_files = FileList['test/**/*_test.rb']
4
+ Rake::TestTask.new do |t|
5
+ t.libs.push('lib')
6
+ t.test_files = FileList['test/**/*_test.rb']
9
7
  end
8
+
9
+ task :default => [:test]
data/lib/structure.rb CHANGED
@@ -1,278 +1,42 @@
1
- begin
2
- JSON::JSON_LOADED
3
- rescue NameError
4
- require 'json'
5
- end
6
-
7
- # Structure is a key/value container. On the most basic level, it mirrors the
8
- # functionality of OpenStruct:
9
- #
10
- # require 'structure'
11
- #
12
- # record = Structure.new
13
- # record.name = "John Smith"
14
- # record.age = 70
15
- # record.pension = 300
16
- #
17
- # puts record.name # -> "John Smith"
18
- # puts record.address # -> nil
19
- #
20
- # Build structures recursively:
21
- #
22
- # hash = {
23
- # "name" => "Australia",
24
- # "population" => "20000000",
25
- # "cities" => [
26
- # {
27
- # "name" => "Sydney",
28
- # "population" => "4100000"
29
- # },
30
- # {
31
- # "name" => "Melbourne",
32
- # "population" => "4000000"
33
- # } ]
34
- # }
35
- #
36
- # country = Structure.new(hash)
37
- # puts country.name # -> "Australia"
38
- # puts country.cities.count # -> 2
39
- # puts country.cities.first.name # -> "Sydney"
40
- #
41
- # Define optionally-typed fields in a structure:
42
- #
43
- # class Price < Structure
44
- # field :cents, Integer
45
- # field :currency, String, :default => "USD"
46
- # end
47
- #
48
- # hash = { "cents" => "100" }
49
- #
50
- # price = Price.new(hash)
51
- # puts price.cents # -> 100
52
- # puts price.currency # -> "USD"
53
- #
54
- # Alternatively, define a proc to cast or otherwise manipulate values and
55
- # assign defaults:
56
- #
57
- # class Product < Structure
58
- # field :sku, lambda(&:upcase)
59
- # field :created_at, String, :default => lambda { Time.now.to_s }
60
- # end
61
- #
62
- # product = Product.new(:sku => 'foo-bar')
63
- # puts product.sku # -> "FOO-BAR"
64
- #
65
- # Structures are fully conversant in JSON, which is quite handy in the
66
- # ephemeral landscape of APIs.
67
- class Structure
68
- class << self
69
- # @private
70
- attr_accessor :blueprint
71
-
72
- # Builds a structure out of a JSON representation.
73
- # @param [Hash] hsh a JSON representation translated to a hash
74
- # @return [Structure] a structure
75
- def json_create(hsh)
76
- hsh.delete('json_class')
77
- new(hsh)
78
- end
79
-
80
- # Creates a field.
81
- # @overload field(key, opts = {})
82
- # Creates a field.
83
- # @param [#to_sym] key the name of the field
84
- # @param [Hash] opts the options to create the field with
85
- # @option opts [Object] :default the default value
86
- # @overload field(key, type, opts = {})
87
- # Creates a typed field.
88
- # @param [#to_sym] key the name of the field
89
- # @param [Class, Proc] type the type to cast assigned values
90
- # @param [Hash] opts the options to create the field with
91
- # @option opts [Object] :default the default value
92
- def field(key, *args)
93
- opts = args.last.is_a?(Hash) ? args.pop : {}
94
- default = opts[:default]
95
- type = args.shift
96
- @blueprint[key] = { :type => type,
97
- :default => default }
98
- end
99
-
100
- alias key field
101
-
102
- # Syntactic sugar to create a typed field that defaults to an empty array.
103
- # @param key the name of the field
104
- def many(key)
105
- field(key, Array, :default => [])
106
- end
107
-
108
- # Syntactic sugar to create a field that stands in for another structure.
109
- # @param key the name of the field
110
- def one(key)
111
- field(key, lambda { |v| v.is_a?(Structure) ? v : Structure.new(v) })
112
- end
113
-
114
- private
115
-
116
- def inherited(child)
117
- child.blueprint = blueprint.dup
118
- end
119
- end
120
-
121
- @blueprint = {}
122
-
123
- # Creates a new structure.
124
- # @param [Hash] hsh an optional hash to populate fields
125
- def initialize(hsh = {})
126
- @table = blueprint.inject({}) do |a, (k, v)|
127
- default = if v[:default].is_a? Proc
128
- v[:default].call
129
- else
130
- v[:default].dup rescue v[:default]
131
- end
132
-
133
- a.merge new_field(k, v[:type]) => default
134
- end
135
-
136
- marshal_load(hsh)
1
+ module Structure
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ base.instance_variable_set(:@value_names, [])
137
5
  end
138
6
 
139
- # Deletes a field.
140
- # @param [#to_sym] key
141
- # @return [Object] the value of the deleted field
142
- def delete_field(key)
143
- key = key.to_sym
144
- class << self; self; end.class_eval do
145
- [key, "#{key}="].each { |m| remove_method m }
146
- end
147
-
148
- @table.delete key
149
- end
7
+ def values
8
+ vals = {}
9
+ self.class.value_names.each { |name| vals[name] = self.send(name) }
150
10
 
151
- # Provides marshalling support for use by the Marshal library.
152
- # @return [Hash] a hash of the keys and values of the structure
153
- def marshal_dump
154
- @table.inject({}) do |a, (k, v)|
155
- a.merge k => recursively_dump(v)
156
- end
11
+ vals
157
12
  end
13
+ alias :to_h :values
158
14
 
159
- # Provides marshalling support for use by the Marshal library.
160
- # @param [Hash] hsh a hash of keys and values to populate the structure
161
- def marshal_load(hsh)
162
- hsh.each do |k, v|
163
- self.send("#{new_field(k)}=", v)
164
- end
165
- end
166
-
167
- # @return [String] a JSON representation of the structure
168
- def to_json(*args)
169
- { JSON.create_id => self.class.name }.
170
- merge(marshal_dump).
171
- to_json(*args)
172
- end
173
-
174
- # @return [Boolean] whether the object and +other+ are equal
175
15
  def ==(other)
176
- other.is_a?(Structure) && @table == other.table
177
- end
178
-
179
- protected
180
-
181
- attr :table
182
-
183
- private
184
-
185
- def blueprint
186
- self.class.blueprint
16
+ values == other.values
187
17
  end
18
+ alias :eql? :==
188
19
 
189
- def initialize_copy(orig)
190
- super
191
- @table = @table.dup
192
- end
20
+ def inspect
21
+ str = "#<#{self.class}"
193
22
 
194
- def method_missing(mth, *args)
195
- name = mth.to_s
196
- len = args.length
197
- if name.chomp!('=') && mth != :[]=
198
- modifiable[new_field(name)] = recursively_load(args.first)
199
- elsif len == 0
200
- @table[new_field(mth)]
201
- else
202
- super
23
+ first = true
24
+ values.each do |k, v|
25
+ str << ',' unless first
26
+ first = false
27
+ str << " #{k}=#{v.inspect}"
203
28
  end
204
- end
205
29
 
206
- def modifiable
207
- if frozen?
208
- raise RuntimeError, "can't modify frozen #{self.class}", caller(3)
209
- end
210
-
211
- @table
30
+ str << '>'
212
31
  end
32
+ alias :to_s :inspect
213
33
 
214
- def new_field(key, type = nil)
215
- key = key.to_sym
216
- unless self.respond_to?(key)
217
- class << self; self; end.class_eval do
218
- define_method(key) { @table[key] }
219
-
220
- assignment =
221
- case type
222
- when nil
223
- lambda { |v| modifiable[key] = recursively_load(v) }
224
- when Proc
225
- lambda { |v| modifiable[key] = type.call(v) }
226
- when Class
227
- mth = type.to_s.to_sym
228
- if Kernel.respond_to?(mth)
229
- lambda { |v|
230
- modifiable[key] = v.nil? ? nil : Kernel.send(mth, v)
231
- }
232
- else
233
- lambda { |v|
234
- modifiable[key] =
235
- if v.nil? || v.is_a?(type)
236
- v
237
- else
238
- raise TypeError, "#{v} isn't a #{type}"
239
- end
240
- }
241
- end
242
- else
243
- raise TypeError, "#{type} isn't a valid type"
244
- end
34
+ module ClassMethods
35
+ attr :value_names
245
36
 
246
- define_method("#{key}=", assignment)
247
- end
37
+ def value(name, &blk)
38
+ define_method(name, &blk)
39
+ @value_names << name
248
40
  end
249
-
250
- key
251
- end
252
-
253
- def recursively_dump(val)
254
- if val.respond_to? :marshal_dump
255
- val.marshal_dump
256
- elsif val.is_a? Array
257
- val.map { |v| recursively_dump(v) }
258
- else
259
- val
260
- end
261
- end
262
-
263
- def recursively_load(val)
264
- case val
265
- when Hash
266
- self.class.new(val)
267
- when Array
268
- val.map { |v| recursively_load(v) }
269
- else
270
- val
271
- end
272
- end
273
-
274
- if defined? ActiveSupport
275
- require 'structure/ext/active_support'
276
- include Ext::ActiveSupport
277
41
  end
278
42
  end
@@ -1,3 +1,3 @@
1
- class Structure
2
- VERSION = '0.24.0'
1
+ module Structure
2
+ VERSION = '0.25.0'
3
3
  end
data/structure.gemspec CHANGED
@@ -1,21 +1,23 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path('../lib', __FILE__)
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
4
  require 'structure/version'
4
5
 
5
- Gem::Specification.new do |s|
6
- s.name = 'structure'
7
- s.version = Structure::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ['Hakan Ensari']
10
- s.email = ['code@papercavalier.com']
11
- s.homepage = 'http://github.com/hakanensari/structure'
12
- s.summary = 'A key/value container'
13
- s.description = 'Structure is a key/value container.'
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'structure'
8
+ spec.version = Structure::VERSION
9
+ spec.authors = ['Hakan Ensari']
10
+ spec.email = ['hakan.ensari@papercavalier.com']
11
+ spec.description = 'Value objects in Ruby'
12
+ spec.summary = 'Value objects in Ruby'
13
+ spec.homepage = 'http://github.com/hakanensari/structure'
14
+ spec.license = 'MIT'
14
15
 
15
- s.rubyforge_project = 'structure'
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
16
20
 
17
- s.files = `git ls-files`.split("\n")
18
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
- s.require_paths = ['lib']
21
+ spec.add_development_dependency 'minitest'
22
+ spec.add_development_dependency 'rake'
21
23
  end
@@ -1,161 +1,51 @@
1
- require File.expand_path('../helper.rb', __FILE__)
1
+ require 'minitest/autorun'
2
+ require 'structure'
2
3
 
3
- # Most tests below are borrowed from RubySpec.
4
- class TestStructure < MiniTest::Unit::TestCase
5
- def setup
6
- @person = Structure.new(:name => 'John')
7
- end
8
-
9
- def test_delete_field
10
- @person.delete_field(:name)
11
- assert_nil @person.send(:table)[:name]
12
- refute_respond_to(@person, :name)
13
- refute_respond_to(@person, :name=)
14
- end
15
-
16
- def test_element_reference
17
- assert_raises(NoMethodError) { @person[1] }
18
- end
19
-
20
- def test_element_set
21
- assert_raises(NoMethodError) { @person[1] = 2 }
22
- end
23
-
24
- def test_equal_value
25
- refute @person == 'foo'
26
- assert @person == @person
27
- assert @person == Structure.new(:name => 'John')
28
- assert @person == Class.new(Structure).new(:name => 'John')
29
- refute @person == Structure.new(:name => 'Johnny')
30
- refute @person == Structure.new(:name => 'John', :age => 20)
31
- end
32
-
33
- def test_frozen
34
- @person.freeze
35
-
36
- assert_equal 'John', @person.name
37
- assert_raises(RuntimeError) { @person.age = 42 }
38
- assert_raises(RuntimeError) { @person.state = :new }
39
-
40
- c = @person.clone
41
- assert_equal 'John', c.name
42
- assert_raises(RuntimeError) { c.age = 42 }
43
- assert_raises(RuntimeError) { c.state = :new }
4
+ class Location
5
+ include Structure
44
6
 
45
- d = @person.dup
46
- assert_equal 'John', d.name
47
- d.age = 42
48
- assert_equal 42, d.age
49
- end
50
-
51
- def test_initialize_copy
52
- d = @person.dup
53
- d.name = 'Jane'
54
- assert_equal 'Jane', d.name
55
- assert_equal 'John', @person.name
7
+ attr :res
56
8
 
57
- @person.friends = ['Joe']
58
- d = @person.dup
59
- d.friends = ['Jim']
60
- assert_equal ['Jim'], d.friends
61
- assert_equal ['Joe'], @person.friends
9
+ def initialize(res)
10
+ @res = res
62
11
  end
63
12
 
64
- def test_json
65
- friend = Structure.new(:name => 'Jane')
66
- @person.friend = friend
67
- @person.cities = ['Zurich']
68
- json = '{"json_class":"Structure",
69
- "name":"John",
70
- "friend":{"name":"Jane"},
71
- "cities":["Zurich"]}'.gsub(/\s+/, '')
72
- assert_equal @person, JSON.parse(json)
73
- assert_equal friend, JSON.parse(json).friend
74
- assert_equal 'Zurich', JSON.parse(json).cities.first
75
-
76
- refute_respond_to @person, :as_json
77
- require 'active_support/ordered_hash'
78
- require 'active_support/json'
79
- load 'structure.rb'
80
- assert @person.as_json(:only => :name).has_key?(:name)
81
- refute @person.as_json(:except => :name).has_key?(:name)
13
+ value :latitude do
14
+ res.fetch(:lat)
82
15
  end
83
16
 
84
- def test_marshaling
85
- assert_equal({ :name => 'John' }, @person.marshal_dump)
86
- @person.marshal_load(:age => 20, :name => 'Jane')
87
- assert_equal 20, @person.age
88
- assert_equal 'Jane', @person.name
17
+ value :longitude do
18
+ res.fetch(:lng)
89
19
  end
20
+ end
90
21
 
91
- def test_method_missing
92
- @person.test = 'test'
93
- assert_respond_to @person, :test
94
- assert_respond_to @person, :test=
95
- assert_equal 'test', @person.test
96
- assert_equal 'test', @person.send(:table)[:test]
97
- @person.test = 'changed'
98
- assert_equal 'changed', @person.test
99
-
100
-
101
- @person.send(:table)[:age] = 20
102
- assert_equal 20, @person.age
103
-
104
- assert_raises(NoMethodError) { @person.gender(1) }
105
- assert_nil @person.gender
106
-
107
- @person.freeze
108
- assert_raises(RuntimeError) { @person.gender = 'male' }
22
+ class StructureTest < MiniTest::Test
23
+ def setup
24
+ @location = Location.new(lat: 10, lng: 100)
109
25
  end
110
26
 
111
- def test_new
112
- person = Structure.new(:name => 'John', :age => 70)
113
- assert_equal 'John', person.name
114
- assert_equal 70, person.age
115
- assert_equal({}, Structure.new.send(:table))
27
+ def test_has_value
28
+ assert_equal 10, @location.latitude
29
+ assert_equal 100, @location.longitude
116
30
  end
117
31
 
118
- def test_new_field
119
- @person.send(:table)[:age] = 20
120
- @person.send(:new_field, :age)
121
-
122
- assert_equal 20, @person.age
123
-
124
- @person.age = 30
125
- assert_equal 30, @person.age
126
-
127
- @person.instance_eval { def gender; 'male'; end }
128
- @person.send(:new_field, :gender)
129
- assert_equal 'male', @person.gender
130
- refute_respond_to @person, :gender=
32
+ def test_class_returns_value_names
33
+ assert_equal [:latitude, :longitude], Location.value_names
131
34
  end
132
35
 
133
- def test_recursive_assignment
134
- friend = { :name => 'Jane' }
135
- @person.friend = friend
136
- @person.friends = [friend]
137
- assert_equal 'Jane', @person.friend.name
138
- assert_equal 'Jane', @person.friends.first.name
36
+ def test_returns_values
37
+ assert_equal({ latitude: 10, longitude: 100 }, @location.values)
38
+ assert_equal @location.to_h, @location.values
139
39
  end
140
40
 
141
- def test_recursive_marshaling
142
- hsh = {
143
- :name => 'John',
144
- :friend => { :name => 'Jane' },
145
- :friends => [{ :name => 'Jane' }]
146
- }
147
- friend = Structure.new(:name => 'Jane')
148
- @person.friend = friend
149
- @person.friends = [friend]
150
- assert_equal hsh, @person.marshal_dump
151
-
152
- person = Structure.new
153
- person.marshal_load(hsh)
154
- assert_equal friend, person.friend
155
- assert_equal friend, person.friends.first
41
+ def test_compares
42
+ @other = Location.new(lng: 100, lat: 10)
43
+ assert @location == @other
44
+ assert @location.eql?(@other)
156
45
  end
157
46
 
158
- def test_table
159
- assert_equal({ :name => 'John' }, @person.send(:table))
47
+ def test_pretty_inspects
48
+ assert_equal '#<Location latitude=10, longitude=100>', @location.inspect
49
+ assert_equal @location.to_s, @location.inspect
160
50
  end
161
51
  end
metadata CHANGED
@@ -1,63 +1,82 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: structure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.0
5
- prerelease:
4
+ version: 0.25.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Hakan Ensari
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-01-16 00:00:00.000000000 Z
13
- dependencies: []
14
- description: Structure is a key/value container.
11
+ date: 2013-08-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Value objects in Ruby
15
42
  email:
16
- - code@papercavalier.com
43
+ - hakan.ensari@papercavalier.com
17
44
  executables: []
18
45
  extensions: []
19
46
  extra_rdoc_files: []
20
47
  files:
21
48
  - .gitignore
22
- - .travis.yml
23
- - .yardopts
24
49
  - Gemfile
25
50
  - LICENSE
26
51
  - README.md
27
52
  - Rakefile
28
53
  - lib/structure.rb
29
- - lib/structure/ext/active_support.rb
30
54
  - lib/structure/version.rb
31
55
  - structure.gemspec
32
- - test/helper.rb
33
56
  - test/structure_test.rb
34
- - test/structure_with_fields_test.rb
35
57
  homepage: http://github.com/hakanensari/structure
36
- licenses: []
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
37
61
  post_install_message:
38
62
  rdoc_options: []
39
63
  require_paths:
40
64
  - lib
41
65
  required_ruby_version: !ruby/object:Gem::Requirement
42
- none: false
43
66
  requirements:
44
- - - ! '>='
67
+ - - '>='
45
68
  - !ruby/object:Gem::Version
46
69
  version: '0'
47
70
  required_rubygems_version: !ruby/object:Gem::Requirement
48
- none: false
49
71
  requirements:
50
- - - ! '>='
72
+ - - '>='
51
73
  - !ruby/object:Gem::Version
52
74
  version: '0'
53
75
  requirements: []
54
- rubyforge_project: structure
55
- rubygems_version: 1.8.11
76
+ rubyforge_project:
77
+ rubygems_version: 2.0.5
56
78
  signing_key:
57
- specification_version: 3
58
- summary: A key/value container
79
+ specification_version: 4
80
+ summary: Value objects in Ruby
59
81
  test_files:
60
- - test/helper.rb
61
82
  - test/structure_test.rb
62
- - test/structure_with_fields_test.rb
63
- has_rdoc:
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- rvm:
2
- - 1.8.7
3
- - 1.9.2
4
- - 1.9.3
5
- - jruby
6
- - rbx
7
- - rbx-2.0
8
- - ree
data/.yardopts DELETED
@@ -1,2 +0,0 @@
1
- --no-private
2
- lib/**/*.rb
@@ -1,23 +0,0 @@
1
- class Structure
2
- # @private
3
- module Ext
4
- module ActiveSupport
5
- def as_json(options = nil)
6
- subset = if options
7
- if only = options[:only]
8
- marshal_dump.slice(*Array.wrap(only))
9
- elsif except = options[:except]
10
- marshal_dump.except(*Array.wrap(except))
11
- else
12
- marshal_dump
13
- end
14
- else
15
- marshal_dump
16
- end
17
-
18
- { JSON.create_id => self.class.name }.
19
- merge(subset)
20
- end
21
- end
22
- end
23
- end
data/test/helper.rb DELETED
@@ -1,8 +0,0 @@
1
- require 'minitest/autorun'
2
-
3
- begin
4
- require 'pry'
5
- rescue LoadError
6
- end
7
-
8
- require 'structure'
@@ -1,80 +0,0 @@
1
- require File.expand_path('../helper.rb', __FILE__)
2
-
3
- class Product < Structure
4
- field :title
5
- field :sku, lambda(&:upcase)
6
- field :cents, Integer
7
- field :currency, String, :default => 'USD'
8
- key :in_stock, :default => true
9
- field :created_on, :default => lambda { Date.today }
10
- many :related
11
- one :manufacturer
12
- end
13
-
14
- class Foo < Structure
15
- field :bar, Hash
16
- end
17
-
18
- class TestStructureWithFields < MiniTest::Unit::TestCase
19
- def setup
20
- @product = Product.new(:title => 'Widget')
21
- end
22
-
23
- def test_inheritance
24
- assert_equal 'USD', Class.new(Product).new.currency
25
- end
26
-
27
- def test_equal_value
28
- assert @product == Class.new(Product).new(:title => 'Widget')
29
- refute @product == Product.new(:title => 'Widget', :sku => '123')
30
- end
31
-
32
- def test_casting
33
- @product.title = 1
34
- assert_kind_of Integer, @product.title
35
-
36
- @product.sku = 'sku-123'
37
- assert_equal 'SKU-123', @product.sku
38
-
39
- @product.cents = '1'
40
- assert_kind_of Integer, @product.cents
41
-
42
- @product.related = '1'
43
- assert_kind_of Array, @product.related
44
- end
45
-
46
- def test_default_values
47
- assert_equal nil, @product.cents
48
- assert_equal 'USD', @product.currency
49
- assert_equal true, @product.in_stock
50
- assert_equal [], @product.related
51
- assert_kind_of Date, @product.created_on
52
- end
53
-
54
- def test_recursive_hashes
55
- foo = Foo.new('bar' => { 'baz' => 1 })
56
- hsh = foo.marshal_dump
57
- foo.marshal_load(hsh)
58
- assert_equal({ 'baz' => 1 }, foo.bar)
59
-
60
- json = foo.to_json
61
- assert foo, JSON.parse(json)
62
- end
63
-
64
- def test_recursive_array_handling
65
- related = Product.new
66
- @product.related << related
67
- assert_equal [related], @product.related
68
- assert_equal [], @product.related.first.related
69
- end
70
-
71
- def test_one_to_one
72
- hsh = { :name => 'Manufacturer' }
73
-
74
- @product.manufacturer = Structure.new(hsh)
75
- assert_equal 'Manufacturer', @product.manufacturer.name
76
-
77
- @product.manufacturer = hsh
78
- assert_equal 'Manufacturer', @product.manufacturer.name
79
- end
80
- end