adaptation 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG +1 -0
  2. data/README +90 -0
  3. data/bin/about +5 -0
  4. data/bin/adaptation +19 -0
  5. data/bin/destroy +5 -0
  6. data/bin/generate +5 -0
  7. data/bin/mom +8 -0
  8. data/bin/subscribe +8 -0
  9. data/configs/boot.rb +10 -0
  10. data/configs/databases/mysql.yml +48 -0
  11. data/configs/empty.log +0 -0
  12. data/configs/mom.yml +8 -0
  13. data/dispatches/dispatch.rb +8 -0
  14. data/dispatches/publish.rb +11 -0
  15. data/doc/README_FOR_APP +2 -0
  16. data/fresh_rakefile +10 -0
  17. data/helpers/publish.rb +24 -0
  18. data/helpers/test_helper.rb +6 -0
  19. data/lib/adaptation/adaptor.rb +32 -0
  20. data/lib/adaptation/base.rb +70 -0
  21. data/lib/adaptation/message.rb +328 -0
  22. data/lib/adaptation/mom.rb +70 -0
  23. data/lib/adaptation/oapdaemon.rb +38 -0
  24. data/lib/adaptation/test/test_help.rb +282 -0
  25. data/lib/adaptation/version.rb +9 -0
  26. data/lib/adaptation.rb +5 -0
  27. data/lib/commands/about.rb +3 -0
  28. data/lib/commands/destroy.rb +6 -0
  29. data/lib/commands/generate.rb +6 -0
  30. data/lib/commands/mom.rb +8 -0
  31. data/lib/commands/subscribe.rb +11 -0
  32. data/lib/commands.rb +17 -0
  33. data/lib/rails_generator/base.rb +262 -0
  34. data/lib/rails_generator/commands.rb +582 -0
  35. data/lib/rails_generator/generated_attribute.rb +42 -0
  36. data/lib/rails_generator/generators/applications/app/USAGE +13 -0
  37. data/lib/rails_generator/generators/applications/app/app_generator.rb +133 -0
  38. data/lib/rails_generator/generators/components/adaptor/USAGE +25 -0
  39. data/lib/rails_generator/generators/components/adaptor/adaptor_generator.rb +21 -0
  40. data/lib/rails_generator/generators/components/adaptor/templates/adaptor.rb +6 -0
  41. data/lib/rails_generator/generators/components/adaptor/templates/functional_test.rb +16 -0
  42. data/lib/rails_generator/generators/components/message/USAGE +16 -0
  43. data/lib/rails_generator/generators/components/message/message_generator.rb +28 -0
  44. data/lib/rails_generator/generators/components/message/templates/fixtures.xml +3 -0
  45. data/lib/rails_generator/generators/components/message/templates/message.rb +2 -0
  46. data/lib/rails_generator/generators/components/message/templates/unit_test.rb +25 -0
  47. data/lib/rails_generator/generators/components/model/USAGE +26 -0
  48. data/lib/rails_generator/generators/components/model/model_generator.rb +38 -0
  49. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -0
  50. data/lib/rails_generator/generators/components/model/templates/migration.rb +13 -0
  51. data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
  52. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +10 -0
  53. data/lib/rails_generator/lookup.rb +209 -0
  54. data/lib/rails_generator/manifest.rb +53 -0
  55. data/lib/rails_generator/options.rb +143 -0
  56. data/lib/rails_generator/scripts/destroy.rb +7 -0
  57. data/lib/rails_generator/scripts/generate.rb +7 -0
  58. data/lib/rails_generator/scripts/update.rb +12 -0
  59. data/lib/rails_generator/scripts.rb +85 -0
  60. data/lib/rails_generator/simple_logger.rb +46 -0
  61. data/lib/rails_generator/spec.rb +44 -0
  62. data/lib/rails_generator.rb +43 -0
  63. data/lib/ruby_version_check.rb +17 -0
  64. metadata +142 -0
@@ -0,0 +1,582 @@
1
+ require 'delegate'
2
+ require 'optparse'
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+ require 'erb'
6
+
7
+ module Rails
8
+ module Generator
9
+ module Commands
10
+ # Here's a convenient way to get a handle on generator commands.
11
+ # Command.instance('destroy', my_generator) instantiates a Destroy
12
+ # delegate of my_generator ready to do your dirty work.
13
+ def self.instance(command, generator)
14
+ const_get(command.to_s.camelize).new(generator)
15
+
16
+ end
17
+
18
+ # Even more convenient access to commands. Include Commands in
19
+ # the generator Base class to get a nice #command instance method
20
+ # which returns a delegate for the requested command.
21
+ def self.included(base)
22
+ base.send(:define_method, :command) do |command|
23
+ Commands.instance(command, self)
24
+ end
25
+ end
26
+
27
+
28
+ # Generator commands delegate Rails::Generator::Base and implement
29
+ # a standard set of actions. Their behavior is defined by the way
30
+ # they respond to these actions: Create brings life; Destroy brings
31
+ # death; List passively observes.
32
+ #
33
+ # Commands are invoked by replaying (or rewinding) the generator's
34
+ # manifest of actions. See Rails::Generator::Manifest and
35
+ # Rails::Generator::Base#manifest method that generator subclasses
36
+ # are required to override.
37
+ #
38
+ # Commands allows generators to "plug in" invocation behavior, which
39
+ # corresponds to the GoF Strategy pattern.
40
+ class Base < DelegateClass(Rails::Generator::Base)
41
+ # Replay action manifest. RewindBase subclass rewinds manifest.
42
+ def invoke!
43
+ manifest.replay(self)
44
+ end
45
+
46
+ def dependency(generator_name, args, runtime_options = {})
47
+ logger.dependency(generator_name) do
48
+ self.class.new(instance(generator_name, args, full_options(runtime_options))).invoke!
49
+ end
50
+ end
51
+
52
+ # Does nothing for all commands except Create.
53
+ def class_collisions(*class_names)
54
+ end
55
+
56
+ # Does nothing for all commands except Create.
57
+ def readme(*args)
58
+ end
59
+
60
+ protected
61
+ def migration_directory(relative_path)
62
+ directory(@migration_directory = relative_path)
63
+ end
64
+
65
+ def existing_migrations(file_name)
66
+ Dir.glob("#{@migration_directory}/[0-9]*_*.rb").grep(/[0-9]+_#{file_name}.rb$/)
67
+ end
68
+
69
+ def migration_exists?(file_name)
70
+ not existing_migrations(file_name).empty?
71
+ end
72
+
73
+ def current_migration_number
74
+ Dir.glob("#{@migration_directory}/[0-9]*.rb").inject(0) do |max, file_path|
75
+ n = File.basename(file_path).split('_', 2).first.to_i
76
+ if n > max then n else max end
77
+ end
78
+ end
79
+
80
+ def next_migration_number
81
+ current_migration_number + 1
82
+ end
83
+
84
+ def next_migration_string(padding = 3)
85
+ "%.#{padding}d" % next_migration_number
86
+ end
87
+
88
+ def gsub_file(relative_destination, regexp, *args, &block)
89
+ path = destination_path(relative_destination)
90
+ content = File.read(path).gsub(regexp, *args, &block)
91
+ File.open(path, 'wb') { |file| file.write(content) }
92
+ end
93
+
94
+ private
95
+ # Ask the user interactively whether to force collision.
96
+ def force_file_collision?(destination, src, dst, file_options = {}, &block)
97
+ $stdout.print "overwrite #{destination}? [Ynaqd] "
98
+ case $stdin.gets
99
+ when /d/i
100
+ Tempfile.open(File.basename(destination), File.dirname(dst)) do |temp|
101
+ temp.write render_file(src, file_options, &block)
102
+ temp.rewind
103
+ $stdout.puts `#{diff_cmd} #{dst} #{temp.path}`
104
+ end
105
+ puts "retrying"
106
+ raise 'retry diff'
107
+ when /a/i
108
+ $stdout.puts "forcing #{spec.name}"
109
+ options[:collision] = :force
110
+ when /q/i
111
+ $stdout.puts "aborting #{spec.name}"
112
+ raise SystemExit
113
+ when /n/i then :skip
114
+ else :force
115
+ end
116
+ rescue
117
+ retry
118
+ end
119
+
120
+ def diff_cmd
121
+ ENV['RAILS_DIFF'] || 'diff -u'
122
+ end
123
+
124
+ def render_template_part(template_options)
125
+ # Getting Sandbox to evaluate part template in it
126
+ part_binding = template_options[:sandbox].call.sandbox_binding
127
+ part_rel_path = template_options[:insert]
128
+ part_path = source_path(part_rel_path)
129
+
130
+ # Render inner template within Sandbox binding
131
+ rendered_part = ERB.new(File.readlines(part_path).join, nil, '-').result(part_binding)
132
+ begin_mark = template_part_mark(template_options[:begin_mark], template_options[:mark_id])
133
+ end_mark = template_part_mark(template_options[:end_mark], template_options[:mark_id])
134
+ begin_mark + rendered_part + end_mark
135
+ end
136
+
137
+ def template_part_mark(name, id)
138
+ "<!--[#{name}:#{id}]-->\n"
139
+ end
140
+ end
141
+
142
+ # Base class for commands which handle generator actions in reverse, such as Destroy.
143
+ class RewindBase < Base
144
+ # Rewind action manifest.
145
+ def invoke!
146
+ manifest.rewind(self)
147
+ end
148
+ end
149
+
150
+
151
+ # Create is the premier generator command. It copies files, creates
152
+ # directories, renders templates, and more.
153
+ class Create < Base
154
+
155
+ # Check whether the given class names are already taken by
156
+ # Ruby or Rails. In the future, expand to check other namespaces
157
+ # such as the rest of the user's app.
158
+ def class_collisions(*class_names)
159
+ class_names.flatten.each do |class_name|
160
+ # Convert to string to allow symbol arguments.
161
+ class_name = class_name.to_s
162
+
163
+ # Skip empty strings.
164
+ next if class_name.strip.empty?
165
+
166
+ # Split the class from its module nesting.
167
+ nesting = class_name.split('::')
168
+ name = nesting.pop
169
+
170
+ # Extract the last Module in the nesting.
171
+ last = nesting.inject(Object) { |last, nest|
172
+ break unless last.const_defined?(nest)
173
+ last.const_get(nest)
174
+ }
175
+
176
+ # If the last Module exists, check whether the given
177
+ # class exists and raise a collision if so.
178
+ if last and last.const_defined?(name.camelize)
179
+ raise_class_collision(class_name)
180
+ end
181
+ end
182
+ end
183
+
184
+ # Copy a file from source to destination with collision checking.
185
+ #
186
+ # The file_options hash accepts :chmod and :shebang and :collision options.
187
+ # :chmod sets the permissions of the destination file:
188
+ # file 'config/empty.log', 'log/test.log', :chmod => 0664
189
+ # :shebang sets the #!/usr/bin/ruby line for scripts
190
+ # file 'bin/generate.rb', 'script/generate', :chmod => 0755, :shebang => '/usr/bin/env ruby'
191
+ # :collision sets the collision option only for the destination file:
192
+ # file 'settings/server.yml', 'config/server.yml', :collision => :skip
193
+ #
194
+ # Collisions are handled by checking whether the destination file
195
+ # exists and either skipping the file, forcing overwrite, or asking
196
+ # the user what to do.
197
+ def file(relative_source, relative_destination, file_options = {}, &block)
198
+ # Determine full paths for source and destination files.
199
+ source = source_path(relative_source)
200
+ destination = destination_path(relative_destination)
201
+ destination_exists = File.exists?(destination)
202
+
203
+ # If source and destination are identical then we're done.
204
+ if destination_exists and identical?(source, destination, &block)
205
+ return logger.identical(relative_destination)
206
+ end
207
+
208
+ # Check for and resolve file collisions.
209
+ if destination_exists
210
+
211
+ # Make a choice whether to overwrite the file. :force and
212
+ # :skip already have their mind made up, but give :ask a shot.
213
+ choice = case (file_options[:collision] || options[:collision]).to_sym #|| :ask
214
+ when :ask then force_file_collision?(relative_destination, source, destination, file_options, &block)
215
+ when :force then :force
216
+ when :skip then :skip
217
+ else raise "Invalid collision option: #{options[:collision].inspect}"
218
+ end
219
+
220
+ # Take action based on our choice. Bail out if we chose to
221
+ # skip the file; otherwise, log our transgression and continue.
222
+ case choice
223
+ when :force then logger.force(relative_destination)
224
+ when :skip then return(logger.skip(relative_destination))
225
+ else raise "Invalid collision choice: #{choice}.inspect"
226
+ end
227
+
228
+ # File doesn't exist so log its unbesmirched creation.
229
+ else
230
+ logger.create relative_destination
231
+ end
232
+
233
+ # If we're pretending, back off now.
234
+ return if options[:pretend]
235
+
236
+ # Write destination file with optional shebang. Yield for content
237
+ # if block given so templaters may render the source file. If a
238
+ # shebang is requested, replace the existing shebang or insert a
239
+ # new one.
240
+ File.open(destination, 'wb') do |dest|
241
+ dest.write render_file(source, file_options, &block)
242
+ end
243
+
244
+ # Optionally change permissions.
245
+ if file_options[:chmod]
246
+ FileUtils.chmod(file_options[:chmod], destination)
247
+ end
248
+
249
+ # Optionally add file to subversion
250
+ system("svn add #{destination}") if options[:svn]
251
+ end
252
+
253
+ # Checks if the source and the destination file are identical. If
254
+ # passed a block then the source file is a template that needs to first
255
+ # be evaluated before being compared to the destination.
256
+ def identical?(source, destination, &block)
257
+ return false if File.directory? destination
258
+ source = block_given? ? File.open(source) {|sf| yield(sf)} : IO.read(source)
259
+ destination = IO.read(destination)
260
+ source == destination
261
+ end
262
+
263
+ # Generate a file for a Rails application using an ERuby template.
264
+ # Looks up and evalutes a template by name and writes the result.
265
+ #
266
+ # The ERB template uses explicit trim mode to best control the
267
+ # proliferation of whitespace in generated code. <%- trims leading
268
+ # whitespace; -%> trims trailing whitespace including one newline.
269
+ #
270
+ # A hash of template options may be passed as the last argument.
271
+ # The options accepted by the file are accepted as well as :assigns,
272
+ # a hash of variable bindings. Example:
273
+ # template 'foo', 'bar', :assigns => { :action => 'view' }
274
+ #
275
+ # Template is implemented in terms of file. It calls file with a
276
+ # block which takes a file handle and returns its rendered contents.
277
+ def template(relative_source, relative_destination, template_options = {})
278
+ file(relative_source, relative_destination, template_options) do |file|
279
+ # Evaluate any assignments in a temporary, throwaway binding.
280
+ vars = template_options[:assigns] || {}
281
+ b = binding
282
+ vars.each { |k,v| eval "#{k} = vars[:#{k}] || vars['#{k}']", b }
283
+
284
+ # Render the source file with the temporary binding.
285
+ ERB.new(file.read, nil, '-').result(b)
286
+ end
287
+ end
288
+
289
+ def complex_template(relative_source, relative_destination, template_options = {})
290
+ options = template_options.dup
291
+ options[:assigns] ||= {}
292
+ options[:assigns]['template_for_inclusion'] = render_template_part(template_options)
293
+ template(relative_source, relative_destination, options)
294
+ end
295
+
296
+ # Create a directory including any missing parent directories.
297
+ # Always directories which exist.
298
+ def directory(relative_path)
299
+ path = destination_path(relative_path)
300
+ if File.exists?(path)
301
+ logger.exists relative_path
302
+ else
303
+ logger.create relative_path
304
+ unless options[:pretend]
305
+ FileUtils.mkdir_p(path)
306
+
307
+ # Subversion doesn't do path adds, so we need to add
308
+ # each directory individually.
309
+ # So stack up the directory tree and add the paths to
310
+ # subversion in order without recursion.
311
+ if options[:svn]
312
+ stack=[relative_path]
313
+ until File.dirname(stack.last) == stack.last # dirname('.') == '.'
314
+ stack.push File.dirname(stack.last)
315
+ end
316
+ stack.reverse_each do |rel_path|
317
+ svn_path = destination_path(rel_path)
318
+ system("svn add -N #{svn_path}") unless File.directory?(File.join(svn_path, '.svn'))
319
+ end
320
+ end
321
+ end
322
+ end
323
+ end
324
+
325
+ # Display a README.
326
+ def readme(*relative_sources)
327
+ relative_sources.flatten.each do |relative_source|
328
+ logger.readme relative_source
329
+ puts File.read(source_path(relative_source)) unless options[:pretend]
330
+ end
331
+ end
332
+
333
+ # When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.
334
+ def migration_template(relative_source, relative_destination, template_options = {})
335
+ migration_directory relative_destination
336
+ migration_file_name = template_options[:migration_file_name] || file_name
337
+ raise "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}" if migration_exists?(migration_file_name)
338
+ template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
339
+ end
340
+
341
+ def route_resources(*resources)
342
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
343
+ sentinel = 'ActionController::Routing::Routes.draw do |map|'
344
+
345
+ logger.route "map.resources #{resource_list}"
346
+ unless options[:pretend]
347
+ gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
348
+ "#{match}\n map.resources #{resource_list}\n"
349
+ end
350
+ end
351
+ end
352
+
353
+ private
354
+ def render_file(path, options = {})
355
+ File.open(path, 'rb') do |file|
356
+ if block_given?
357
+ yield file
358
+ else
359
+ content = ''
360
+ if shebang = options[:shebang]
361
+ content << "#!#{shebang}\n"
362
+ if line = file.gets
363
+ content << "line\n" if line !~ /^#!/
364
+ end
365
+ end
366
+ content << file.read
367
+ end
368
+ end
369
+ end
370
+
371
+ # Raise a usage error with an informative WordNet suggestion.
372
+ # Thanks to Florian Gross (flgr).
373
+ def raise_class_collision(class_name)
374
+ message = <<end_message
375
+ The name '#{class_name}' is reserved by Ruby on Rails.
376
+ Please choose an alternative and run this generator again.
377
+ end_message
378
+ if suggest = find_synonyms(class_name)
379
+ message << "\n Suggestions: \n\n"
380
+ message << suggest.join("\n")
381
+ end
382
+ raise UsageError, message
383
+ end
384
+
385
+ SYNONYM_LOOKUP_URI = "http://wordnet.princeton.edu/cgi-bin/webwn2.0?stage=2&word=%s&posnumber=1&searchtypenumber=2&senses=&showglosses=1"
386
+
387
+ # Look up synonyms on WordNet. Thanks to Florian Gross (flgr).
388
+ def find_synonyms(word)
389
+ require 'open-uri'
390
+ require 'timeout'
391
+ timeout(5) do
392
+ open(SYNONYM_LOOKUP_URI % word) do |stream|
393
+ data = stream.read.gsub("&nbsp;", " ").gsub("<BR>", "")
394
+ data.scan(/^Sense \d+\n.+?\n\n/m)
395
+ end
396
+ end
397
+ rescue Exception
398
+ return nil
399
+ end
400
+ end
401
+
402
+
403
+ # Undo the actions performed by a generator. Rewind the action
404
+ # manifest and attempt to completely erase the results of each action.
405
+ class Destroy < RewindBase
406
+ # Remove a file if it exists and is a file.
407
+ def file(relative_source, relative_destination, file_options = {})
408
+ destination = destination_path(relative_destination)
409
+ if File.exists?(destination)
410
+ logger.rm relative_destination
411
+ unless options[:pretend]
412
+ if options[:svn]
413
+ # If the file has been marked to be added
414
+ # but has not yet been checked in, revert and delete
415
+ if options[:svn][relative_destination]
416
+ system("svn revert #{destination}")
417
+ FileUtils.rm(destination)
418
+ else
419
+ # If the directory is not in the status list, it
420
+ # has no modifications so we can simply remove it
421
+ system("svn rm #{destination}")
422
+ end
423
+ else
424
+ FileUtils.rm(destination)
425
+ end
426
+ end
427
+ else
428
+ logger.missing relative_destination
429
+ return
430
+ end
431
+ end
432
+
433
+ # Templates are deleted just like files and the actions take the
434
+ # same parameters, so simply alias the file method.
435
+ alias_method :template, :file
436
+
437
+ # Remove each directory in the given path from right to left.
438
+ # Remove each subdirectory if it exists and is a directory.
439
+ def directory(relative_path)
440
+ parts = relative_path.split('/')
441
+ until parts.empty?
442
+ partial = File.join(parts)
443
+ path = destination_path(partial)
444
+ if File.exists?(path)
445
+ if Dir[File.join(path, '*')].empty?
446
+ logger.rmdir partial
447
+ unless options[:pretend]
448
+ if options[:svn]
449
+ # If the directory has been marked to be added
450
+ # but has not yet been checked in, revert and delete
451
+ if options[:svn][relative_path]
452
+ system("svn revert #{path}")
453
+ FileUtils.rmdir(path)
454
+ else
455
+ # If the directory is not in the status list, it
456
+ # has no modifications so we can simply remove it
457
+ system("svn rm #{path}")
458
+ end
459
+ else
460
+ FileUtils.rmdir(path)
461
+ end
462
+ end
463
+ else
464
+ logger.notempty partial
465
+ end
466
+ else
467
+ logger.missing partial
468
+ end
469
+ parts.pop
470
+ end
471
+ end
472
+
473
+ def complex_template(*args)
474
+ # nothing should be done here
475
+ end
476
+
477
+ # When deleting a migration, it knows to delete every file named "[0-9]*_#{file_name}".
478
+ def migration_template(relative_source, relative_destination, template_options = {})
479
+ migration_directory relative_destination
480
+
481
+ migration_file_name = template_options[:migration_file_name] || file_name
482
+ unless migration_exists?(migration_file_name)
483
+ puts "There is no migration named #{migration_file_name}"
484
+ return
485
+ end
486
+
487
+
488
+ existing_migrations(migration_file_name).each do |file_path|
489
+ file(relative_source, file_path, template_options)
490
+ end
491
+ end
492
+
493
+ def route_resources(*resources)
494
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
495
+ look_for = "\n map.resources #{resource_list}\n"
496
+ logger.route "map.resources #{resource_list}"
497
+ gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
498
+ end
499
+ end
500
+
501
+
502
+ # List a generator's action manifest.
503
+ class List < Base
504
+ def dependency(generator_name, args, options = {})
505
+ logger.dependency "#{generator_name}(#{args.join(', ')}, #{options.inspect})"
506
+ end
507
+
508
+ def class_collisions(*class_names)
509
+ logger.class_collisions class_names.join(', ')
510
+ end
511
+
512
+ def file(relative_source, relative_destination, options = {})
513
+ logger.file relative_destination
514
+ end
515
+
516
+ def template(relative_source, relative_destination, options = {})
517
+ logger.template relative_destination
518
+ end
519
+
520
+ def complex_template(relative_source, relative_destination, options = {})
521
+ logger.template "#{options[:insert]} inside #{relative_destination}"
522
+ end
523
+
524
+ def directory(relative_path)
525
+ logger.directory "#{destination_path(relative_path)}/"
526
+ end
527
+
528
+ def readme(*args)
529
+ logger.readme args.join(', ')
530
+ end
531
+
532
+ def migration_template(relative_source, relative_destination, options = {})
533
+ migration_directory relative_destination
534
+ logger.migration_template file_name
535
+ end
536
+
537
+ def route_resources(*resources)
538
+ resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
539
+ logger.route "map.resources #{resource_list}"
540
+ end
541
+ end
542
+
543
+ # Update generator's action manifest.
544
+ class Update < Create
545
+ def file(relative_source, relative_destination, options = {})
546
+ # logger.file relative_destination
547
+ end
548
+
549
+ def template(relative_source, relative_destination, options = {})
550
+ # logger.template relative_destination
551
+ end
552
+
553
+ def complex_template(relative_source, relative_destination, template_options = {})
554
+
555
+ begin
556
+ dest_file = destination_path(relative_destination)
557
+ source_to_update = File.readlines(dest_file).join
558
+ rescue Errno::ENOENT
559
+ logger.missing relative_destination
560
+ return
561
+ end
562
+
563
+ logger.refreshing "#{template_options[:insert].gsub(/\.rhtml/,'')} inside #{relative_destination}"
564
+
565
+ begin_mark = Regexp.quote(template_part_mark(template_options[:begin_mark], template_options[:mark_id]))
566
+ end_mark = Regexp.quote(template_part_mark(template_options[:end_mark], template_options[:mark_id]))
567
+
568
+ # Refreshing inner part of the template with freshly rendered part.
569
+ rendered_part = render_template_part(template_options)
570
+ source_to_update.gsub!(/#{begin_mark}.*?#{end_mark}/m, rendered_part)
571
+
572
+ File.open(dest_file, 'w') { |file| file.write(source_to_update) }
573
+ end
574
+
575
+ def directory(relative_path)
576
+ # logger.directory "#{destination_path(relative_path)}/"
577
+ end
578
+ end
579
+
580
+ end
581
+ end
582
+ end
@@ -0,0 +1,42 @@
1
+ require 'optparse'
2
+
3
+ module Rails
4
+ module Generator
5
+ class GeneratedAttribute
6
+ attr_accessor :name, :type, :column
7
+
8
+ def initialize(name, type)
9
+ @name, @type = name, type.to_sym
10
+ @column = ActiveRecord::ConnectionAdapters::Column.new(name, nil, @type)
11
+ end
12
+
13
+ def field_type
14
+ @field_type ||= case type
15
+ when :integer, :float, :decimal then :text_field
16
+ when :datetime, :timestamp, :time then :datetime_select
17
+ when :date then :date_select
18
+ when :string then :text_field
19
+ when :text then :text_area
20
+ when :boolean then :check_box
21
+ else
22
+ :text_field
23
+ end
24
+ end
25
+
26
+ def default
27
+ @default ||= case type
28
+ when :integer then 1
29
+ when :float then 1.5
30
+ when :decimal then "9.99"
31
+ when :datetime, :timestamp, :time then Time.now.to_s(:db)
32
+ when :date then Date.today.to_s(:db)
33
+ when :string then "MyString"
34
+ when :text then "MyText"
35
+ when :boolean then false
36
+ else
37
+ ""
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ Description:
2
+ The 'adaptation' command creates a new Adaptation adaptor with a default
3
+ directory structure and configuration at the path you specify.
4
+
5
+ Example:
6
+ adaptation ~/Code/Ruby/crm_adaptor
7
+
8
+ This generates a skeletal Adaptation installation in ~/Code/Ruby/adaptation.
9
+ See the README in the newly created application to get going.
10
+
11
+ WARNING:
12
+ Only specify --without-gems if you did not use gems to install Adaptation.
13
+ Your application will expect to find activerecord directory in the vendor directory.