structural 0.0.3 → 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d2e683ae4dc0a1839b52352576db3fc726201321
4
+ data.tar.gz: 947df1932b578c7c5e786b2e6baf4463f2d10312
5
+ SHA512:
6
+ metadata.gz: c4da802d16a95c7d4b5516697fb9c6c76687032686e693830c6c3f8b44a3aa47c3f9adb3ca9341ccf378afafb0e75b118ac186ed612d9ab7fa274efefffcd4a7
7
+ data.tar.gz: a1f58451da825b7bc071958150407011f743d2ab4411692095b6197a0a3377a749ca6de810170b1098dfa525457e00ff83e398ece251d3d2d7b1088e9dbc5e26
@@ -1,27 +1,18 @@
1
1
  module Structural
2
2
  class Hashifier
3
3
  def self.hashify(data)
4
- new(data).hashify
4
+ {}.tap do |hash|
5
+ data.each do |key, value|
6
+ hash[key.to_sym] = as_data(value)
7
+ end
8
+ end
5
9
  end
6
10
 
7
- def initialize(data)
8
- @data = data
9
- end
10
-
11
- def hashify
12
- Hash[data.map { |k, v| [ k.to_s, as_data(v) ] }]
13
- end
14
-
15
- private
16
-
17
- def as_data(v)
11
+ def self.as_data(v)
18
12
  case v
19
13
  when Structural::Model then v.data
20
14
  when Array then v.first.is_a?(Structural::Model) ? v.map(&:data) : v
21
- when Hash then Hashifier.hashify(v)
22
15
  else v end
23
16
  end
24
-
25
- attr_reader :data
26
17
  end
27
18
  end
@@ -11,7 +11,7 @@ module Structural
11
11
  end
12
12
 
13
13
  def unset(*keys)
14
- self.class.new(data.except(*keys.map(&:to_s)))
14
+ self.class.new(data.except(*keys.map(&:to_sym)))
15
15
  end
16
16
 
17
17
  def eql? other
@@ -29,8 +29,8 @@ module Structural
29
29
  base.extend(Descriptor)
30
30
  end
31
31
 
32
- def memoize(f, &b)
33
- instance_variable_get("@#{f}") || instance_variable_set("@#{f}", b.call(data))
32
+ def memoize(ivar, &b)
33
+ instance_variable_get(ivar) || instance_variable_set(ivar, b.call(data))
34
34
  end
35
35
  end
36
36
  end
@@ -1,17 +1,17 @@
1
1
  module Structural
2
2
  module Model
3
3
  class Definer
4
- def self.method_memoize(context, name, &value_block)
5
- method(context, name) do |object|
6
- object.instance_eval do
7
- memoize(name, &value_block)
4
+ def self.method_memoize(context, name, ivar_name, &value_block)
5
+ context.class_eval do
6
+ define_method(name) do
7
+ memoize(ivar_name, &value_block)
8
8
  end
9
9
  end
10
10
  end
11
11
 
12
12
  def self.method(context, name, &value_block)
13
- context.instance_eval do
14
- define_method name do
13
+ context.class_eval do
14
+ define_method(name) do
15
15
  value_block.call(self)
16
16
  end
17
17
  end
@@ -8,7 +8,7 @@ module Structural
8
8
  end
9
9
 
10
10
  def define
11
- Definer.method_memoize(model, name) { |data| value_of(data) }
11
+ Definer.method_memoize(model, name, ivar_name) { |data| value_of(data) }
12
12
  Definer.method(model, "#{name}?") { |obj| presence_of(obj.data) }
13
13
  hook_define
14
14
  end
@@ -26,18 +26,22 @@ module Structural
26
26
  end
27
27
 
28
28
  def cast(value)
29
- TypeCasts.cast(options.fetch(:type, false), value)
29
+ TypeCasts.cast(options.fetch(:type, value.class), value)
30
30
  end
31
31
 
32
32
  def key
33
- options.fetch(:key, name).to_s
33
+ options.fetch(:key, name).to_sym
34
+ end
35
+
36
+ def ivar_name
37
+ @ivar_name ||= "@#{@name}"
34
38
  end
35
39
 
36
40
  def default_value
37
- proc do
41
+ @default_value ||= proc do
38
42
  if default?
39
43
  default
40
- else
44
+ else
41
45
  raise MissingAttributeError, key
42
46
  end
43
47
  end
@@ -1,12 +1,15 @@
1
1
  module Structural
2
2
  module Model
3
3
  module TypeCasts
4
+
4
5
  def self.cast(type, value)
5
- casts.fetch(type, Identity).new(value).cast
6
+ if value.is_a?(type)
7
+ value
8
+ else
9
+ casts.fetch(type, Identity).cast(value)
10
+ end
6
11
  end
7
12
 
8
- protected
9
-
10
13
  def self.register(cast)
11
14
  casts[cast.type] = cast
12
15
  end
@@ -17,92 +20,70 @@ module Structural
17
20
  @casts ||= {}
18
21
  end
19
22
 
20
- class Cast
21
- def initialize(value)
22
- @value = value
23
- end
24
-
25
- def cast
26
- value.is_a?(type) ? value : conversion
27
- end
28
-
29
- def type
30
- self.class.type
31
- end
32
-
33
- def conversion
34
- raise NotImplementedError
35
- end
36
-
37
- private
38
-
23
+ class Identity
39
24
  def self.type
40
- raise NotImplementedError
25
+ ::Identity
41
26
  end
42
27
 
43
- attr_reader :value
44
- end
45
-
46
- class Identity < Cast
47
- def cast
28
+ def self.cast(value)
48
29
  value
49
30
  end
50
31
  end
51
32
 
52
- class Integer < Cast
33
+ class Integer
53
34
  def self.type
54
35
  ::Integer
55
36
  end
56
37
 
57
- def conversion
38
+ def self.cast(value)
58
39
  value.to_i
59
40
  end
60
41
 
61
42
  TypeCasts.register(self)
62
43
  end
63
44
 
64
- class Float < Cast
45
+ class Float
65
46
  def self.type
66
47
  ::Float
67
48
  end
68
49
 
69
- def conversion
50
+ def self.cast(value)
70
51
  value.to_f
71
52
  end
72
53
 
73
54
  TypeCasts.register(self)
74
55
  end
75
56
 
76
- class Date < Cast
57
+ class Date
77
58
  def self.type
78
59
  ::Date
79
60
  end
80
61
 
81
- def conversion
62
+ def self.cast(value)
82
63
  ::Date.parse value
83
64
  end
84
65
 
85
66
  TypeCasts.register(self)
86
67
  end
87
68
 
88
- class Time < Cast
69
+ class Time
89
70
  def self.type
90
71
  ::Time
91
72
  end
92
73
 
93
- def conversion
74
+ def self.cast(value)
94
75
  ::Time.parse value
95
76
  end
96
77
 
97
78
  TypeCasts.register(self)
98
79
  end
99
80
 
100
- class Money < Cast
81
+ class Money
101
82
  def self.type
102
83
  ::Money
103
84
  end
104
85
 
105
- def conversion
86
+ def self.cast(value)
106
87
  ::Money.new value.to_i
107
88
  end
108
89
 
@@ -6,7 +6,7 @@ module Structural
6
6
  end
7
7
 
8
8
  def initialize(data = {})
9
- super data.merge(:created_at => data.fetch('created_at', Time.now))
9
+ super data.merge(:created_at => data.fetch(:created_at, Time.now))
10
10
  end
11
11
 
12
12
  def set(values)
@@ -1,3 +1,3 @@
1
1
  module Structural
2
- VERSION = '0.0.3'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -3,19 +3,8 @@ require 'spec_helper'
3
3
  module Structural
4
4
  module Model
5
5
  module TypeCasts
6
- describe Cast do
7
- it 'requires a type' do
8
- expect { Cast.new(1).type }.to raise_error NotImplementedError
9
- end
10
-
11
- it 'requires a conversion' do
12
- expect { Cast.new(1).conversion }.to raise_error NotImplementedError
13
- end
14
-
15
- end
16
-
17
6
  describe Integer do
18
- subject { Integer.new("2").cast }
7
+ subject { Integer.cast("2") }
19
8
 
20
9
  it 'casts strings to integers' do
21
10
  expect(subject).to eql(2)
@@ -23,7 +12,7 @@ module Structural
23
12
  end
24
13
 
25
14
  describe Float do
26
- subject { Float.new("2.0").cast }
15
+ subject { Float.cast("2.0") }
27
16
 
28
17
  it 'casts strings to floats' do
29
18
  expect(subject).to eql(2.0)
@@ -32,25 +21,20 @@ module Structural
32
21
 
33
22
  describe Date do
34
23
  it 'casts strings to dates' do
35
- Date.new("06-06-1983").cast.should eq ::Date.new(1983, 6, 6)
24
+ Date.cast("06-06-1983").should eq ::Date.new(1983, 6, 6)
36
25
  end
37
26
  end
38
27
 
39
28
  describe Time do
40
29
  it 'casts strings to Times' do
41
- Time.new("06-06-1983").cast.should eq ::Time.parse("06-06-1983")
42
- end
43
-
44
- it 'does nothing if the value is already of the correct type' do
45
- time = ::Time.now
46
- Time.new(time).cast.should eq time
30
+ Time.cast("06-06-1983").should eq ::Time.parse("06-06-1983")
47
31
  end
48
32
  end
49
33
 
50
34
  describe Money do
51
35
  it 'ints or strings to Money' do
52
- Money.new("500").cast.should eq ::Money.new(5_00)
53
- Money.new(500).cast.should eq ::Money.new(5_00)
36
+ Money.cast("500").should eq ::Money.new(5_00)
37
+ Money.cast(500).should eq ::Money.new(5_00)
54
38
  end
55
39
  end
56
40
  end
@@ -10,6 +10,7 @@ class TestModel
10
10
 
11
11
  field :foo
12
12
  field :bar, :key => 'baz'
13
+ field :nested_hash
13
14
  field :quux, :default => false
14
15
  field :date_of_birth, :type => Date
15
16
  field :empty_date, :type => Date
@@ -33,6 +34,7 @@ describe Structural::Model do
33
34
  :foo => 3,
34
35
  :baz => 6,
35
36
  :quxx => 8,
37
+ :nested_hash => {1 => :one, 2 => :two},
36
38
  :test_model => {},
37
39
  :date_of_birth => '06-06-1983',
38
40
  :aliased_model => {'yak' => 11},
@@ -62,6 +64,10 @@ describe Structural::Model do
62
64
  model.quux.should eql(false)
63
65
  end
64
66
 
67
+ it 'leaves nested hashes unmodified' do
68
+ model.nested_hash.should eql({1 => :one, 2 => :two})
69
+ end
70
+
65
71
  describe "typecast option" do
66
72
  it 'typecasts to the provided type if a cast exists' do
67
73
  model.date_of_birth.should be_a Date
metadata CHANGED
@@ -1,138 +1,125 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: structural
3
- version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 3
10
- version: 0.0.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Russell Dunphy
14
8
  - Radek Molenda
15
9
  - Jon Doveston
16
10
  autorequire:
17
11
  bindir: bin
18
12
  cert_chain: []
19
-
20
- date: 2014-11-11 00:00:00 +00:00
21
- default_executable:
22
- dependencies:
23
- - !ruby/object:Gem::Dependency
13
+ date: 2016-11-07 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
24
16
  name: money
25
- prerelease: false
26
- requirement: &id001 !ruby/object:Gem::Requirement
27
- none: false
28
- requirements:
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
29
19
  - - ">="
30
- - !ruby/object:Gem::Version
31
- hash: 3
32
- segments:
33
- - 0
34
- version: "0"
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
35
22
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: activesupport
39
23
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: activesupport
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
43
33
  - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 3
46
- segments:
47
- - 0
48
- version: "0"
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
49
36
  type: :runtime
50
- version_requirements: *id002
51
- - !ruby/object:Gem::Dependency
52
- name: rspec
53
37
  prerelease: false
54
- requirement: &id003 !ruby/object:Gem::Requirement
55
- none: false
56
- requirements:
57
- - - ~>
58
- - !ruby/object:Gem::Version
59
- hash: 7
60
- segments:
61
- - 3
62
- - 0
63
- version: "3.0"
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.0'
64
50
  type: :development
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: yard
68
51
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
70
- none: false
71
- requirements:
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '3.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: yard
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
72
61
  - - ">="
73
- - !ruby/object:Gem::Version
74
- hash: 3
75
- segments:
76
- - 0
77
- version: "0"
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
78
64
  type: :development
79
- version_requirements: *id004
80
- - !ruby/object:Gem::Dependency
81
- name: redcarpet
82
65
  prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: redcarpet
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
86
75
  - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
92
78
  type: :development
93
- version_requirements: *id005
94
- - !ruby/object:Gem::Dependency
95
- name: bundler
96
79
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
98
- none: false
99
- requirements:
100
- - - ~>
101
- - !ruby/object:Gem::Version
102
- hash: 3
103
- segments:
104
- - 1
105
- - 6
106
- version: "1.6"
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: bundler
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '1.6'
107
92
  type: :development
108
- version_requirements: *id006
109
- - !ruby/object:Gem::Dependency
110
- name: rake
111
93
  prerelease: false
112
- requirement: &id007 !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '1.6'
99
+ - !ruby/object:Gem::Dependency
100
+ name: rake
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
115
103
  - - ">="
116
- - !ruby/object:Gem::Version
117
- hash: 3
118
- segments:
119
- - 0
120
- version: "0"
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
121
106
  type: :development
122
- version_requirements: *id007
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
123
113
  description: A cut down fork of the Id gem developed at On The Beach Ltd.
124
- email:
114
+ email:
125
115
  - jon.doveston@onthebeach.co.uk
126
116
  executables: []
127
-
128
117
  extensions: []
129
-
130
118
  extra_rdoc_files: []
131
-
132
- files:
133
- - .gitignore
134
- - .ruby-version
135
- - .travis.yml
119
+ files:
120
+ - ".gitignore"
121
+ - ".ruby-version"
122
+ - ".travis.yml"
136
123
  - CONTRIBUTING.md
137
124
  - Gemfile
138
125
  - LICENSE.md
@@ -158,41 +145,31 @@ files:
158
145
  - spec/lib/structural/timestamps_spec.rb
159
146
  - spec/spec_helper.rb
160
147
  - structural.gemspec
161
- has_rdoc: true
162
148
  homepage: https://github.com/onthebeach/structural
163
- licenses:
149
+ licenses:
164
150
  - MIT
151
+ metadata: {}
165
152
  post_install_message:
166
153
  rdoc_options: []
167
-
168
- require_paths:
154
+ require_paths:
169
155
  - lib
170
- required_ruby_version: !ruby/object:Gem::Requirement
171
- none: false
172
- requirements:
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
173
158
  - - ">="
174
- - !ruby/object:Gem::Version
175
- hash: 3
176
- segments:
177
- - 0
178
- version: "0"
179
- required_rubygems_version: !ruby/object:Gem::Requirement
180
- none: false
181
- requirements:
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
182
163
  - - ">="
183
- - !ruby/object:Gem::Version
184
- hash: 3
185
- segments:
186
- - 0
187
- version: "0"
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
188
166
  requirements: []
189
-
190
167
  rubyforge_project:
191
- rubygems_version: 1.3.7
168
+ rubygems_version: 2.5.1
192
169
  signing_key:
193
- specification_version: 3
170
+ specification_version: 4
194
171
  summary: Simple models based on hashes
195
- test_files:
172
+ test_files:
196
173
  - spec/lib/structural/model/association_spec.rb
197
174
  - spec/lib/structural/model/field_spec.rb
198
175
  - spec/lib/structural/model/type_casts_spec.rb