obvious 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/bin/obvious CHANGED
@@ -2,293 +2,6 @@
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
-
289
5
  if ARGV[0] == 'generate'
290
- Obvious::generate
6
+ Obvious::Generators::ApplicationGenerator.generate
291
7
  end
292
-
293
-
294
-
@@ -0,0 +1,159 @@
1
+ require 'yaml'
2
+
3
+ require_relative 'helpers/application'
4
+ require_relative 'descriptor'
5
+
6
+ module Obvious
7
+ module Generators
8
+ class ApplicationGenerator
9
+ class << self
10
+ def generate
11
+ @app = Obvious::Generators::Application.instance
12
+
13
+ puts 'Generating the files...'
14
+
15
+ Obvious::Generators::ApplicationGenerator.create_directories ['/', '/actions', '/contracts', '/entities',
16
+ '/spec', '/spec/actions', '/spec/contracts', '/spec/entities',
17
+ '/spec/doubles']
18
+
19
+ unless File.exist? "#{@app.target_path}/Rakefile"
20
+ puts 'Creating Rakefile...'
21
+ `cp #{@app.lib_path}/obvious/files/Rakefile #{@app.target_path}/Rakefile`
22
+ end
23
+
24
+ unless File.exist? "#{@app.target_path}/external"
25
+ puts 'Creating external directory'
26
+ `cp -r #{@app.lib_path}/obvious/files/external #{@app.target_path}/external`
27
+ end
28
+
29
+ descriptors = Dir['descriptors/*.yml']
30
+
31
+ puts 'Creating actions from descriptors... ' unless descriptors.length.zero?
32
+ descriptors.each do |file|
33
+ descriptor = Obvious::Generators::Descriptor.new file
34
+ descriptor.to_file
35
+ end
36
+
37
+ @app.remove_duplicates
38
+
39
+ puts 'Writing Entities scaffolds... '
40
+ Obvious::Generators::ApplicationGenerator.write_entities
41
+
42
+ puts 'Writing jacks scaffolds... '
43
+ Obvious::Generators::ApplicationGenerator.write_jacks
44
+
45
+ puts "Files are located in the `#{@app.dir}` directory."
46
+ end # ::generate
47
+
48
+ def create_directories directories
49
+ directories.each do |dir|
50
+ Dir.mkdir @app.dir + dir
51
+ end
52
+ end
53
+
54
+ def write_entities
55
+ @app.entities.each do |k, v|
56
+ name = k
57
+ method_specs = ''
58
+ method_defs = ''
59
+
60
+ method_defs << '
61
+ def self.shape
62
+ {}
63
+ end
64
+ '
65
+
66
+ v.each do |method|
67
+ method_defs << "
68
+ def #{method} input
69
+ nil
70
+ end
71
+ "
72
+
73
+ method_specs << "
74
+ describe '.#{method}' do
75
+ it 'should #{method} with valid input'
76
+
77
+ it 'should raise an error with invalid input'
78
+
79
+ end
80
+ "
81
+ end
82
+
83
+ output = %Q{class #{name}
84
+ #{method_defs}
85
+ end
86
+ }
87
+ snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
88
+
89
+ filename = "#{@app.dir}/entities/#{snake_name}.rb"
90
+ File.open(filename, 'w') { |f| f.write(output) }
91
+
92
+ output = %Q{require_relative '../../entities/#{snake_name}'
93
+
94
+ describe #{name} do
95
+ #{method_specs}
96
+ end
97
+ }
98
+
99
+ filename = "#{@app.dir}/spec/entities/#{snake_name}_spec.rb"
100
+ File.open(filename, 'w') {|f| f.write(output) }
101
+ end
102
+ end #write_entities
103
+
104
+ def write_jacks
105
+ @app.jacks.each do |k, v|
106
+ name = k.chomp('Jack').downcase
107
+ method_specs = ''
108
+ method_defs = ''
109
+
110
+ v.each do |method|
111
+
112
+ method_defs << "
113
+ def #{method}_contract input
114
+ input_shape = {}
115
+ output_shape = {}
116
+ call_method :#{method}_alias, input, input_shape, output_shape
117
+ end
118
+ "
119
+
120
+ method_specs << "
121
+ describe '.#{method}_contract' do
122
+ it 'should #{method} data with valid input'
123
+
124
+ it 'should raise an error with invalid input'
125
+
126
+ it 'should raise an error with invalid output'
127
+
128
+ end
129
+ "
130
+ end
131
+
132
+ output = %Q{require 'obvious'
133
+
134
+ class #{k}Contract < Contract
135
+ contracts :#{ v.join(', :')}
136
+ #{method_defs}
137
+ end
138
+ }
139
+
140
+ snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
141
+
142
+ filename = "#{@app.dir}/contracts/#{snake_name}_jack_contract.rb"
143
+ File.open(filename, 'w') {|f| f.write(output) }
144
+
145
+ output = %Q{require_relative '../../contracts/#{snake_name}_jack_contract'
146
+
147
+ describe #{k}Contract do
148
+ #{method_specs}
149
+ end
150
+ }
151
+
152
+ filename = "#{@app.dir}/spec/contracts/#{snake_name}_jack_spec.rb"
153
+ File.open(filename, 'w') {|f| f.write(output) }
154
+ end
155
+ end # generate_jacks_code
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,107 @@
1
+ require 'yaml'
2
+
3
+ require_relative 'helpers/application'
4
+
5
+ module Obvious
6
+ module Generators
7
+ class Descriptor
8
+ def initialize descriptor
9
+ @descriptor = descriptor
10
+ end
11
+
12
+ def to_file
13
+ action = YAML.load_file @descriptor
14
+ @jacks, @entities = {}, {}
15
+ @code = ''
16
+
17
+ action['Code'].each do |entry|
18
+ write_comments_for entry
19
+ process_requirements_for entry if entry['requires']
20
+ end
21
+
22
+ write_action action
23
+ end
24
+
25
+ private
26
+ def write_comments_for entry
27
+ @code << " \# #{entry['c']}\n"
28
+ @code << " \# use: #{entry['requires']}\n" if entry['requires']
29
+ @code << " \n"
30
+ end
31
+
32
+ def process_requirements_for entry
33
+ app = Obvious::Generators::Application.instance
34
+ requires = entry['requires'].split ','
35
+
36
+ requires.each do |req|
37
+ req.strip!
38
+ infos = req.split '.'
39
+
40
+ if infos[0].index 'Jack'
41
+ app.jacks[infos[0]] = [] unless app.jacks[infos[0]]
42
+ @jacks[infos[0]] = [] unless @jacks[infos[0]]
43
+
44
+ app.jacks[infos[0]] << infos[1]
45
+ @jacks[infos[0]] << infos[1]
46
+ else
47
+ app.entities[infos[0]] = [] unless app.entities[infos[0]]
48
+ @entities[infos[0]] = [] unless @entities[infos[0]]
49
+
50
+ app.entities[infos[0]] << infos[1]
51
+ @entities[infos[0]] << infos[1]
52
+ end
53
+ end
54
+ end # #process_requirements_for
55
+
56
+ def write_action action
57
+ jacks_data = process_jacks
58
+ requirements = require_entities
59
+
60
+ output = %Q{#{requirements}
61
+ class #{action['Action']}
62
+
63
+ def initialize #{jacks_data[:inputs]}
64
+ #{jacks_data[:assignments]} end
65
+
66
+ def execute input
67
+ #{@code} end
68
+ end
69
+ }
70
+
71
+ snake_name = action['Action'].gsub(/(.)([A-Z])/,'\1_\2').downcase
72
+
73
+ filename = "#{Obvious::Generators::Application.instance.dir}/actions/#{snake_name}.rb"
74
+ File.open(filename, 'w') {|f| f.write(output) }
75
+ end
76
+
77
+ def process_jacks
78
+ jack_inputs = ''
79
+ jack_assignments = ''
80
+
81
+ @jacks.each do |k, v|
82
+ name = k.chomp('Jack').downcase
83
+ jack_inputs << "#{name}_jack, "
84
+ jack_assignments << " @#{name}_jack = #{name}_jack\n"
85
+ end
86
+
87
+ jack_inputs.chomp! ', '
88
+
89
+ {
90
+ inputs: jack_inputs,
91
+ assignments: jack_assignments
92
+ }
93
+ end
94
+
95
+ def require_entities
96
+ entity_requires = ''
97
+
98
+ @entities.each do |k, v|
99
+ name = k.downcase
100
+ entity_requires << "require_relative '../entities/#{name}'\n"
101
+ end
102
+
103
+ entity_requires
104
+ end
105
+ end # ::Descriptor
106
+ end
107
+ end
@@ -0,0 +1,47 @@
1
+ require 'singleton'
2
+
3
+ module Obvious
4
+ module Generators
5
+ class Application
6
+ include Singleton
7
+
8
+ attr_reader :jacks, :entities, :dir
9
+
10
+ def initialize
11
+ @dir = 'app'
12
+
13
+ counter = 1
14
+ while File.directory? @dir
15
+ @dir = "app_#{counter}"
16
+ counter += 1
17
+ end
18
+ end
19
+
20
+ def jacks
21
+ @jacks ||= {}
22
+ end
23
+
24
+ def entities
25
+ @entities ||= {}
26
+ end
27
+
28
+ def target_path
29
+ File.realpath Dir.pwd
30
+ end
31
+
32
+ def lib_path
33
+ Gem::Specification.find_by_name("obvious").gem_dir + '/lib'
34
+ end
35
+
36
+ def remove_duplicates
37
+ entities.each do |k, v|
38
+ v.uniq!
39
+ end
40
+
41
+ jacks.each do |k,v|
42
+ v.uniq!
43
+ end
44
+ end
45
+ end # ::Application
46
+ end
47
+ end
data/lib/obvious.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'obvious/version'
2
2
  require 'obvious/contract'
3
-
3
+ require_relative 'generators/application_generator'
@@ -20,7 +20,7 @@ class Contract
20
20
  #
21
21
  # Returns Nothing.
22
22
  def self.contracts *contracts
23
- singleton_class.send :define_method, :contract_list do
23
+ singleton_class.send :define_method, :contract_list do
24
24
  contracts
25
25
  end
26
26
  end
@@ -0,0 +1,94 @@
1
+ require 'json'
2
+
3
+ class FsPlug
4
+
5
+ def initialize filename
6
+ @filename = filename
7
+ end
8
+
9
+ def save input
10
+ # open the file
11
+ contents = File.read @filename
12
+
13
+ data = []
14
+ # parse the json list
15
+ query = JSON.parse contents, :symbolize_names => true
16
+
17
+ new_element = true if input[:id] == -1 # by convention set new element flag if id == -1
18
+
19
+ max_id = -1
20
+ # transform the data if needed
21
+ query.each do |h|
22
+ if input[:id] == h[:id]
23
+ h = input
24
+ end
25
+ max_id = h[:id] if h[:id] > max_id
26
+ data << h
27
+ end
28
+
29
+ # add data to the list if it's a new element
30
+ input[:id] = max_id + 1
31
+ data << input if new_element
32
+
33
+ # save the data back to FS
34
+ json_data = JSON.pretty_generate data
35
+ File.open(@filename, 'w') {|f| f.write(json_data) }
36
+
37
+ # return the transformed data
38
+ input
39
+ end
40
+
41
+ def list
42
+ # open the file
43
+ contents = File.read @filename
44
+
45
+ # parse the json list
46
+ data = JSON.parse contents, :symbolize_names => true
47
+
48
+ # return the transformed data
49
+ data
50
+ end
51
+
52
+ def get input
53
+ # open the file
54
+ contents = File.read @filename
55
+
56
+ data = []
57
+ # parse the json list
58
+ query = JSON.parse contents, :symbolize_names => true
59
+
60
+ # transform the data if needed
61
+ query.each do |h|
62
+ return h if h[:id] == input[:id]
63
+ end
64
+
65
+ {}
66
+ end
67
+
68
+ def remove input
69
+ # open the file
70
+ contents = File.read @filename
71
+
72
+ data = []
73
+ # parse the json list
74
+ query = JSON.parse contents, :symbolize_names => true
75
+
76
+ # transform the data if needed
77
+ query.each do |h|
78
+ unless h[:id] == input[:id]
79
+ data << h
80
+ end
81
+ end
82
+
83
+ # save the data back to FS
84
+ json_data = JSON.pretty_generate data
85
+ File.open(@filename, 'w') {|f| f.write(json_data) }
86
+
87
+ # return true on success
88
+ true
89
+ end
90
+
91
+ end
92
+
93
+
94
+
@@ -0,0 +1,57 @@
1
+ require 'moped'
2
+
3
+ class MongoPlug
4
+ def initialize collection
5
+ @collection = collection
6
+ @session = MONGO_SESSION
7
+ end
8
+
9
+ def list
10
+ result = @session[@collection].find.entries
11
+ result.map! do |entry|
12
+ clean_up entry
13
+ end
14
+
15
+ result
16
+ end
17
+
18
+ def get input
19
+ result = symbolize_keys @session[@collection].find(:id => input[:id]).first
20
+ clean_up result
21
+ end
22
+
23
+ def save input
24
+ if input[:id] == -1
25
+ id = @session[:counters].find(:_id => @collection).modify({ "$inc" => { seq: 1 } }, new:true)["seq"]
26
+ input[:id] = id
27
+ end
28
+ result = @session[@collection].find(:id => input[:id]).modify(input, upsert: true, new: true)
29
+ clean_up result
30
+ end
31
+
32
+ def remove input
33
+ @session[@collection].find(:id => input[:id]).remove
34
+ true
35
+ end
36
+
37
+ def clean_up input
38
+ result = symbolize_keys input
39
+ result.delete :_id
40
+ result
41
+ end
42
+
43
+ def symbolize_keys hash
44
+ hash.inject({}){|result, (key, value)|
45
+ new_key = case key
46
+ when String then key.to_sym
47
+ else key
48
+ end
49
+ new_value = case value
50
+ when Hash then symbolize_keys(value)
51
+ else value
52
+ end
53
+ result[new_key] = new_value
54
+ result
55
+ }
56
+ end
57
+ end
@@ -0,0 +1,38 @@
1
+ require 'sequel'
2
+
3
+ # assume that DB is defined as a global constant elsewhere
4
+
5
+ class MysqlPlug
6
+
7
+ def initialize table
8
+ @table = table
9
+ end
10
+
11
+ def save input
12
+ table = DB[@table]
13
+ input[:id] = nil if input[:id] == -1
14
+
15
+ # this does an upsert
16
+ result = table.on_duplicate_key_update.insert input
17
+
18
+ input[:id] = result
19
+ input
20
+ end
21
+
22
+ def list
23
+ table = DB[@table]
24
+ table.all
25
+ end
26
+
27
+ def get input
28
+ table = DB[@table]
29
+ table.first :id => input[:id]
30
+ end
31
+
32
+ def remove input
33
+ table = DB[@table]
34
+ result = table.where(:id => input[:id]).delete
35
+ return true if result == 1
36
+ false
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Obvious
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  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.3
4
+ version: 0.0.5
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: 2013-01-10 00:00:00.000000000 Z
12
+ date: 2013-01-14 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:
@@ -25,9 +25,15 @@ files:
25
25
  - README.md
26
26
  - Rakefile
27
27
  - bin/obvious
28
+ - lib/generators/application_generator.rb
29
+ - lib/generators/descriptor.rb
30
+ - lib/generators/helpers/application.rb
28
31
  - lib/obvious.rb
29
32
  - lib/obvious/contract.rb
30
33
  - lib/obvious/files/Rakefile
34
+ - lib/obvious/files/external/fs_plug.rb
35
+ - lib/obvious/files/external/mongo_plug.rb
36
+ - lib/obvious/files/external/mysql_plug.rb
31
37
  - lib/obvious/version.rb
32
38
  - obvious.gemspec
33
39
  homepage: http://obvious.retromocha.com/
@@ -50,8 +56,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
56
  version: '0'
51
57
  requirements: []
52
58
  rubyforge_project:
53
- rubygems_version: 1.8.11
59
+ rubygems_version: 1.8.17
54
60
  signing_key:
55
61
  specification_version: 3
56
62
  summary: Isn't it Obvious?
57
63
  test_files: []
64
+ has_rdoc: