structure 0.24.0 → 0.25.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.
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