obvious 0.0.2 → 0.0.3
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.
- data/README.md +18 -2
- data/bin/obvious +287 -0
- data/lib/obvious/contract.rb +42 -22
- data/lib/obvious/version.rb +1 -1
- data/lib/obvious.rb +0 -282
- metadata +3 -4
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# Obvious
|
2
2
|
|
3
|
-
|
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
|
4
8
|
|
5
9
|
## Installation
|
6
10
|
|
@@ -18,7 +22,19 @@ Or install it yourself as:
|
|
18
22
|
|
19
23
|
## Usage
|
20
24
|
|
21
|
-
|
25
|
+
Obvious is designed to be used in two ways - as a gem you require in your Obvious projects and also as an Obvious project
|
26
|
+
generation tool.
|
27
|
+
|
28
|
+
The project generation tool is run by executing...
|
29
|
+
|
30
|
+
$ obvious generate
|
31
|
+
|
32
|
+
in a directory containing a decriptors directory. You can read more about descriptors on the Obvious page or see an example
|
33
|
+
in the Obvious Status example app: https://github.com/RetroMocha/obvious_status.
|
34
|
+
|
35
|
+
Currently the footprint of the Obvious library is quite small. The most important things defined so far are the Contract class
|
36
|
+
and the Hash.has_shape? method. The rest of what makes an Obvious app interesting is the structure itself, not the libraries Obvious
|
37
|
+
provides.
|
22
38
|
|
23
39
|
## Contributing
|
24
40
|
|
data/bin/obvious
CHANGED
@@ -2,6 +2,293 @@
|
|
2
2
|
|
3
3
|
require 'obvious'
|
4
4
|
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module Obvious
|
8
|
+
# Your code goes here...
|
9
|
+
def self.generate
|
10
|
+
puts 'generate the codes!a'
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
#`rm -rf app`
|
15
|
+
|
16
|
+
app_dir = 'app'
|
17
|
+
|
18
|
+
counter = 1
|
19
|
+
while File.directory? app_dir
|
20
|
+
app_dir = "app_#{counter}"
|
21
|
+
counter += 1
|
22
|
+
end
|
23
|
+
|
24
|
+
puts "Generating application at: #{app_dir}"
|
25
|
+
|
26
|
+
dirs = ['/', '/actions', '/contracts', '/entities',
|
27
|
+
'/spec', '/spec/actions', '/spec/contracts', '/spec/entities',
|
28
|
+
'/spec/doubles']
|
29
|
+
|
30
|
+
dirs.each do |dir|
|
31
|
+
Dir.mkdir app_dir + dir
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
target_path = File.realpath Dir.pwd
|
36
|
+
spec = Gem::Specification.find_by_name("obvious")
|
37
|
+
gem_root = spec.gem_dir
|
38
|
+
gem_lib = gem_root + "/lib"
|
39
|
+
|
40
|
+
#`cp #{gem_lib}/obvious/files/contract.rb #{target_path}/app/contracts/contract.rb`
|
41
|
+
`cp #{gem_lib}/obvious/files/Rakefile #{target_path}/Rakefile`
|
42
|
+
entities = Hash.new
|
43
|
+
jacks = Hash.new
|
44
|
+
|
45
|
+
files = Dir['descriptors/*.yml']
|
46
|
+
|
47
|
+
files.each do |file|
|
48
|
+
action = YAML.load_file file
|
49
|
+
code = ''
|
50
|
+
#puts action.inspect
|
51
|
+
|
52
|
+
local_jacks = Hash.new
|
53
|
+
local_entities = Hash.new
|
54
|
+
|
55
|
+
action['Code'].each do |entry|
|
56
|
+
code << " \# #{entry['c']}\n"
|
57
|
+
code << " \# use: #{entry['requires']}\n" if entry['requires']
|
58
|
+
code << " \n"
|
59
|
+
|
60
|
+
if entry['requires']
|
61
|
+
requires = entry['requires'].split(',')
|
62
|
+
requires.each do |req|
|
63
|
+
req.strip!
|
64
|
+
info = req.split '.'
|
65
|
+
|
66
|
+
if info[0].index 'Jack'
|
67
|
+
unless jacks[info[0]]
|
68
|
+
jacks[info[0]] = []
|
69
|
+
end
|
70
|
+
|
71
|
+
unless local_jacks[info[0]]
|
72
|
+
local_jacks[info[0]] = []
|
73
|
+
end
|
74
|
+
|
75
|
+
jacks[info[0]] << info[1]
|
76
|
+
local_jacks[info[0]] << info[1]
|
77
|
+
else
|
78
|
+
unless entities[info[0]]
|
79
|
+
entities[info[0]] = []
|
80
|
+
end
|
81
|
+
|
82
|
+
unless local_entities[info[0]]
|
83
|
+
local_entities[info[0]] = []
|
84
|
+
end
|
85
|
+
|
86
|
+
entities[info[0]] << info[1]
|
87
|
+
local_entities[info[0]] << info[1]
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
jack_inputs = ''
|
97
|
+
jack_assignments = ''
|
98
|
+
|
99
|
+
local_jacks.each do |k, v|
|
100
|
+
name = k.chomp('Jack').downcase
|
101
|
+
jack_inputs << "#{name}_jack, "
|
102
|
+
jack_assignments << " @#{name}_jack = #{name}_jack\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
jack_inputs.chomp! ', '
|
106
|
+
|
107
|
+
entity_requires = ''
|
108
|
+
|
109
|
+
local_entities.each do |k, v|
|
110
|
+
name = k.downcase
|
111
|
+
entity_requires << "require_relative '../entities/#{name}'\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
output = <<FIN
|
116
|
+
#{entity_requires}
|
117
|
+
class #{action['Action']}
|
118
|
+
|
119
|
+
def initialize #{jack_inputs}
|
120
|
+
#{jack_assignments} end
|
121
|
+
|
122
|
+
def do input
|
123
|
+
#{code} end
|
124
|
+
|
125
|
+
end
|
126
|
+
FIN
|
127
|
+
snake_name = action['Action'].gsub(/(.)([A-Z])/,'\1_\2').downcase
|
128
|
+
|
129
|
+
filename = "#{app_dir}/actions/#{snake_name}.rb"
|
130
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
131
|
+
|
132
|
+
#puts output
|
133
|
+
|
134
|
+
output = <<FIN
|
135
|
+
require_relative '../../actions/#{snake_name}'
|
136
|
+
|
137
|
+
describe #{action['Action']} do
|
138
|
+
|
139
|
+
it '#{action['Description']}'
|
140
|
+
|
141
|
+
it 'should raise an error with invalid input'
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
FIN
|
147
|
+
|
148
|
+
filename = "#{app_dir}/spec/actions/#{snake_name}_spec.rb"
|
149
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
150
|
+
|
151
|
+
#puts output
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
#filter out duplicate methods
|
156
|
+
|
157
|
+
entities.each do |k, v|
|
158
|
+
v.uniq!
|
159
|
+
end
|
160
|
+
|
161
|
+
jacks.each do |k,v|
|
162
|
+
v.uniq!
|
163
|
+
end
|
164
|
+
|
165
|
+
#puts entities.inspect
|
166
|
+
#puts jacks.inspect
|
167
|
+
|
168
|
+
entities.each do |k, v|
|
169
|
+
name = k
|
170
|
+
method_specs = ''
|
171
|
+
method_definitions = ''
|
172
|
+
|
173
|
+
v.each do |method|
|
174
|
+
method_definitions << "
|
175
|
+
def #{method} input
|
176
|
+
nil
|
177
|
+
end
|
178
|
+
"
|
179
|
+
|
180
|
+
method_specs << "
|
181
|
+
describe '.#{method}' do
|
182
|
+
it 'should #{method} with valid input'
|
183
|
+
|
184
|
+
it 'should raise an error with invalid input'
|
185
|
+
|
186
|
+
end
|
187
|
+
"
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
output = <<FIN
|
192
|
+
class #{name}
|
193
|
+
#{method_definitions}
|
194
|
+
end
|
195
|
+
FIN
|
196
|
+
snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
197
|
+
|
198
|
+
filename = "#{app_dir}/entities/#{snake_name}.rb"
|
199
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
200
|
+
|
201
|
+
output = <<FIN
|
202
|
+
require_relative '../../entities/#{snake_name}'
|
203
|
+
|
204
|
+
describe #{name} do
|
205
|
+
#{method_specs}
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
FIN
|
210
|
+
filename = "#{app_dir}/spec/entities/#{snake_name}_spec.rb"
|
211
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
212
|
+
|
213
|
+
|
214
|
+
#puts output
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
jacks.each do |k, v|
|
220
|
+
|
221
|
+
name = k.chomp('Jack').downcase
|
222
|
+
|
223
|
+
method_specs = ''
|
224
|
+
method_definitions = ''
|
225
|
+
|
226
|
+
v.each do |method|
|
227
|
+
|
228
|
+
method_definitions << "
|
229
|
+
def #{method}_contract input
|
230
|
+
input_shape = {}
|
231
|
+
output_shape = {}
|
232
|
+
call_method :#{method}_alias, input, input_shape, output_shape
|
233
|
+
end
|
234
|
+
"
|
235
|
+
|
236
|
+
method_specs << "
|
237
|
+
describe '.#{method}_contract' do
|
238
|
+
it 'should #{method} data with valid input'
|
239
|
+
|
240
|
+
it 'should raise an error with invalid input'
|
241
|
+
|
242
|
+
it 'should raise an error with invalid output'
|
243
|
+
|
244
|
+
end
|
245
|
+
"
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
output = <<FIN
|
251
|
+
require 'obvious'
|
252
|
+
|
253
|
+
class #{k}Contract < Contract
|
254
|
+
contracts :#{v.join(', :')}
|
255
|
+
#{method_definitions}
|
256
|
+
end
|
257
|
+
FIN
|
258
|
+
|
259
|
+
snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
260
|
+
|
261
|
+
filename = "#{app_dir}/contracts/#{snake_name}_jack_contract.rb"
|
262
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
263
|
+
|
264
|
+
#puts output
|
265
|
+
|
266
|
+
output = <<FIN
|
267
|
+
require_relative '../../contracts/#{snake_name}_jack_contract'
|
268
|
+
|
269
|
+
describe #{k}Contract do
|
270
|
+
#{method_specs}
|
271
|
+
end
|
272
|
+
|
273
|
+
FIN
|
274
|
+
|
275
|
+
filename = "#{app_dir}/spec/contracts/#{snake_name}_jack_contract_spec.rb"
|
276
|
+
File.open(filename, 'w') {|f| f.write(output) }
|
277
|
+
|
278
|
+
#puts output
|
279
|
+
end
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
|
5
289
|
if ARGV[0] == 'generate'
|
6
290
|
Obvious::generate
|
7
291
|
end
|
292
|
+
|
293
|
+
|
294
|
+
|
data/lib/obvious/contract.rb
CHANGED
@@ -1,24 +1,42 @@
|
|
1
1
|
class Contract
|
2
2
|
@@disable_override = false
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
def self.
|
4
|
+
# Provides a default empty array for method_added
|
5
|
+
# Overriden by self.contracts
|
6
|
+
def self.contract_list
|
7
7
|
[]
|
8
8
|
end
|
9
9
|
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# Public: Sets the contracts
|
11
|
+
#
|
12
|
+
# contracts - a list of contracts, as String or as Symbols.
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
#
|
16
|
+
# class FooJackContract < Contract
|
17
|
+
# contracts :save, :get, :list
|
18
|
+
#
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Returns Nothing.
|
22
|
+
def self.contracts *contracts
|
23
|
+
singleton_class.send :define_method, :contract_list do
|
24
|
+
contracts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# This method will move methods defined in @contracts into new methods.
|
29
|
+
# Each entry in @contracts will cause the method with the same name to
|
30
|
+
# become method_name_alias and for the original method to point to
|
13
31
|
# method_name_contract.
|
14
32
|
def self.method_added name
|
15
33
|
unless @@disable_override
|
16
|
-
self.
|
34
|
+
self.contract_list.each do |method|
|
17
35
|
if name == method.to_sym
|
18
36
|
method_alias = "#{method}_alias".to_sym
|
19
37
|
method_contract = "#{method}_contract".to_sym
|
20
38
|
|
21
|
-
@@disable_override = true # to stop the new build method
|
39
|
+
@@disable_override = true # to stop the new build method
|
22
40
|
self.send :alias_method, method_alias, name
|
23
41
|
self.send :remove_method, name
|
24
42
|
self.send :alias_method, name, method_contract
|
@@ -26,24 +44,24 @@ class Contract
|
|
26
44
|
@@disable_override = false
|
27
45
|
else
|
28
46
|
# puts self.inspect
|
29
|
-
#
|
47
|
+
# puts "defining other method #{name}"
|
30
48
|
end
|
31
49
|
end
|
32
50
|
end
|
33
51
|
end
|
34
52
|
|
35
53
|
# This method is used as a shorthand to mak the contract method calling pattern more DRY
|
36
|
-
# It starts by checking if you are sending in input and if so will check the input shape for
|
54
|
+
# It starts by checking if you are sending in input and if so will check the input shape for
|
37
55
|
# errors. If no errors are found it calls the method via the passed in symbol(method).
|
38
56
|
#
|
39
57
|
# Output checking is more complicated because of the types of output we check for. Nil is
|
40
|
-
# never valid output. If we pass in the output shape of true, that means we are looking for
|
58
|
+
# never valid output. If we pass in the output shape of true, that means we are looking for
|
41
59
|
# result to be the object True. If the output shape is an array, that is actually a shorthand
|
42
60
|
# for telling our output check to look at the output as an array and compare it to the shape
|
43
61
|
# stored in output_shape[0]. If we pass in the symbol :true_false it means we are looking for
|
44
62
|
# the result to be either true or false. The default case will just check if result has the shape
|
45
63
|
# of the output_shape.
|
46
|
-
def call_method method, input, input_shape, output_shape
|
64
|
+
def call_method method, input, input_shape, output_shape
|
47
65
|
if input != nil && input_shape != nil
|
48
66
|
unless input.has_shape? input_shape
|
49
67
|
raise ContractInputError, 'incorrect input data format'
|
@@ -70,23 +88,23 @@ class Contract
|
|
70
88
|
end
|
71
89
|
|
72
90
|
# we want to check the shape of each item in the result array
|
73
|
-
if output_shape.class == Array
|
91
|
+
if output_shape.class == Array
|
74
92
|
if result.class == Array
|
75
93
|
inner_shape = output_shape[0]
|
76
94
|
result.each do |item|
|
77
95
|
unless item.has_shape? inner_shape
|
78
96
|
raise ContractOutputError, 'incorrect output data format'
|
79
97
|
end
|
80
|
-
end
|
81
|
-
|
82
|
-
return result
|
83
|
-
end
|
98
|
+
end
|
99
|
+
|
100
|
+
return result
|
101
|
+
end
|
84
102
|
raise ContractOutputError, 'incorrect output data format'
|
85
|
-
end
|
103
|
+
end
|
86
104
|
|
87
|
-
# we want result to be true or false
|
105
|
+
# we want result to be true or false
|
88
106
|
if output_shape == :true_false
|
89
|
-
unless result == true || result == false
|
107
|
+
unless result == true || result == false
|
90
108
|
raise ContractOutputError, 'incorrect output data format'
|
91
109
|
end
|
92
110
|
|
@@ -122,8 +140,10 @@ class Hash
|
|
122
140
|
return shape.empty?
|
123
141
|
end
|
124
142
|
|
125
|
-
all? do |k, v|
|
126
|
-
|
143
|
+
shape.all? do |k, v|
|
144
|
+
# hash_value
|
145
|
+
hv = self[k]
|
146
|
+
Hash === hv ? hv.has_shape?(v) : v === hv
|
127
147
|
end
|
128
148
|
end
|
129
149
|
end
|
data/lib/obvious/version.rb
CHANGED
data/lib/obvious.rb
CHANGED
@@ -1,285 +1,3 @@
|
|
1
1
|
require 'obvious/version'
|
2
2
|
require 'obvious/contract'
|
3
|
-
require 'yaml'
|
4
3
|
|
5
|
-
module Obvious
|
6
|
-
# Your code goes here...
|
7
|
-
def self.generate
|
8
|
-
puts 'generate the codes!a'
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
#`rm -rf app`
|
13
|
-
|
14
|
-
app_dir = 'app'
|
15
|
-
|
16
|
-
counter = 1
|
17
|
-
while File.directory? app_dir
|
18
|
-
app_dir = "app_#{counter}"
|
19
|
-
counter += 1
|
20
|
-
end
|
21
|
-
|
22
|
-
puts "Generating application at: #{app_dir}"
|
23
|
-
|
24
|
-
dirs = ['/', '/actions', '/contracts', '/entities',
|
25
|
-
'/spec', '/spec/actions', '/spec/contracts', '/spec/entities',
|
26
|
-
'/spec/doubles']
|
27
|
-
|
28
|
-
dirs.each do |dir|
|
29
|
-
Dir.mkdir app_dir + dir
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
target_path = File.realpath Dir.pwd
|
34
|
-
spec = Gem::Specification.find_by_name("obvious")
|
35
|
-
gem_root = spec.gem_dir
|
36
|
-
gem_lib = gem_root + "/lib"
|
37
|
-
|
38
|
-
#`cp #{gem_lib}/obvious/files/contract.rb #{target_path}/app/contracts/contract.rb`
|
39
|
-
`cp #{gem_lib}/obvious/files/Rakefile #{target_path}/Rakefile`
|
40
|
-
entities = Hash.new
|
41
|
-
jacks = Hash.new
|
42
|
-
|
43
|
-
files = Dir['descriptors/*.yml']
|
44
|
-
|
45
|
-
files.each do |file|
|
46
|
-
action = YAML.load_file file
|
47
|
-
code = ''
|
48
|
-
#puts action.inspect
|
49
|
-
|
50
|
-
local_jacks = Hash.new
|
51
|
-
local_entities = Hash.new
|
52
|
-
|
53
|
-
action['Code'].each do |entry|
|
54
|
-
code << " \# #{entry['c']}\n"
|
55
|
-
code << " \# use: #{entry['requires']}\n" if entry['requires']
|
56
|
-
code << " \n"
|
57
|
-
|
58
|
-
if entry['requires']
|
59
|
-
requires = entry['requires'].split(',')
|
60
|
-
requires.each do |req|
|
61
|
-
req.strip!
|
62
|
-
info = req.split '.'
|
63
|
-
|
64
|
-
if info[0].index 'Jack'
|
65
|
-
unless jacks[info[0]]
|
66
|
-
jacks[info[0]] = []
|
67
|
-
end
|
68
|
-
|
69
|
-
unless local_jacks[info[0]]
|
70
|
-
local_jacks[info[0]] = []
|
71
|
-
end
|
72
|
-
|
73
|
-
jacks[info[0]] << info[1]
|
74
|
-
local_jacks[info[0]] << info[1]
|
75
|
-
else
|
76
|
-
unless entities[info[0]]
|
77
|
-
entities[info[0]] = []
|
78
|
-
end
|
79
|
-
|
80
|
-
unless local_entities[info[0]]
|
81
|
-
local_entities[info[0]] = []
|
82
|
-
end
|
83
|
-
|
84
|
-
entities[info[0]] << info[1]
|
85
|
-
local_entities[info[0]] << info[1]
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
jack_inputs = ''
|
95
|
-
jack_assignments = ''
|
96
|
-
|
97
|
-
local_jacks.each do |k, v|
|
98
|
-
name = k.chomp('Jack').downcase
|
99
|
-
jack_inputs << "#{name}_jack, "
|
100
|
-
jack_assignments << " @#{name}_jack = #{name}_jack\n"
|
101
|
-
end
|
102
|
-
|
103
|
-
jack_inputs.chomp! ', '
|
104
|
-
|
105
|
-
entity_requires = ''
|
106
|
-
|
107
|
-
local_entities.each do |k, v|
|
108
|
-
name = k.downcase
|
109
|
-
entity_requires << "require_relative '../entities/#{name}'\n"
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
output = <<FIN
|
114
|
-
#{entity_requires}
|
115
|
-
class #{action['Action']}
|
116
|
-
|
117
|
-
def initialize #{jack_inputs}
|
118
|
-
#{jack_assignments} end
|
119
|
-
|
120
|
-
def do input
|
121
|
-
#{code} end
|
122
|
-
|
123
|
-
end
|
124
|
-
FIN
|
125
|
-
snake_name = action['Action'].gsub(/(.)([A-Z])/,'\1_\2').downcase
|
126
|
-
|
127
|
-
filename = "#{app_dir}/actions/#{snake_name}.rb"
|
128
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
129
|
-
|
130
|
-
#puts output
|
131
|
-
|
132
|
-
output = <<FIN
|
133
|
-
require_relative '../../actions/#{snake_name}'
|
134
|
-
|
135
|
-
describe #{action['Action']} do
|
136
|
-
|
137
|
-
it '#{action['Description']}'
|
138
|
-
|
139
|
-
it 'should raise an error with invalid input'
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
FIN
|
145
|
-
|
146
|
-
filename = "#{app_dir}/spec/actions/#{snake_name}_spec.rb"
|
147
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
148
|
-
|
149
|
-
#puts output
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
#filter out duplicate methods
|
154
|
-
|
155
|
-
entities.each do |k, v|
|
156
|
-
v.uniq!
|
157
|
-
end
|
158
|
-
|
159
|
-
jacks.each do |k,v|
|
160
|
-
v.uniq!
|
161
|
-
end
|
162
|
-
|
163
|
-
#puts entities.inspect
|
164
|
-
#puts jacks.inspect
|
165
|
-
|
166
|
-
entities.each do |k, v|
|
167
|
-
name = k
|
168
|
-
method_specs = ''
|
169
|
-
method_definitions = ''
|
170
|
-
|
171
|
-
v.each do |method|
|
172
|
-
method_definitions << "
|
173
|
-
def #{method} input
|
174
|
-
nil
|
175
|
-
end
|
176
|
-
"
|
177
|
-
|
178
|
-
method_specs << "
|
179
|
-
describe '.#{method}' do
|
180
|
-
it 'should #{method} with valid input'
|
181
|
-
|
182
|
-
it 'should raise an error with invalid input'
|
183
|
-
|
184
|
-
end
|
185
|
-
"
|
186
|
-
|
187
|
-
end
|
188
|
-
|
189
|
-
output = <<FIN
|
190
|
-
class #{name}
|
191
|
-
#{method_definitions}
|
192
|
-
end
|
193
|
-
FIN
|
194
|
-
snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
195
|
-
|
196
|
-
filename = "#{app_dir}/entities/#{snake_name}.rb"
|
197
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
198
|
-
|
199
|
-
output = <<FIN
|
200
|
-
require_relative '../../entities/#{snake_name}'
|
201
|
-
|
202
|
-
describe #{name} do
|
203
|
-
#{method_specs}
|
204
|
-
end
|
205
|
-
|
206
|
-
|
207
|
-
FIN
|
208
|
-
filename = "#{app_dir}/spec/entities/#{snake_name}_spec.rb"
|
209
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
210
|
-
|
211
|
-
|
212
|
-
#puts output
|
213
|
-
end
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
jacks.each do |k, v|
|
218
|
-
|
219
|
-
name = k.chomp('Jack').downcase
|
220
|
-
|
221
|
-
method_specs = ''
|
222
|
-
method_definitions = ''
|
223
|
-
|
224
|
-
v.each do |method|
|
225
|
-
|
226
|
-
method_definitions << "
|
227
|
-
def #{method}_contract input
|
228
|
-
input_shape = {}
|
229
|
-
output_shape = {}
|
230
|
-
call_method :#{method}_alias, input, input_shape, output_shape
|
231
|
-
end
|
232
|
-
"
|
233
|
-
|
234
|
-
method_specs << "
|
235
|
-
describe '.#{method}_contract' do
|
236
|
-
it 'should #{method} data with valid input'
|
237
|
-
|
238
|
-
it 'should raise an error with invalid input'
|
239
|
-
|
240
|
-
it 'should raise an error with invalid output'
|
241
|
-
|
242
|
-
end
|
243
|
-
"
|
244
|
-
|
245
|
-
end
|
246
|
-
|
247
|
-
|
248
|
-
output = <<FIN
|
249
|
-
require 'obvious'
|
250
|
-
|
251
|
-
class #{k}Contract < Contract
|
252
|
-
def self.contracts
|
253
|
-
#{v.to_s}
|
254
|
-
end
|
255
|
-
#{method_definitions}
|
256
|
-
end
|
257
|
-
FIN
|
258
|
-
|
259
|
-
snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
|
260
|
-
|
261
|
-
filename = "#{app_dir}/contracts/#{snake_name}_jack_contract.rb"
|
262
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
263
|
-
|
264
|
-
#puts output
|
265
|
-
|
266
|
-
output = <<FIN
|
267
|
-
require_relative '../../contracts/#{snake_name}_jack_contract'
|
268
|
-
|
269
|
-
describe #{k}Contract do
|
270
|
-
#{method_specs}
|
271
|
-
end
|
272
|
-
|
273
|
-
FIN
|
274
|
-
|
275
|
-
filename = "#{app_dir}/spec/contracts/#{snake_name}_jack_spec.rb"
|
276
|
-
File.open(filename, 'w') {|f| f.write(output) }
|
277
|
-
|
278
|
-
#puts output
|
279
|
-
end
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
end
|
285
|
-
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: obvious
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-10 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A set of tools to build apps using the Obvious Architecture
|
15
15
|
email:
|
@@ -50,9 +50,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
50
|
version: '0'
|
51
51
|
requirements: []
|
52
52
|
rubyforge_project:
|
53
|
-
rubygems_version: 1.8.
|
53
|
+
rubygems_version: 1.8.11
|
54
54
|
signing_key:
|
55
55
|
specification_version: 3
|
56
56
|
summary: Isn't it Obvious?
|
57
57
|
test_files: []
|
58
|
-
has_rdoc:
|