adaptation 0.0.1

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.
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.