my_enginery 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.gitignore +18 -0
  2. data/.travis.yml +9 -0
  3. data/CHANGELOG.md +14 -0
  4. data/Gemfile +12 -0
  5. data/LICENSE +19 -0
  6. data/README.md +957 -0
  7. data/Rakefile +48 -0
  8. data/app/base/.pryrc +1 -0
  9. data/app/base/Gemfile +25 -0
  10. data/app/base/Rakefile +4 -0
  11. data/app/base/app.rb +8 -0
  12. data/app/base/base/boot.rb +45 -0
  13. data/app/base/base/config.rb +127 -0
  14. data/app/base/base/controllers/rear-controllers/.gitkeep +0 -0
  15. data/app/base/base/database.rb +3 -0
  16. data/app/base/base/helpers/application_helpers.rb +3 -0
  17. data/app/base/base/migrations/.gitkeep +0 -0
  18. data/app/base/base/models/.gitkeep +0 -0
  19. data/app/base/base/specs/.gitkeep +0 -0
  20. data/app/base/base/views/.gitkeep +0 -0
  21. data/app/base/config.ru +4 -0
  22. data/app/base/config/config.yml +17 -0
  23. data/app/base/public/assets/Enginery.png +0 -0
  24. data/app/base/public/assets/Espresso.png +0 -0
  25. data/app/base/public/assets/application.css +13 -0
  26. data/app/base/public/assets/application.js +2 -0
  27. data/app/base/public/assets/bootstrap/css/bootstrap-responsive.min.css +9 -0
  28. data/app/base/public/assets/bootstrap/css/bootstrap.min.css +9 -0
  29. data/app/base/public/assets/bootstrap/img/glyphicons-halflings-white.png +0 -0
  30. data/app/base/public/assets/bootstrap/img/glyphicons-halflings.png +0 -0
  31. data/app/base/public/assets/bootstrap/js/bootstrap.min.js +6 -0
  32. data/app/base/public/assets/jquery.js +6 -0
  33. data/app/base/var/db/.gitkeep +0 -0
  34. data/app/base/var/log/.gitkeep +0 -0
  35. data/app/base/var/pid/.gitkeep +0 -0
  36. data/app/database/ActiveRecord.rb +11 -0
  37. data/app/database/DataMapper.rb +11 -0
  38. data/app/database/Sequel.rb +11 -0
  39. data/app/database/mysql.yml +24 -0
  40. data/app/database/postgres.yml +24 -0
  41. data/app/database/sqlite.yml +24 -0
  42. data/app/gemfiles/ActiveRecord.rb +1 -0
  43. data/app/gemfiles/BlueCloth.rb +1 -0
  44. data/app/gemfiles/DataMapper.rb +1 -0
  45. data/app/gemfiles/FastCGI.rb +1 -0
  46. data/app/gemfiles/Puma.rb +1 -0
  47. data/app/gemfiles/RDiscount.rb +1 -0
  48. data/app/gemfiles/RDoc.rb +1 -0
  49. data/app/gemfiles/RedCloth.rb +1 -0
  50. data/app/gemfiles/WEBrick.rb +1 -0
  51. data/app/gemfiles/WikiCloth.rb +1 -0
  52. data/app/gemfiles/mysql/ActiveRecord.rb +1 -0
  53. data/app/gemfiles/mysql/DataMapper.rb +1 -0
  54. data/app/gemfiles/mysql/Sequel.rb +1 -0
  55. data/app/gemfiles/postgres/ActiveRecord.rb +1 -0
  56. data/app/gemfiles/postgres/DataMapper.rb +1 -0
  57. data/app/gemfiles/postgres/Sequel.rb +1 -0
  58. data/app/gemfiles/sqlite/ActiveRecord.rb +1 -0
  59. data/app/gemfiles/sqlite/DataMapper.rb +1 -0
  60. data/app/gemfiles/sqlite/Sequel.rb +1 -0
  61. data/app/layouts/ERB/layout.erb +56 -0
  62. data/app/layouts/Erubis/layout.erb +56 -0
  63. data/app/layouts/Haml/layout.haml +38 -0
  64. data/app/layouts/Slim/layout.slim +38 -0
  65. data/app/migrations/ActiveRecord.erb +51 -0
  66. data/app/migrations/DataMapper.erb +61 -0
  67. data/app/migrations/Sequel.erb +54 -0
  68. data/app/migrations/tracking_table/ActiveRecord.rb +19 -0
  69. data/app/migrations/tracking_table/DataMapper.rb +26 -0
  70. data/app/migrations/tracking_table/Sequel.rb +18 -0
  71. data/app/rakefiles/ActiveRecord.rb +0 -0
  72. data/app/rakefiles/DataMapper.rb +1 -0
  73. data/app/rakefiles/Sequel.rb +0 -0
  74. data/app/rakefiles/Specular.rb +1 -0
  75. data/app/specfiles/Specular.erb +7 -0
  76. data/bin/my_enginery +235 -0
  77. data/lib/enginery.rb +23 -0
  78. data/lib/enginery/cli.rb +44 -0
  79. data/lib/enginery/configurator.rb +139 -0
  80. data/lib/enginery/delete.rb +116 -0
  81. data/lib/enginery/enginery.rb +41 -0
  82. data/lib/enginery/generator.rb +325 -0
  83. data/lib/enginery/helpers/app.rb +83 -0
  84. data/lib/enginery/helpers/generic.rb +145 -0
  85. data/lib/enginery/helpers/input.rb +123 -0
  86. data/lib/enginery/helpers/orm.rb +86 -0
  87. data/lib/enginery/helpers/validations.rb +101 -0
  88. data/lib/enginery/migrator.rb +371 -0
  89. data/lib/enginery/rake-tasks/data_mapper.rb +49 -0
  90. data/lib/enginery/rake-tasks/specular.rb +41 -0
  91. data/lib/enginery/registry.rb +101 -0
  92. data/lib/enginery/usage.rb +66 -0
  93. data/lib/enginery/version.rb +7 -0
  94. data/logo.png +0 -0
  95. data/my_enginery.gemspec +37 -0
  96. data/test/delete/test__admin.rb +49 -0
  97. data/test/delete/test__controller.rb +37 -0
  98. data/test/delete/test__helper.rb +49 -0
  99. data/test/delete/test__migration.rb +27 -0
  100. data/test/delete/test__model.rb +35 -0
  101. data/test/delete/test__route.rb +35 -0
  102. data/test/delete/test__spec.rb +59 -0
  103. data/test/delete/test__view.rb +51 -0
  104. data/test/generator/test__admin.rb +39 -0
  105. data/test/generator/test__controller.rb +123 -0
  106. data/test/generator/test__helper.rb +56 -0
  107. data/test/generator/test__model.rb +206 -0
  108. data/test/generator/test__project.rb +81 -0
  109. data/test/generator/test__route.rb +110 -0
  110. data/test/generator/test__spec.rb +56 -0
  111. data/test/generator/test__view.rb +85 -0
  112. data/test/migrator/test__auto_generation.rb +41 -0
  113. data/test/migrator/test__manual_generation.rb +59 -0
  114. data/test/migrator/test__migrations.rb +139 -0
  115. data/test/sandbox/.gitkeep +0 -0
  116. data/test/setup.rb +29 -0
  117. data/test/support/spec_helpers.rb +151 -0
  118. metadata +392 -0
@@ -0,0 +1,116 @@
1
+ module Enginery
2
+ class Delete
3
+ include Helpers
4
+ attr_reader :dst_root
5
+
6
+ def initialize dst_root
7
+ @dst_root = dst_root
8
+ end
9
+
10
+ def controller name
11
+
12
+ controller_path, controller_object = valid_controller?(name)
13
+
14
+ routes_by_controller(name).each {|r| route(name, r)}
15
+ helper(name)
16
+
17
+ if File.exists?(controller_path)
18
+ o
19
+ o '*** Removing "%s" folder ***' % unrootify(controller_path)
20
+ FileUtils.rm_r(controller_path)
21
+ end
22
+
23
+ file = controller_path + CONTROLLER_SUFFIX
24
+ if File.exists?(file)
25
+ o '*** Deleting "%s" file ***' % unrootify(file)
26
+ o
27
+ FileUtils.rm(file)
28
+ end
29
+
30
+ end
31
+
32
+ def rear_controller model
33
+
34
+ file = dst_path(:rear_controllers, class_to_route(model) + ADMIN_SUFFIX)
35
+
36
+ if File.exists?(file)
37
+ o
38
+ o '*** Deleting "%s" file ***' % unrootify(file)
39
+ FileUtils.rm(file)
40
+ end
41
+ end
42
+
43
+ def route controller, name
44
+ file, * = valid_route?(controller, name)
45
+ if File.exists?(file)
46
+ o '*** Deleting "%s" file ***' % unrootify(file)
47
+ o
48
+ FileUtils.rm(file)
49
+ end
50
+ view controller, name
51
+ spec controller, name
52
+ end
53
+
54
+ def view controller, route
55
+ _, ctrl = valid_controller?(controller)
56
+ path, ext = view_setups_for(ctrl, route)
57
+ file = File.join(path, route + ext)
58
+
59
+ return unless File.exists?(file)
60
+ o '*** Deleting "%s" file ***' % unrootify(file)
61
+ o
62
+ FileUtils.rm(file)
63
+ end
64
+
65
+ def spec controller, route
66
+ _, controller_object = valid_controller?(controller)
67
+ _, route = valid_route?(controller, route)
68
+
69
+ path = dst_path(:specs, class_to_route(controller), '/')
70
+ file = path + route + SPEC_SUFFIX
71
+ return unless File.exists?(file)
72
+ o '*** Deleting "%s" file ***' % unrootify(file)
73
+ o
74
+ FileUtils.rm(file)
75
+ end
76
+
77
+ def helper controller
78
+ _, ctrl = valid_controller?(controller)
79
+ file = dst_path(:helpers, class_to_route(controller) + HELPER_SUFFIX)
80
+ return unless File.exists?(file)
81
+ o '*** Deleting "%s" file ***' % unrootify(file)
82
+ o
83
+ FileUtils.rm(file)
84
+ end
85
+
86
+ def model name
87
+ name.nil? || name.empty? && fail("Please provide model name")
88
+
89
+ file = dst_path(:models, class_to_route(name) + MODEL_SUFFIX)
90
+ if File.exists?(file)
91
+ o '*** Deleting "%s" file ***' % unrootify(file)
92
+ o
93
+ FileUtils.rm(file)
94
+ end
95
+ migrations_by_model(name).each do |m|
96
+ migration m.split('.').first
97
+ end
98
+ rear_controller(name)
99
+ true
100
+ end
101
+
102
+ def migration name
103
+ name.nil? || name.empty? && fail("Please provide migration name")
104
+ Dir[dst_path(:migrations, '**/%s.*%s' % [name, MIGRATION_SUFFIX])].each do |file|
105
+ load_file file
106
+ if defined?(DataMapper::Migration) && Migrator::MigratorInstance.instance_of?(DataMapper::Migration)
107
+ Migrator.new(dst_root).update_model_file(Migrator::MigratorContext, :down)
108
+ end
109
+ o '*** Deleting "%s" file ***' % unrootify(file)
110
+ o
111
+ FileUtils.rm(file)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,41 @@
1
+ module Enginery
2
+ ENVIRONMENTS = [:development, :test, :production].freeze
3
+ DEFAULT_TEST_FRAMEWORK = :Specular
4
+ DEFAULT_DB_TYPE = :sqlite
5
+ INDENT = (' ' * 2).freeze
6
+ KNOWN_WEB_SERVERS = %w[
7
+ WEBrick
8
+ Thin
9
+ Unicorn
10
+ Rainbows
11
+ Puma
12
+ Reel
13
+ Mongrel
14
+ FastCGI
15
+ SCGI
16
+ ].map(&:to_sym).freeze
17
+
18
+ # using z_ prefix to make sure tracking table shown last
19
+ # when some database management tools used.
20
+ TRACKING_TABLE = :z_enginery_migrator_tracks
21
+ TRACKING_TABLE__COLUMNS = [:migration, :performed_at, :vector].freeze
22
+ TRACKING_TABLE__INDEXES = [:migration].freeze
23
+
24
+ CONTROLLER_SUFFIX = '_controller.rb'.freeze
25
+ ROUTE_SUFFIX = '.rb'.freeze
26
+ SPEC_SUFFIX = '_spec.rb'.freeze
27
+ MODEL_SUFFIX = '.rb'.freeze
28
+ MIGRATION_SUFFIX = '.rb'.freeze
29
+ HELPER_SUFFIX = '.rb'.freeze
30
+ ADMIN_SUFFIX = '.rb'.freeze # suffix for Rear controllers
31
+
32
+ ORM_IDENTITY_METHODS = {
33
+ ActiveRecord: [:connection, :columns, :reflect_on_all_associations].freeze,
34
+ DataMapper: [:repository, :properties, :relationships].freeze,
35
+ Sequel: [:db_schema, :columns, :dataset].freeze
36
+ }.freeze
37
+ ORM_MATCHERS = Hash[ORM_IDENTITY_METHODS.keys.zip(ORM_IDENTITY_METHODS.keys.map{|x| Regexp.new(x.to_s, 'i')})]
38
+ ORM_ASSOCIATIONS = [:belongs_to, :has_one, :has_many, :has_and_belongs_to_many].freeze
39
+
40
+ EXECUTABLE = File.expand_path('../../../bin/enginery', __FILE__).freeze
41
+ end
@@ -0,0 +1,325 @@
1
+ module Enginery
2
+ class Generator
3
+
4
+ include Helpers
5
+ attr_reader :dst_root, :setups
6
+
7
+ def initialize dst_root, setups = {}
8
+ @dst_root, @setups = dst_root, setups
9
+ end
10
+
11
+ def generate_project name = nil
12
+ name = name.to_s
13
+
14
+ if name.empty?
15
+ name = '.'
16
+ else
17
+ name =~ /\.\.|\// && fail('Project name can not contain "/" nor ".."')
18
+ @dst_root, @dst_path_map = File.join(@dst_root, name, ''), nil
19
+ end
20
+
21
+ Dir[dst_path(:root, '*')].any? && fail('"%s" should be a empty folder' % dst_path.root)
22
+
23
+ o
24
+ o '=== Generating "%s" project ===' % name
25
+
26
+ folders, files = Dir[src_path(:base, '**/{*,.[a-z]*}')].partition do |entry|
27
+ File.directory?(entry)
28
+ end
29
+
30
+ FileUtils.mkdir_p dst_path.root
31
+ o "#{name}/"
32
+ folders.each do |folder|
33
+ path = unrootify(folder, src_path.base)
34
+ o " D #{path}/"
35
+ FileUtils.mkdir_p dst_path(:root, path)
36
+ end
37
+
38
+ files.reject {|f| File.basename(f) == '.gitkeep'}.each do |file|
39
+ path = unrootify(file, src_path.base)
40
+ o " F #{path}"
41
+ FileUtils.cp file, dst_path(:root, path)
42
+ end
43
+
44
+ Configurator.new dst_root, setups do
45
+ update_gemfile
46
+ update_rakefile
47
+ update_boot_rb
48
+ update_config_yml
49
+ update_database_rb
50
+ update_database_yml
51
+ end
52
+ name
53
+ end
54
+
55
+ def generate_controller name
56
+
57
+ name.nil? || name.empty? && fail("Please provide controller name")
58
+ before, ctrl_name, after = namespace_to_source_code(name)
59
+
60
+ source_code, i = [], INDENT * before.size
61
+ before.each {|s| source_code << s}
62
+ source_code << "#{i}class #{ctrl_name} < E"
63
+
64
+ (@setups[:include] || []).each do |mdl|
65
+ source_code << "#{i + INDENT}include #{mdl}"
66
+ end
67
+
68
+ source_code << "#{i + INDENT}include %sHelpers if defined?(%sHelpers)" % [ctrl_name, ctrl_name]
69
+ source_code << "#{i + INDENT}# controller-wide setups"
70
+
71
+ if route = setups[:route]
72
+ source_code << "#{i + INDENT}map '#{route}'"
73
+ end
74
+ if engine = setups[:engine]
75
+ source_code << "#{i + INDENT}engine :#{engine}"
76
+ Configurator.new(dst_root, engine: engine).update_gemfile
77
+ end
78
+ if format = setups[:format]
79
+ source_code << "#{i + INDENT}format '#{format}'"
80
+ end
81
+ source_code << INDENT
82
+
83
+ source_code << "#{i}end"
84
+ after.each {|s| source_code << s}
85
+
86
+ path = dst_path(:controllers, class_to_route(name))
87
+ file = path + CONTROLLER_SUFFIX
88
+ File.exists?(file) && fail('"%s" controller already exists' % name)
89
+ o
90
+ o '=== Generating "%s" controller ===' % name
91
+ o '*** Creating "%s/" ***' % unrootify(path)
92
+ FileUtils.mkdir_p(path)
93
+
94
+ write_file file, source_code.join("\n")
95
+ output_source_code source_code
96
+ ctrl_name
97
+ end
98
+
99
+ def generate_route ctrl_name, name
100
+
101
+ action_file, action = valid_route?(ctrl_name, name)
102
+
103
+ File.exists?(action_file) && fail('"%s" route already exists' % name)
104
+
105
+ before, ctrl_name, after = namespace_to_source_code(ctrl_name)
106
+
107
+ source_code, i = [], ' ' * before.size
108
+ before.each {|s| source_code << s}
109
+ source_code << "#{i}class #{ctrl_name}"
110
+ source_code << "#{i + INDENT}# action-specific setups"
111
+ source_code << ''
112
+
113
+ if format = setups[:format]
114
+ source_code << "#{i + INDENT}format_for :#{action}, '#{format}'"
115
+ end
116
+ if setups.reject {|k,v| k == :route}.any?
117
+ source_code << "#{i + INDENT}before :#{action} do"
118
+ if engine = setups[:engine]
119
+ source_code << "#{i + INDENT*2}engine :#{engine}"
120
+ Configurator.new(dst_root, engine: engine).update_gemfile
121
+ end
122
+ source_code << "#{i + INDENT}end"
123
+ source_code << ""
124
+ end
125
+
126
+ source_code << (i + INDENT + "def #{action}")
127
+ action_source_code = ["render"]
128
+ if block_given?
129
+ action_source_code = yield
130
+ action_source_code.is_a?(Array) || action_source_code = [action_source_code]
131
+ end
132
+ action_source_code.each do |line|
133
+ source_code << (i + INDENT*2 + line.to_s)
134
+ end
135
+ source_code << (i + INDENT + "end")
136
+ source_code << ''
137
+
138
+ source_code << "#{i}end"
139
+ after.each {|s| source_code << s}
140
+
141
+ o
142
+ o '=== Generating "%s" route ===' % name
143
+
144
+ write_file action_file, source_code.join("\n")
145
+ output_source_code source_code
146
+ action
147
+ end
148
+
149
+ def generate_helper ctrl_name
150
+ o
151
+ o '=== Generating helper file for "%s" controller ===' % ctrl_name
152
+
153
+ _, ctrl = valid_controller?(ctrl_name)
154
+ file = dst_path(:helpers, class_to_route(ctrl_name) + HELPER_SUFFIX)
155
+ path = File.dirname(file)
156
+
157
+ if File.exists?(path)
158
+ File.directory?(path) || fail('"%s" should be a directory' % unrootify(path))
159
+ else
160
+ o '*** Creating "%s/" ***' % unrootify(path)
161
+ FileUtils.mkdir_p(path)
162
+ end
163
+
164
+ if File.exists?(file)
165
+ File.file?(file) || fail('"%s" should be a file' % unrootify(file))
166
+ o('*** WARN: overwriting "%s" file ***' % unrootify(file))
167
+ else
168
+ o '*** Creating "%s" ***' % unrootify(file)
169
+ end
170
+
171
+ before, helper_name, after = namespace_to_source_code(ctrl_name)
172
+
173
+ source_code, i = [], INDENT * before.size
174
+ before.each {|s| source_code << s}
175
+ source_code << "#{i}module #{helper_name}Helpers"
176
+
177
+ source_code << "#{i + INDENT}include Helpers if defined?(Helpers)"
178
+ source_code << ""
179
+ source_code << "#{i + INDENT}# helper methods for %s controller" % ctrl_name
180
+ source_code << INDENT
181
+
182
+ source_code << "#{i}end"
183
+ after.each {|s| source_code << s}
184
+
185
+ write_file file, source_code.join("\n")
186
+ output_source_code source_code
187
+ file
188
+ end
189
+
190
+ def generate_view ctrl_name, name
191
+
192
+ _, action = valid_route?(ctrl_name, name)
193
+ _, ctrl = valid_controller?(ctrl_name)
194
+ path, ext = view_setups_for(ctrl, action)
195
+
196
+ o
197
+ o '=== Generating "%s" view ===' % name
198
+ if File.exists?(path)
199
+ File.directory?(path) || fail('"%s" should be a directory' % unrootify(path))
200
+ else
201
+ o '*** Creating "%s/" ***' % unrootify(path)
202
+ FileUtils.mkdir_p(path)
203
+ end
204
+ file = File.join(path, action + ext)
205
+ if File.exists?(file)
206
+ File.file?(file) || fail('"%s" should be a file' % unrootify(file))
207
+ o('*** WARN: overwriting "%s" file ***' % unrootify(file))
208
+ else
209
+ o '*** Creating "%s" ***' % unrootify(file)
210
+ end
211
+ File.open(file, 'w') {}
212
+ file
213
+ end
214
+
215
+ def generate_model name
216
+
217
+ name.nil? || name.empty? && fail("Please provide model name")
218
+ before, model_name, after = namespace_to_source_code(name)
219
+
220
+ superclass, insertions = '', []
221
+ if orm = valid_orm?(setups[:orm] || Cfg[:orm])
222
+ orm == :ActiveRecord && superclass = ' < ActiveRecord::Base'
223
+ orm == :Sequel && superclass = ' < Sequel::Model'
224
+ orm == :DataMapper && insertions << 'include DataMapper::Resource'
225
+
226
+ (@setups[:include] || []).each do |mdl|
227
+ insertions << "include #{mdl}"
228
+ end
229
+ insertions << ''
230
+
231
+ orm == :DataMapper && insertions << 'property :id, Serial'
232
+ insertions << ''
233
+ send(orm.to_s.downcase + '_associations', @setups).each do |a|
234
+ insertions << a
235
+ end
236
+ end
237
+ insertions << ''
238
+
239
+ source_code, i = [], INDENT * before.size
240
+ before.each {|s| source_code << s}
241
+ source_code << "#{i}class #{model_name + superclass}"
242
+
243
+ insertions.each do |line|
244
+ source_code << (i + INDENT + line.to_s)
245
+ end
246
+
247
+ source_code << "#{i}end"
248
+ after.each {|s| source_code << s}
249
+ source_code = source_code.join("\n")
250
+
251
+ file = dst_path(:models, class_to_route(name) + '.rb')
252
+ File.exists?(file) && fail('"%s" file already exists' % unrootify(file))
253
+
254
+ o
255
+ o '=== Generating "%s" model ===' % name
256
+ dir = File.dirname(file)
257
+ if File.exists?(dir)
258
+ File.directory?(dir) || fail("#{unrootify dir} should be a directory")
259
+ else
260
+ o '*** Creating "%s/" ***' % unrootify(dir)
261
+ FileUtils.mkdir_p(dir)
262
+ end
263
+
264
+ write_file file, source_code
265
+ output_source_code source_code.split("\n")
266
+ model_name
267
+ end
268
+
269
+ def generate_rear_controller model
270
+
271
+ model.nil? || model.empty? && fail('Please provide the model name to build controller for')
272
+ model_exists?(model) || fail('Seems "%s" model does not exists' % model)
273
+
274
+ source_code = []
275
+ source_code << "defined?(Rear) && Rear.register('#{model}') do"
276
+ source_code << " # Rear setups for #{model} model"
277
+ source_code << " # Details at https://github.com/espresso/rear"
278
+ source_code << " "
279
+ source_code << " "
280
+ source_code << "end"
281
+ source_code << ""
282
+
283
+ path = dst_path(:rear_controllers, class_to_route(model))
284
+ file = path + ADMIN_SUFFIX
285
+ File.exists?(file) && fail('A Rear controller for "%s" model already exists' % model)
286
+ o
287
+ o '=== Generating Rear controller for "%s" model ===' % model
288
+ FileUtils.mkdir_p(File.dirname(path))
289
+
290
+ write_file file, source_code.join("\n")
291
+ output_source_code source_code
292
+ model
293
+ end
294
+
295
+ def generate_spec ctrl_name, name
296
+
297
+ context = {}
298
+ _, context[:controller] = valid_controller?(ctrl_name)
299
+ _, context[:action] = valid_route?(ctrl_name, name)
300
+ context[:spec] = [ctrl_name, context[:action]]*'#'
301
+
302
+ o
303
+ o '=== Generating "%s#%s" spec ===' % [ctrl_name, name]
304
+ path = dst_path(:specs, class_to_route(ctrl_name), '/')
305
+ if File.exists?(path)
306
+ File.directory?(path) || fail("#{path} should be a directory")
307
+ else
308
+ o '*** Creating "%s" ***' % unrootify(path)
309
+ FileUtils.mkdir_p(path)
310
+ end
311
+
312
+ file = path + context[:action] + SPEC_SUFFIX
313
+ File.exists?(file) && o('*** WARN: overwriting "%s" file ***' % unrootify(file))
314
+
315
+ test_framework = setups[:test_framework] || DEFAULT_TEST_FRAMEWORK
316
+ engine = Tenjin::Engine.new(path: [src_path.specfiles], cache: false)
317
+ source_code = engine.render(test_framework.to_s + '.erb', context)
318
+
319
+ write_file file, source_code
320
+ output_source_code source_code.split("\n")
321
+ file
322
+ end
323
+
324
+ end
325
+ end