structural 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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