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.
@@ -1,199 +0,0 @@
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
- yaml = YAML.load_file(file)
34
- descriptor = Obvious::Generators::Descriptor.new yaml
35
- descriptor.to_file
36
- end
37
-
38
- @app.remove_duplicates
39
-
40
- puts 'Writing Entities scaffolds... '
41
- Obvious::Generators::ApplicationGenerator.write_entities
42
-
43
- puts 'Writing jacks scaffolds... '
44
- Obvious::Generators::ApplicationGenerator.write_jacks
45
-
46
- puts "Files are located in the `#{@app.dir}` directory."
47
- end # ::generate
48
-
49
- def create_directories directories
50
- directories.each do |dir|
51
- Dir.mkdir @app.dir + dir
52
- end
53
- end
54
-
55
- def write_entities
56
- @app.entities.each do |k, v|
57
- name = k
58
- method_specs = ''
59
- method_defs = ''
60
-
61
- method_defs << '
62
- def self.shape
63
- {}
64
- end
65
- '
66
-
67
- v.each do |method|
68
- method_defs << "
69
- def #{method} input
70
- nil
71
- end
72
- "
73
-
74
- method_specs << "
75
- describe '.#{method}' do
76
- it 'should #{method} with valid input'
77
-
78
- it 'should raise an error with invalid input'
79
-
80
- end
81
- "
82
- end
83
-
84
- output = %Q{class #{name}
85
- #{method_defs}
86
- end
87
- }
88
- snake_name = name.gsub(/(.)([A-Z])/,'\1_\2').downcase
89
-
90
- filename = "#{@app.dir}/entities/#{snake_name}.rb"
91
- File.open(filename, 'w') { |f| f.write(output) }
92
-
93
- output = %Q{require_relative '../../entities/#{snake_name}'
94
-
95
- describe #{name} do
96
- #{method_specs}
97
- end
98
- }
99
-
100
- filename = "#{@app.dir}/spec/entities/#{snake_name}_spec.rb"
101
- File.open(filename, 'w') {|f| f.write(output) }
102
- end
103
- end #write_entities
104
-
105
- def write_jacks
106
- @app.jacks.each do |k, v|
107
- name = k.chomp('Jack').downcase
108
- method_specs = ''
109
- contract_defs = ''
110
-
111
- jack_double_default_methods = ''
112
- jack_double_badoutput_methods = ''
113
-
114
- v.each do |method|
115
-
116
- contract_defs << "
117
- contract_for :#{method}, {
118
- :input => {},
119
- :output => {},
120
- }
121
- "
122
-
123
- method_specs << "
124
- describe '.#{method}_contract' do
125
- it 'should #{method} data with valid input'
126
-
127
- it 'should raise an error with invalid input'
128
-
129
- it 'should raise an error with invalid output'
130
-
131
- end
132
- "
133
-
134
- jack_double_default_methods << "
135
- def #{method} input
136
- {}
137
- end
138
- "
139
-
140
- jack_double_badoutput_methods << "
141
- def #{method} input
142
- nil
143
- end
144
- "
145
- end
146
-
147
- output = %Q{require 'obvious'
148
-
149
- class #{k}Contract < Obvious::Contract
150
- #{contract_defs}
151
- end
152
- }
153
-
154
- snake_name = k.gsub(/(.)([A-Z])/,'\1_\2').downcase
155
-
156
- filename = "#{@app.dir}/contracts/#{snake_name}_contract.rb"
157
- File.open(filename, 'w') {|f| f.write(output) }
158
-
159
- output = %Q{require_relative '../../contracts/#{snake_name}_contract'
160
-
161
- describe #{k}Contract do
162
- #{method_specs}
163
- end
164
- }
165
-
166
- filename = "#{@app.dir}/spec/contracts/#{snake_name}_spec.rb"
167
- File.open(filename, 'w') {|f| f.write(output) }
168
-
169
- output = %Q{require_relative '../../contracts/#{snake_name}_contract'
170
-
171
- class #{k}Double
172
- def self.create behavior
173
- case behavior
174
- when :bad_output
175
- #{k}_BadOutput.new
176
- when :default
177
- #{k}_Default.new
178
- end
179
- end
180
- end
181
-
182
- class #{k}_Default < #{k}Contract
183
- #{jack_double_default_methods}
184
- end
185
-
186
- class #{k}_BadOutput < #{k}Contract
187
- #{jack_double_badoutput_methods}
188
- end
189
- }
190
-
191
- filename = "#{@app.dir}/spec/doubles/#{snake_name}_double.rb"
192
- File.open(filename, 'w') {|f| f.write(output) }
193
-
194
- end
195
- end # generate_jacks_code
196
- end
197
- end
198
- end
199
- end
@@ -1,131 +0,0 @@
1
- require 'yaml'
2
-
3
- require_relative 'helpers/application'
4
-
5
- module Obvious
6
- module Generators
7
- class InvalidDescriptorError < StandardError; end
8
-
9
- class Descriptor
10
- def initialize descriptor
11
- @descriptor = descriptor
12
- end
13
-
14
- def to_file
15
- validate_descriptor
16
-
17
- @jacks, @entities = {}, {}
18
- @code = ''
19
-
20
- @descriptor['Code'].each do |entry|
21
- write_comments_for entry
22
- process_requirements_for entry if entry['requires']
23
- end
24
-
25
- write_action
26
- end
27
-
28
- private
29
- def write_comments_for entry
30
- @code << " \# #{entry['c']}\n"
31
- @code << " \# use: #{entry['requires']}\n" if entry['requires']
32
- @code << " \n"
33
- end
34
-
35
- def process_requirements_for entry
36
- app = Obvious::Generators::Application.instance
37
- requires = entry['requires'].split ','
38
-
39
- requires.each do |req|
40
- req.strip!
41
- infos = req.split '.'
42
-
43
- if infos[0].index 'Jack'
44
- app.jacks[infos[0]] = [] unless app.jacks[infos[0]]
45
- @jacks[infos[0]] = [] unless @jacks[infos[0]]
46
-
47
- app.jacks[infos[0]] << infos[1]
48
- @jacks[infos[0]] << infos[1]
49
- else
50
- app.entities[infos[0]] = [] unless app.entities[infos[0]]
51
- @entities[infos[0]] = [] unless @entities[infos[0]]
52
-
53
- app.entities[infos[0]] << infos[1]
54
- @entities[infos[0]] << infos[1]
55
- end
56
- end
57
- end # #process_requirements_for
58
-
59
- def write_action
60
- jacks_data = process_jacks
61
- requirements = require_entities
62
-
63
- output = %Q{#{requirements}
64
- class #{@descriptor['Action']}
65
-
66
- def initialize #{jacks_data[:inputs]}
67
- #{jacks_data[:assignments]} end
68
-
69
- def execute input
70
- #{@code} end
71
- end
72
- }
73
-
74
- snake_name = @descriptor['Action'].gsub(/(.)([A-Z])/,'\1_\2').downcase
75
-
76
- filename = "#{Obvious::Generators::Application.instance.dir}/actions/#{snake_name}.rb"
77
- File.open(filename, 'w') {|f| f.write(output) }
78
-
79
- output = %Q{require_relative '../../actions/#{snake_name}'
80
-
81
- describe #{@descriptor['Action']} do
82
-
83
- it '#{@descriptor['Description']}'
84
-
85
- it 'should raise an error with invalid input'
86
-
87
- end
88
- }
89
-
90
- filename = "#{Obvious::Generators::Application.instance.dir}/spec/actions/#{snake_name}_spec.rb"
91
- File.open(filename, 'w') {|f| f.write(output) }
92
- end
93
-
94
- def process_jacks
95
- jack_inputs = ''
96
- jack_assignments = ''
97
-
98
- @jacks.each do |k, v|
99
- name = k.chomp('Jack').downcase
100
- jack_inputs << "#{name}_jack, "
101
- jack_assignments << " @#{name}_jack = #{name}_jack\n"
102
- end
103
-
104
- jack_inputs.chomp! ', '
105
-
106
- {
107
- inputs: jack_inputs,
108
- assignments: jack_assignments
109
- }
110
- end
111
-
112
- def require_entities
113
- entity_requires = ''
114
-
115
- @entities.each do |k, v|
116
- snake_name = k.gsub(/(.)([A-Z])/,'\1_\2').downcase
117
- entity_requires << "require_relative '../entities/#{snake_name}'\n"
118
- end
119
-
120
- entity_requires
121
- end
122
-
123
- def validate_descriptor
124
- raise InvalidDescriptorError unless @descriptor
125
- raise InvalidDescriptorError if @descriptor['Code'].nil?
126
- raise InvalidDescriptorError if @descriptor['Action'].nil?
127
- raise InvalidDescriptorError if @descriptor['Description'].nil?
128
- end
129
- end # ::Descriptor
130
- end
131
- end
@@ -1,47 +0,0 @@
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
@@ -1,4 +0,0 @@
1
- task :rspec do
2
- sh 'rspec ./app -c'
3
- end
4
-
@@ -1,99 +0,0 @@
1
- require 'json'
2
-
3
- class FsPlug
4
-
5
- def initialize filename
6
- @filename = filename
7
- end
8
-
9
- def load_data
10
- contents = File.read @filename
11
- JSON.parse contents, :symbolize_names => true
12
- end
13
-
14
- def save_data input
15
- json_data = JSON.pretty_generate input
16
- File.open(@filename, 'w') {|f| f.write(json_data) }
17
- end
18
-
19
- def save input
20
- data = []
21
- query = load_data
22
-
23
- new_element = true if input[:id] == -1 # by convention set new element flag if id == -1
24
-
25
- max_id = -1
26
- # transform the data if needed
27
- query.each do |h|
28
- if input[:id] == h[:id]
29
- h = input
30
- end
31
- max_id = h[:id] if h[:id] > max_id
32
- data << h
33
- end
34
-
35
- # add data to the list if it's a new element
36
- if new_element
37
- input[:id] = max_id + 1
38
- data << input
39
- end
40
-
41
- save_data data
42
-
43
- # return the transformed data
44
- input
45
- end
46
-
47
- def list
48
- load_data
49
- end
50
-
51
- def get input
52
- data = []
53
- query = load_data
54
-
55
- # transform the data if needed
56
- query.each do |h|
57
- return h if h[:id] == input[:id]
58
- end
59
-
60
- raise Exception.new 'no object found'
61
- end
62
-
63
- def remove input
64
- data = []
65
- # parse the json list
66
- query = load_data
67
-
68
- # transform the data if needed
69
- query.each do |h|
70
- unless h[:id] == input[:id]
71
- data << h
72
- end
73
- end
74
-
75
- save_data data
76
-
77
- # return true on success
78
- true
79
- end
80
-
81
- def find input
82
- data = []
83
- query = load_data
84
-
85
- key = input.keys[0]
86
-
87
- query.each do |h|
88
- if input[key] == h[key]
89
- return h
90
- end
91
- end
92
-
93
- raise Exception.new 'no object found'
94
- end
95
- end
96
-
97
-
98
-
99
-
@@ -1,62 +0,0 @@
1
- require 'moped'
2
-
3
- # To get the mongo system to work you need to have a counters collection. The
4
- # code here will increment the seq field which we use to set the id. If you are
5
- # having problems, you probably need to create the collection and add entries
6
- # for each other collection you want to have an id sequence.
7
-
8
- class MongoPlug
9
- def initialize collection
10
- @collection = collection
11
- @session = MONGO_SESSION
12
- end
13
-
14
- def list
15
- result = @session[@collection].find.entries
16
- result.map! do |entry|
17
- clean_up entry
18
- end
19
-
20
- result
21
- end
22
-
23
- def get input
24
- result = symbolize_keys @session[@collection].find(:id => input[:id]).first
25
- clean_up result
26
- end
27
-
28
- def save input
29
- if input[:id] == -1
30
- id = @session[:counters].find(:_id => @collection).modify({ "$inc" => { seq: 1 } }, new:true)["seq"]
31
- input[:id] = id
32
- end
33
- result = @session[@collection].find(:id => input[:id]).modify(input, upsert: true, new: true)
34
- clean_up result
35
- end
36
-
37
- def remove input
38
- @session[@collection].find(:id => input[:id]).remove
39
- true
40
- end
41
-
42
- def clean_up input
43
- result = symbolize_keys input
44
- result.delete :_id
45
- result
46
- end
47
-
48
- def symbolize_keys hash
49
- hash.inject({}){|result, (key, value)|
50
- new_key = case key
51
- when String then key.to_sym
52
- else key
53
- end
54
- new_value = case value
55
- when Hash then symbolize_keys(value)
56
- else value
57
- end
58
- result[new_key] = new_value
59
- result
60
- }
61
- end
62
- end
@@ -1,38 +0,0 @@
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,94 +0,0 @@
1
- require 'json'
2
- require 'aws/s3'
3
-
4
- class S3Plug
5
- include AWS::S3
6
-
7
- def initialize input
8
- @filename = input[:filename]
9
- @bucket = input[:bucket]
10
-
11
- # you can test locally with the fake-s3 gem: https://github.com/jubos/fake-s3
12
- # or just swap out for the filesystem plug locally
13
- s3_key = ENV['S3_KEY'] || '123'
14
- s3_secret = ENV['S3_SECRET'] || 'abc'
15
- s3_server = ENV['S3_SERVER'] || '0.0.0.0'
16
- s3_port = ENV['S3_PORT'] || '10001'
17
-
18
- AWS::S3::Base.establish_connection!(:access_key_id => s3_key,
19
- :secret_access_key => s3_secret,
20
- :server => s3_server,
21
- :port => s3_port)
22
- end
23
-
24
- def load_data
25
- contents = S3Object.value @filename, @bucket
26
- JSON.parse contents, :symbolize_names => true
27
- end
28
-
29
- def save_data data
30
- json_data = JSON.pretty_generate data
31
- S3Object.store @filename, json_data, @bucket
32
- end
33
-
34
- def save input
35
- data = []
36
- result = load_data
37
- new_element = true if input[:id] == -1 # by convention set new element flag if id == -1
38
-
39
- max_id = -1
40
- # transform the data if needed
41
- result.each do |h|
42
- if input[:id] == h[:id]
43
- h = input
44
- end
45
- max_id = h[:id] if h[:id] > max_id
46
- data << h
47
- end
48
-
49
- # add data to the list if it's a new element
50
- if new_element
51
- input[:id] = max_id + 1
52
- data << input
53
- end
54
-
55
- save_data data
56
-
57
- # return the transformed data
58
- input
59
- end
60
-
61
- def list
62
- load_data
63
- end
64
-
65
- def get input
66
- data = []
67
- result = load_data
68
-
69
- # transform the data if needed
70
- result.each do |h|
71
- return h if h[:id] == input[:id]
72
- end
73
-
74
- {}
75
- end
76
-
77
- def remove input
78
- data = []
79
- result = load_data
80
-
81
- # transform the data if needed
82
- result.each do |h|
83
- unless h[:id] == input[:id]
84
- data << h
85
- end
86
- end
87
-
88
- save_data data
89
-
90
- # return true on success
91
- true
92
- end
93
- end
94
-
Binary file