obvious 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bf4de686eee48c524a3037620e21a154db8c75fce3ff8db780afc25dc376202
4
- data.tar.gz: c4930e55f1420a9b40996fc042052f267548b3f6017055ad69355c44bad28f7e
3
+ metadata.gz: 9a0c1346518213e685185d08916b2c573697ca5d6be5763f8cfe245febeac4f0
4
+ data.tar.gz: 2125df9f05284d2e34b16edb85ee14f73d1d1f2a296df90c7a2b4e2a795ab81f
5
5
  SHA512:
6
- metadata.gz: 377a83eba55eeadeb63bdadd1a12f72a81507b5d029486add3ffba65fd81c4de929936e435bc73ac0816185bab6dff2a0aa1b4ecfcf527fa36d4dbdc13abaf81
7
- data.tar.gz: 6f7a51c4037baa95be253c62a801f1c8204e662b089bc45bd7f6db1df94f6c39d1130625fb745a7c558111662c5baeaf59372817a077f17d14faf7af2ce0b394
6
+ metadata.gz: 1f8684fe2bc370eb3d2cec4933e3281a00b0633a5829cdee580b36632d330e6b71ba605612bd1ef5f5cfa6884ed66369a50117f68d3b1a9a9ec73a0c3e5bdfda
7
+ data.tar.gz: f393f71805593ff5b748477ebe9486148c356fdb73b1fb09f108453611ceabf4cce982768914c10de719012b0782659bf57ab4e91357871173551d60fb4503ff
@@ -16,4 +16,4 @@ jobs:
16
16
  ruby-version: ${{ matrix.ruby }}
17
17
  bundler-cache: true
18
18
  - run: |
19
- bundle exec rspec
19
+ ruby -Ilib:test test/*_test.rb
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.2.0]
6
+
7
+ ### Added
8
+
9
+ ### Changed
10
+
11
+ - Updated README to be current
12
+ - Removed generators from Obvious
13
+ - Refactored Obvious::Obj#define to be simpler
14
+ - Replaced RSPec with Minitest for testing
15
+
16
+ ### Fixed
17
+
18
+ - Fixed namespace issues with Contract errors
19
+ - Updated project URL on Rubygems listing
data/Gemfile.lock CHANGED
@@ -1,25 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- obvious (0.1.0)
4
+ obvious (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- diff-lcs (1.5.0)
10
- rspec (3.10.0)
11
- rspec-core (~> 3.10.0)
12
- rspec-expectations (~> 3.10.0)
13
- rspec-mocks (~> 3.10.0)
14
- rspec-core (3.10.1)
15
- rspec-support (~> 3.10.0)
16
- rspec-expectations (3.10.1)
17
- diff-lcs (>= 1.2.0, < 2.0)
18
- rspec-support (~> 3.10.0)
19
- rspec-mocks (3.10.2)
20
- diff-lcs (>= 1.2.0, < 2.0)
21
- rspec-support (~> 3.10.0)
22
- rspec-support (3.10.3)
23
9
 
24
10
  PLATFORMS
25
11
  ruby
@@ -28,7 +14,6 @@ PLATFORMS
28
14
 
29
15
  DEPENDENCIES
30
16
  obvious!
31
- rspec
32
17
 
33
18
  BUNDLED WITH
34
19
  2.3.4
data/README.md CHANGED
@@ -1,20 +1,9 @@
1
1
  # Obvious
2
2
 
3
- Obvious is an architecture framework. The goal is to provide architectural structure for a highly testable system that is
4
- obvious to understand and where both the front end UI and back end infrastructure are treated as implementation details
5
- independent of the app logic itself.
6
-
7
- You can get a full explanation of Obvious at http://obvious.retromocha.com
8
-
9
-
10
- # Notice:
11
-
12
- This project is no longer under active development is only made available for historical purposes.
13
-
14
- Right now [Brian is working on a little of this](http://brianknapp.me/now/) and [Shawn is working on a little of that](http://shawnbaden.com/now/).
15
-
16
- Most of our spare energy goes to the [Unbranded Pocket Notebook](https://www.amazon.com/dp/B00ZGE1914/) and the [Unbranded Pocket Journal](https://www.amazon.com/dp/B016LB2XYW).
17
-
3
+ Obvious is an architecture framework. The goal is to provide architectural
4
+ structure for a highly testable system that is obvious to understand and where
5
+ both the front end UI and back end infrastructure are treated as implementation
6
+ details independent of the app logic itself.
18
7
 
19
8
  ## Installation
20
9
 
@@ -25,23 +14,3 @@ Add this line to your application's Gemfile:
25
14
  And then execute:
26
15
 
27
16
  $ bundle
28
-
29
- Or install it yourself as:
30
-
31
- $ gem install obvious
32
-
33
- ## Usage
34
-
35
- Obvious is designed to be used in two ways - as a gem you require in your Obvious projects and also as an Obvious project
36
- generation tool.
37
-
38
- The project generation tool is run by executing...
39
-
40
- $ obvious generate
41
-
42
- in a directory containing a decriptors directory. You can read more about descriptors on the Obvious page or see an example
43
- in the Obvious Status example app: https://github.com/RetroMocha/obvious_status.
44
-
45
- Currently the footprint of the Obvious library is quite small. The most important things defined so far are the Contract class
46
- and the Hash.has_shape? method. The rest of what makes an Obvious app interesting is the structure itself, not the libraries Obvious
47
- provides.
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+ task :default => :test
@@ -94,8 +94,8 @@ module Obvious
94
94
  def call_method method, input, input_shape, output_shape
95
95
  if input != nil && input_shape != nil
96
96
  has_shape, error_field = input.has_shape? input_shape, true
97
- unless has_shape
98
- raise ContractInputError, "incorrect input data format field #{error_field}"
97
+ unless has_shape
98
+ raise Obvious::ContractInputError, "incorrect input data format field #{error_field}"
99
99
  end
100
100
 
101
101
  result = self.send method, input
@@ -106,11 +106,11 @@ module Obvious
106
106
  # check output
107
107
  # output should never be nil
108
108
  if result == nil
109
- raise ContractOutputError, 'incorrect output data format'
109
+ raise Obvious::ContractOutputError, 'incorrect output data format'
110
110
  end
111
111
 
112
112
  if result === {}
113
- raise DataNotFoundError, 'data was not found'
113
+ raise Obvious::DataNotFoundError, 'data was not found'
114
114
  end
115
115
 
116
116
  # we are looking for result to be a True object
@@ -118,7 +118,7 @@ module Obvious
118
118
  if output_shape == result
119
119
  return result
120
120
  else
121
- raise ContractOutputError, 'incorrect output data format'
121
+ raise Obvious::ContractOutputError, 'incorrect output data format'
122
122
  end
123
123
  end
124
124
 
@@ -128,20 +128,20 @@ module Obvious
128
128
  inner_shape = output_shape[0]
129
129
  result.each do |item|
130
130
  has_shape, error_field = item.has_shape? inner_shape, true
131
- unless has_shape
132
- raise ContractOutputError, "incorrect output data format field #{error_field}"
131
+ unless has_shape
132
+ raise Obvious::ContractOutputError, "incorrect output data format field #{error_field}"
133
133
  end
134
134
  end
135
135
 
136
136
  return result
137
137
  end
138
- raise ContractOutputError, 'incorrect output data format'
138
+ raise Obvious::ContractOutputError, 'incorrect output data format'
139
139
  end
140
140
 
141
141
  # we want result to be true or false
142
142
  if output_shape == :true_false
143
143
  unless result == true || result == false
144
- raise ContractOutputError, 'incorrect output data format'
144
+ raise Obvious::ContractOutputError, 'incorrect output data format'
145
145
  end
146
146
 
147
147
  return result
@@ -149,8 +149,8 @@ module Obvious
149
149
 
150
150
  # we want result to be output_shape's shape
151
151
  has_shape, error_field = result.has_shape? output_shape, true
152
- unless has_shape
153
- raise ContractOutputError, "incorrect output data format field #{error_field}"
152
+ unless has_shape
153
+ raise Obvious::ContractOutputError, "incorrect output data format field #{error_field}"
154
154
  end
155
155
 
156
156
  result
@@ -158,6 +158,15 @@ module Obvious
158
158
 
159
159
  end
160
160
 
161
+
162
+ class ContractInputError < StandardError
163
+ end
164
+
165
+ class ContractOutputError < StandardError
166
+ end
167
+
168
+ class DataNotFoundError < StandardError
169
+ end
161
170
  end
162
171
 
163
172
  # via https://github.com/citizen428/shenanigans/blob/master/lib/shenanigans/hash/has_shape_pred.rb
@@ -178,28 +187,28 @@ class Hash
178
187
  if return_field
179
188
  return r, f
180
189
  else
181
- return r
190
+ return r
182
191
  end
183
192
  }
184
-
193
+
185
194
  # I added an empty check
186
195
  if self.empty?
187
196
  return return_value.call shape.empty?, nil
188
- end
189
-
197
+ end
198
+
190
199
  self.each do |k, v|
191
200
  return return_value.call false, k if shape[k] == nil
192
- end
201
+ end
193
202
 
194
203
  shape.each do |k, v|
195
204
  # hash_value
196
205
  hv = self[k]
197
- return return_value.call false, k unless self.has_key? k
206
+ return return_value.call false, k unless self.has_key? k
198
207
 
199
208
  next if hv === nil
200
209
 
201
- if Hash === hv
202
- return hv.has_shape?(v, return_field)
210
+ if Hash === hv
211
+ return hv.has_shape?(v, return_field)
203
212
  else
204
213
  return return_value.call false, k unless v === hv
205
214
  end
@@ -211,18 +220,8 @@ class Hash
211
220
  def nil_fields? list
212
221
  list.each do |field|
213
222
  return true, field unless self[field]
214
- end
215
-
223
+ end
224
+
216
225
  return false, nil
217
226
  end
218
227
  end
219
-
220
- class ContractInputError < StandardError
221
- end
222
-
223
- class ContractOutputError < StandardError
224
- end
225
-
226
- class DataNotFoundError < StandardError
227
- end
228
-
data/lib/obvious/obj.rb CHANGED
@@ -5,31 +5,29 @@ module Obvious
5
5
  base.extend ClassMethods
6
6
  end
7
7
  end
8
-
8
+
9
9
  module ClassMethods
10
10
 
11
- def define method, input = {}, &block
12
- define_method(method) do |method_input = {}|
11
+ def define method, input = {}, &block
12
+ define_method(method) do |method_input = {}|
13
13
  block_input = {}
14
- method_input.each do |k,v|
15
- if input[k].nil?
14
+ method_input.each do |k,v|
15
+ if input[k].nil?
16
16
  raise ArgumentError.new "invalid input field #{k}"
17
- end
18
-
19
- unless v.is_a? input[k][1]
20
- raise ArgumentError.new "invalid type for #{k} expected #{input[k][1]}"
21
- end
17
+ end
22
18
 
23
- block_input[input[k][0]] = v
19
+ unless v.is_a? input[k]
20
+ raise ArgumentError.new "invalid type for #{k} expected #{input[k]}"
21
+ end
24
22
  end
25
-
23
+
26
24
  input.each do |k,v|
27
- if block_input[v[0]].nil?
25
+ if method_input[k].nil?
28
26
  raise ArgumentError.new "missing input field #{k}"
29
27
  end
30
28
  end
31
29
 
32
- self.instance_exec block_input, &block
30
+ self.instance_exec method_input, &block
33
31
  end
34
32
  end
35
33
 
@@ -1,3 +1,3 @@
1
1
  module Obvious
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/obvious.rb CHANGED
@@ -2,4 +2,3 @@ require 'obvious/version'
2
2
  require 'obvious/contract'
3
3
  require 'obvious/entity'
4
4
  require 'obvious/obj'
5
- require_relative 'generators/application_generator'
data/obvious.gemspec CHANGED
@@ -6,16 +6,14 @@ require 'obvious/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "obvious"
8
8
  gem.version = Obvious::VERSION
9
- gem.authors = ["Brian Knapp"]
10
- gem.email = ["brianknapp@gmail.com"]
9
+ gem.authors = ["Brian Knapp", "Shawn Baden"]
10
+ gem.email = ["brianknapp@gmail.com", "shawnbaden@hotmail.com"]
11
11
  gem.description = "A set of tools to build apps using the Obvious Architecture"
12
12
  gem.summary = "Clean Architecture framework"
13
- gem.homepage = "http://obvious.retromocha.com/"
14
-
13
+ gem.homepage = "https://github.com/RetroMocha/obvious"
14
+ gem.license = "MIT"
15
15
  gem.files = `git ls-files`.split($/)
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
-
20
- gem.add_development_dependency "rspec"
21
19
  end
@@ -0,0 +1,62 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/obvious/contract'
3
+
4
+ class TestContract < Obvious::Contract
5
+ contract_for :test, {
6
+ input: { id: Integer },
7
+ output: { id: Integer, value: String }
8
+ }
9
+
10
+ def test input
11
+ { id: 1, value: 'this is a test' }
12
+ end
13
+ end
14
+
15
+ class ContractTest < Minitest::Test
16
+ def test_valid_input
17
+ result = TestContract.new.test(id: 1)
18
+ assert_equal({id: 1, value: 'this is a test'}, result)
19
+ end
20
+
21
+ def test_invalid_input
22
+ assert_raises Obvious::ContractInputError do
23
+ TestContract.new.test(Hash.new)
24
+ end
25
+ end
26
+
27
+ def test_empty_hash_return
28
+ assert_raises Obvious::DataNotFoundError do
29
+ tc = TestContract.new
30
+ tc.stub :test_alias, {} do
31
+ tc.test(id: 1)
32
+ end
33
+ end
34
+ end
35
+
36
+ def test_nil_return
37
+ assert_raises Obvious::ContractOutputError do
38
+ tc = TestContract.new
39
+ tc.stub :test_alias, nil do
40
+ tc.test(id: 1)
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ class HashTest < Minitest::Test
47
+ def test_valid_has_shape
48
+ assert({id: 1}.has_shape?(id: Integer))
49
+ end
50
+
51
+ def test_invalid_has_shape
52
+ refute({id: 1}.has_shape?(id: String))
53
+ end
54
+
55
+ def test_has_shape_allow_nil_values
56
+ assert({id: nil}.has_shape?({id: String}))
57
+ end
58
+
59
+ def test_has_shape_return_invalid_field
60
+ assert_equal([false, :id], { id: 1 }.has_shape?({id: String}, true))
61
+ end
62
+ end
@@ -0,0 +1,76 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/obvious/entity'
3
+
4
+ class Thing < Obvious::Entity
5
+ value :id, Integer
6
+ value :name, String
7
+ end
8
+
9
+ class Thing2 < Obvious::Entity
10
+ value :foo , String
11
+
12
+ validation :something, -> {
13
+ if foo != "hello world"
14
+ msg = "Validation Error: Invalid value for foo, should be 'hello world'"
15
+ raise Obvious::ValidationError.new msg
16
+ end
17
+ }
18
+
19
+ def modify_foo
20
+ @values[:foo] = 100
21
+ end
22
+ end
23
+
24
+ class Thing3 < Obvious::Entity
25
+ value :foo , String
26
+
27
+ validation :something, -> {
28
+ @values[:foo] = 12
29
+ }
30
+ end
31
+
32
+
33
+ # Test code begins here
34
+
35
+ class EntityTest < Minitest::Test
36
+ def test_valid_input
37
+ t = Thing.new(name: 'Thing', id: 1)
38
+ assert_equal('Thing', t.name)
39
+ assert_equal(1, t.id)
40
+ end
41
+
42
+ def test_invalid_input_types
43
+ assert_raises Obvious::TypeError do
44
+ Thing.new(name: nil, id: nil)
45
+ end
46
+ end
47
+
48
+ def test_invalid_extra_field
49
+ assert_raises Obvious::ShapeError do
50
+ Thing.new(name: 'Thing', id: 1, extra: 'should explode')
51
+ end
52
+ end
53
+
54
+ def test_method_modify_value
55
+ assert_raises RuntimeError do
56
+ Thing2.new(foo: 'hello world').modify_foo
57
+ end
58
+ end
59
+
60
+ def test_to_hash
61
+ t = Thing.new(name: 'Thing', id: 1)
62
+ assert_equal({name: 'Thing', id: 1}, t.to_hash)
63
+ end
64
+
65
+ def test_failed_validation
66
+ assert_raises Obvious::ValidationError do
67
+ Thing2.new(foo: 'not valid I promise!')
68
+ end
69
+ end
70
+
71
+ def test_modify_value_inside_validation
72
+ assert_raises RuntimeError do
73
+ Thing3.new(foo: 'hello world')
74
+ end
75
+ end
76
+ end
data/test/obj_test.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/obvious/obj'
3
+
4
+ class TestObj
5
+ include Obvious::Obj
6
+
7
+ def initialize
8
+ @local = 'set!'
9
+ end
10
+
11
+ define :defined_method, foo: String, bar: Integer do |input|
12
+ input
13
+ end
14
+
15
+ define :defined_local do |input|
16
+ @local
17
+ end
18
+
19
+ define :early_return_example do |input|
20
+ next true
21
+ false
22
+ end
23
+ end
24
+
25
+ class ObjTest < Minitest::Test
26
+ def test_valid_input
27
+ result = TestObj.new.defined_method foo: 'hello', bar: 12
28
+ assert_equal({foo: 'hello', bar: 12}, result)
29
+ end
30
+
31
+ def test_access_instance_variables
32
+ result = TestObj.new.defined_local
33
+ assert_equal('set!', result)
34
+ end
35
+
36
+ def test_missing_parameters
37
+ error = assert_raises ArgumentError do
38
+ TestObj.new.defined_method foo: 'hello'
39
+ end
40
+ assert_equal('missing input field bar', error.message)
41
+ end
42
+
43
+ def test_extra_parameters
44
+ error = assert_raises ArgumentError do
45
+ TestObj.new.defined_method foo: 'hello', bar: 12, extra: 'fail'
46
+ end
47
+ assert_equal('invalid input field extra', error.message)
48
+ end
49
+
50
+ def test_invalid_types
51
+ error = assert_raises ArgumentError do
52
+ TestObj.new.defined_method foo: 1, bar: 12
53
+ end
54
+ assert_equal('invalid type for foo expected String', error.message)
55
+
56
+ error = assert_raises ArgumentError do
57
+ TestObj.new.defined_method foo: 'hello', bar: nil
58
+ end
59
+ assert_equal('invalid type for bar expected Integer', error.message)
60
+ end
61
+
62
+ def test_early_return
63
+ assert(TestObj.new.early_return_example)
64
+ end
65
+ end
metadata CHANGED
@@ -1,67 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obvious
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Knapp
8
+ - Shawn Baden
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2022-01-26 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rspec
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'
12
+ date: 2022-02-02 00:00:00.000000000 Z
13
+ dependencies: []
27
14
  description: A set of tools to build apps using the Obvious Architecture
28
15
  email:
29
16
  - brianknapp@gmail.com
30
- executables:
31
- - obvious
17
+ - shawnbaden@hotmail.com
18
+ executables: []
32
19
  extensions: []
33
20
  extra_rdoc_files: []
34
21
  files:
35
22
  - ".github/workflows/obvious.yml"
36
23
  - ".gitignore"
24
+ - CHANGELOG.md
37
25
  - Gemfile
38
26
  - Gemfile.lock
39
27
  - LICENSE.txt
40
28
  - README.md
41
29
  - Rakefile
42
- - bin/obvious
43
- - lib/generators/application_generator.rb
44
- - lib/generators/descriptor.rb
45
- - lib/generators/helpers/application.rb
46
30
  - lib/obvious.rb
47
31
  - lib/obvious/contract.rb
48
32
  - lib/obvious/entity.rb
49
- - lib/obvious/files/Rakefile
50
- - lib/obvious/files/external/fs_plug.rb
51
- - lib/obvious/files/external/mongo_plug.rb
52
- - lib/obvious/files/external/mysql_plug.rb
53
- - lib/obvious/files/external/s3_plug.rb
54
33
  - lib/obvious/obj.rb
55
34
  - lib/obvious/version.rb
56
35
  - obvious.gemspec
57
- - spec/.spec_helper.rb.swp
58
- - spec/contract_spec.rb
59
- - spec/entity_spec.rb
60
- - spec/generators/descriptor_spec.rb
61
- - spec/obj_spec.rb
62
- - spec/spec_helper.rb
63
- homepage: http://obvious.retromocha.com/
64
- licenses: []
36
+ - test/contract_test.rb
37
+ - test/entity_test.rb
38
+ - test/obj_test.rb
39
+ homepage: https://github.com/RetroMocha/obvious
40
+ licenses:
41
+ - MIT
65
42
  metadata: {}
66
43
  post_install_message:
67
44
  rdoc_options: []
@@ -83,9 +60,6 @@ signing_key:
83
60
  specification_version: 4
84
61
  summary: Clean Architecture framework
85
62
  test_files:
86
- - spec/.spec_helper.rb.swp
87
- - spec/contract_spec.rb
88
- - spec/entity_spec.rb
89
- - spec/generators/descriptor_spec.rb
90
- - spec/obj_spec.rb
91
- - spec/spec_helper.rb
63
+ - test/contract_test.rb
64
+ - test/entity_test.rb
65
+ - test/obj_test.rb
data/bin/obvious DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'obvious'
4
-
5
- if ARGV[0] == 'generate'
6
- Obvious::Generators::ApplicationGenerator.generate
7
- end