view_mapper 0.3.0 → 0.3.1

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