view_mapper 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README +116 -0
  5. data/Rakefile +57 -0
  6. data/VERSION +1 -0
  7. data/generators/scaffold_for_view/USAGE +1 -0
  8. data/generators/scaffold_for_view/scaffold_for_view_generator.rb +37 -0
  9. data/generators/view_for/USAGE +1 -0
  10. data/generators/view_for/view_for_generator.rb +85 -0
  11. data/lib/view_mapper/auto_complete_templates/controller.rb +88 -0
  12. data/lib/view_mapper/auto_complete_templates/functional_test.rb +45 -0
  13. data/lib/view_mapper/auto_complete_templates/helper.rb +2 -0
  14. data/lib/view_mapper/auto_complete_templates/helper_test.rb +4 -0
  15. data/lib/view_mapper/auto_complete_templates/layout.html.erb +18 -0
  16. data/lib/view_mapper/auto_complete_templates/style.css +54 -0
  17. data/lib/view_mapper/auto_complete_templates/view_edit.html.erb +21 -0
  18. data/lib/view_mapper/auto_complete_templates/view_index.html.erb +24 -0
  19. data/lib/view_mapper/auto_complete_templates/view_new.html.erb +20 -0
  20. data/lib/view_mapper/auto_complete_templates/view_show.html.erb +10 -0
  21. data/lib/view_mapper/auto_complete_view.rb +44 -0
  22. data/lib/view_mapper/editable_manifest.rb +10 -0
  23. data/lib/view_mapper/route_action.rb +32 -0
  24. data/lib/view_mapper/view_mapper.rb +33 -0
  25. data/lib/view_mapper.rb +4 -0
  26. data/test/auto_complete_test.rb +146 -0
  27. data/test/database.yml +3 -0
  28. data/test/editable_manifest_test.rb +32 -0
  29. data/test/expected_templates/auto_complete/edit.html.erb +23 -0
  30. data/test/expected_templates/auto_complete/expected_routes.rb +45 -0
  31. data/test/expected_templates/auto_complete/index.html.erb +24 -0
  32. data/test/expected_templates/auto_complete/new.html.erb +22 -0
  33. data/test/expected_templates/auto_complete/show.html.erb +18 -0
  34. data/test/expected_templates/auto_complete/standard_routes.rb +43 -0
  35. data/test/expected_templates/auto_complete/testies.html.erb +18 -0
  36. data/test/expected_templates/auto_complete/testies_controller.rb +88 -0
  37. data/test/fake/fake_generator.rb +3 -0
  38. data/test/fake_view.rb +7 -0
  39. data/test/rails_generator/base.rb +266 -0
  40. data/test/rails_generator/commands.rb +621 -0
  41. data/test/rails_generator/generated_attribute.rb +46 -0
  42. data/test/rails_generator/generators/components/scaffold/scaffold_generator.rb +102 -0
  43. data/test/rails_generator/lookup.rb +249 -0
  44. data/test/rails_generator/manifest.rb +53 -0
  45. data/test/rails_generator/options.rb +150 -0
  46. data/test/rails_generator/scripts/destroy.rb +29 -0
  47. data/test/rails_generator/scripts/generate.rb +7 -0
  48. data/test/rails_generator/scripts/update.rb +12 -0
  49. data/test/rails_generator/scripts.rb +89 -0
  50. data/test/rails_generator/secret_key_generator.rb +24 -0
  51. data/test/rails_generator/simple_logger.rb +46 -0
  52. data/test/rails_generator/spec.rb +44 -0
  53. data/test/rails_generator.rb +43 -0
  54. data/test/scaffold_for_view_generator_test.rb +77 -0
  55. data/test/test_helper.rb +43 -0
  56. data/test/view_for_generator_test.rb +93 -0
  57. data/test/view_mapper_test.rb +29 -0
  58. data/view_mapper.gemspec +125 -0
  59. metadata +147 -0
@@ -0,0 +1,102 @@
1
+ class ScaffoldGenerator < Rails::Generator::NamedBase
2
+ default_options :skip_timestamps => false, :skip_migration => false, :force_plural => false
3
+
4
+ attr_reader :controller_name,
5
+ :controller_class_path,
6
+ :controller_file_path,
7
+ :controller_class_nesting,
8
+ :controller_class_nesting_depth,
9
+ :controller_class_name,
10
+ :controller_underscore_name,
11
+ :controller_singular_name,
12
+ :controller_plural_name
13
+ alias_method :controller_file_name, :controller_underscore_name
14
+ alias_method :controller_table_name, :controller_plural_name
15
+
16
+ def initialize(runtime_args, runtime_options = {})
17
+ super
18
+
19
+ if @name == @name.pluralize && !options[:force_plural]
20
+ logger.warning "Plural version of the model detected, using singularized version. Override with --force-plural."
21
+ @name = @name.singularize
22
+ end
23
+
24
+ @controller_name = @name.pluralize
25
+
26
+ base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
27
+ @controller_class_name_without_nesting, @controller_underscore_name, @controller_plural_name = inflect_names(base_name)
28
+ @controller_singular_name=base_name.singularize
29
+ if @controller_class_nesting.empty?
30
+ @controller_class_name = @controller_class_name_without_nesting
31
+ else
32
+ @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
33
+ end
34
+ end
35
+
36
+ def manifest
37
+ record do |m|
38
+ # Check for class naming collisions.
39
+ m.class_collisions("#{controller_class_name}Controller", "#{controller_class_name}Helper")
40
+ m.class_collisions(class_name)
41
+
42
+ # Controller, helper, views, test and stylesheets directories.
43
+ m.directory(File.join('app/models', class_path))
44
+ m.directory(File.join('app/controllers', controller_class_path))
45
+ m.directory(File.join('app/helpers', controller_class_path))
46
+ m.directory(File.join('app/views', controller_class_path, controller_file_name))
47
+ m.directory(File.join('app/views/layouts', controller_class_path))
48
+ m.directory(File.join('test/functional', controller_class_path))
49
+ m.directory(File.join('test/unit', class_path))
50
+ m.directory(File.join('test/unit/helpers', class_path))
51
+ m.directory(File.join('public/stylesheets', class_path))
52
+
53
+ for action in scaffold_views
54
+ m.template(
55
+ "view_#{action}.html.erb",
56
+ File.join('app/views', controller_class_path, controller_file_name, "#{action}.html.erb")
57
+ )
58
+ end
59
+
60
+ # Layout and stylesheet.
61
+ m.template('layout.html.erb', File.join('app/views/layouts', controller_class_path, "#{controller_file_name}.html.erb"))
62
+ m.template('style.css', 'public/stylesheets/scaffold.css')
63
+
64
+ m.template(
65
+ 'controller.rb', File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
66
+ )
67
+
68
+ m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
69
+ m.template('helper.rb', File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb"))
70
+ m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))
71
+
72
+ m.route_resources controller_file_name
73
+
74
+ m.dependency 'model', [name] + @args, :collision => :skip
75
+ end
76
+ end
77
+
78
+ protected
79
+ # Override with your own usage banner.
80
+ def banner
81
+ "Usage: #{$0} scaffold ModelName [field:type, field:type]"
82
+ end
83
+
84
+ def add_options!(opt)
85
+ opt.separator ''
86
+ opt.separator 'Options:'
87
+ opt.on("--skip-timestamps",
88
+ "Don't add timestamps to the migration file for this model") { |v| options[:skip_timestamps] = v }
89
+ opt.on("--skip-migration",
90
+ "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
91
+ opt.on("--force-plural",
92
+ "Forces the generation of a plural ModelName") { |v| options[:force_plural] = v }
93
+ end
94
+
95
+ def scaffold_views
96
+ %w[ index show new edit ]
97
+ end
98
+
99
+ def model_name
100
+ class_name.demodulize
101
+ end
102
+ end
@@ -0,0 +1,249 @@
1
+ require 'pathname'
2
+
3
+ require File.dirname(__FILE__) + '/spec'
4
+
5
+ class Object
6
+ class << self
7
+ # Lookup missing generators using const_missing. This allows any
8
+ # generator to reference another without having to know its location:
9
+ # RubyGems, ~/.rails/generators, and RAILS_ROOT/generators.
10
+ def lookup_missing_generator(class_id)
11
+ if md = /(.+)Generator$/.match(class_id.to_s)
12
+ name = md.captures.first.demodulize.underscore
13
+ Rails::Generator::Base.lookup(name).klass
14
+ else
15
+ const_missing_before_generators(class_id)
16
+ end
17
+ end
18
+
19
+ unless respond_to?(:const_missing_before_generators)
20
+ alias_method :const_missing_before_generators, :const_missing
21
+ alias_method :const_missing, :lookup_missing_generator
22
+ end
23
+ end
24
+ end
25
+
26
+ # User home directory lookup adapted from RubyGems.
27
+ def Dir.user_home
28
+ if ENV['HOME']
29
+ ENV['HOME']
30
+ elsif ENV['USERPROFILE']
31
+ ENV['USERPROFILE']
32
+ elsif ENV['HOMEDRIVE'] and ENV['HOMEPATH']
33
+ "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
34
+ else
35
+ File.expand_path '~'
36
+ end
37
+ end
38
+
39
+
40
+ module Rails
41
+ module Generator
42
+
43
+ # Generator lookup is managed by a list of sources which return specs
44
+ # describing where to find and how to create generators. This module
45
+ # provides class methods for manipulating the source list and looking up
46
+ # generator specs, and an #instance wrapper for quickly instantiating
47
+ # generators by name.
48
+ #
49
+ # A spec is not a generator: it's a description of where to find
50
+ # the generator and how to create it. A source is anything that
51
+ # yields generators from #each. PathSource and GemGeneratorSource are provided.
52
+ module Lookup
53
+ def self.included(base)
54
+ base.extend(ClassMethods)
55
+ base.use_component_sources!
56
+ end
57
+
58
+ # Convenience method to instantiate another generator.
59
+ def instance(generator_name, args, runtime_options = {})
60
+ self.class.instance(generator_name, args, runtime_options)
61
+ end
62
+
63
+ module ClassMethods
64
+ # The list of sources where we look, in order, for generators.
65
+ def sources
66
+ read_inheritable_attribute(:sources) or use_component_sources!
67
+ end
68
+
69
+ # Add a source to the end of the list.
70
+ def append_sources(*args)
71
+ sources.concat(args.flatten)
72
+ invalidate_cache!
73
+ end
74
+
75
+ # Add a source to the beginning of the list.
76
+ def prepend_sources(*args)
77
+ write_inheritable_array(:sources, args.flatten + sources)
78
+ invalidate_cache!
79
+ end
80
+
81
+ # Reset the source list.
82
+ def reset_sources
83
+ write_inheritable_attribute(:sources, [])
84
+ invalidate_cache!
85
+ end
86
+
87
+ # Use application generators (app, ?).
88
+ def use_application_sources!
89
+ reset_sources
90
+ sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/applications")
91
+ end
92
+
93
+ # Use component generators (model, controller, etc).
94
+ # 1. Rails application. If RAILS_ROOT is defined we know we're
95
+ # generating in the context of a Rails application, so search
96
+ # RAILS_ROOT/generators.
97
+ # 2. Look in plugins, either for generators/ or rails_generators/
98
+ # directories within each plugin
99
+ # 3. User home directory. Search ~/.rails/generators.
100
+ # 4. RubyGems. Search for gems named *_generator, and look for
101
+ # generators within any RubyGem's
102
+ # /rails_generators/<generator_name>_generator.rb file.
103
+ # 5. Builtins. Model, controller, mailer, scaffold, and so on.
104
+ def use_component_sources!
105
+ reset_sources
106
+ if defined? ::RAILS_ROOT
107
+ sources << PathSource.new(:lib, "#{::RAILS_ROOT}/lib/generators")
108
+ sources << PathSource.new(:vendor, "#{::RAILS_ROOT}/vendor/generators")
109
+ Rails.configuration.plugin_paths.each do |path|
110
+ relative_path = Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(::RAILS_ROOT))
111
+ sources << PathSource.new(:"plugins (#{relative_path})", "#{path}/*/**/{,rails_}generators")
112
+ end
113
+ end
114
+ sources << PathSource.new(:user, "#{Dir.user_home}/.rails/generators")
115
+ if Object.const_defined?(:Gem)
116
+ sources << GemGeneratorSource.new
117
+ sources << GemPathSource.new
118
+ end
119
+ sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/components")
120
+ end
121
+
122
+ # Lookup knows how to find generators' Specs from a list of Sources.
123
+ # Searches the sources, in order, for the first matching name.
124
+ def lookup(generator_name)
125
+ @found ||= {}
126
+ generator_name = generator_name.to_s.downcase
127
+ @found[generator_name] ||= cache.find { |spec| spec.name == generator_name }
128
+ unless @found[generator_name]
129
+ chars = generator_name.scan(/./).map{|c|"#{c}.*?"}
130
+ rx = /^#{chars}$/
131
+ gns = cache.select{|spec| spec.name =~ rx }
132
+ @found[generator_name] ||= gns.first if gns.length == 1
133
+ raise GeneratorError, "Pattern '#{generator_name}' matches more than one generator: #{gns.map{|sp|sp.name}.join(', ')}" if gns.length > 1
134
+ end
135
+ @found[generator_name] or raise GeneratorError, "Couldn't find '#{generator_name}' generator"
136
+ end
137
+
138
+ # Convenience method to lookup and instantiate a generator.
139
+ def instance(generator_name, args = [], runtime_options = {})
140
+ lookup(generator_name).klass.new(args, full_options(runtime_options))
141
+ end
142
+
143
+ private
144
+ # Lookup and cache every generator from the source list.
145
+ def cache
146
+ @cache ||= sources.inject([]) { |cache, source| cache + source.to_a }
147
+ end
148
+
149
+ # Clear the cache whenever the source list changes.
150
+ def invalidate_cache!
151
+ @cache = nil
152
+ end
153
+ end
154
+ end
155
+
156
+ # Sources enumerate (yield from #each) generator specs which describe
157
+ # where to find and how to create generators. Enumerable is mixed in so,
158
+ # for example, source.collect will retrieve every generator.
159
+ # Sources may be assigned a label to distinguish them.
160
+ class Source
161
+ include Enumerable
162
+
163
+ attr_reader :label
164
+ def initialize(label)
165
+ @label = label
166
+ end
167
+
168
+ # The each method must be implemented in subclasses.
169
+ # The base implementation raises an error.
170
+ def each
171
+ raise NotImplementedError
172
+ end
173
+
174
+ # Return a convenient sorted list of all generator names.
175
+ def names
176
+ map { |spec| spec.name }.sort
177
+ end
178
+ end
179
+
180
+
181
+ # PathSource looks for generators in a filesystem directory.
182
+ class PathSource < Source
183
+ attr_reader :path
184
+
185
+ def initialize(label, path)
186
+ super label
187
+ @path = path
188
+ end
189
+
190
+ # Yield each eligible subdirectory.
191
+ def each
192
+ Dir["#{path}/[a-z]*"].each do |dir|
193
+ if File.directory?(dir)
194
+ yield Spec.new(File.basename(dir), dir, label)
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ class AbstractGemSource < Source
201
+ def initialize
202
+ super :RubyGems
203
+ end
204
+ end
205
+
206
+ # GemGeneratorSource hits the mines to quarry for generators. The latest versions
207
+ # of gems named *_generator are selected.
208
+ class GemGeneratorSource < AbstractGemSource
209
+ # Yield latest versions of generator gems.
210
+ def each
211
+ dependency = Gem::Dependency.new(/_generator$/, Gem::Requirement.default)
212
+ Gem::cache.search(dependency).inject({}) { |latest, gem|
213
+ hem = latest[gem.name]
214
+ latest[gem.name] = gem if hem.nil? or gem.version > hem.version
215
+ latest
216
+ }.values.each { |gem|
217
+ yield Spec.new(gem.name.sub(/_generator$/, ''), gem.full_gem_path, label)
218
+ }
219
+ end
220
+ end
221
+
222
+ # GemPathSource looks for generators within any RubyGem's /rails_generators/<generator_name>_generator.rb file.
223
+ class GemPathSource < AbstractGemSource
224
+ # Yield each generator within rails_generator subdirectories.
225
+ def each
226
+ generator_full_paths.each do |generator|
227
+ yield Spec.new(File.basename(generator).sub(/_generator.rb$/, ''), File.dirname(generator), label)
228
+ end
229
+ end
230
+
231
+ private
232
+ def generator_full_paths
233
+ @generator_full_paths ||=
234
+ Gem::cache.inject({}) do |latest, name_gem|
235
+ name, gem = name_gem
236
+ hem = latest[gem.name]
237
+ latest[gem.name] = gem if hem.nil? or gem.version > hem.version
238
+ latest
239
+ end.values.inject([]) do |mem, gem|
240
+ Dir[gem.full_gem_path + '/{rails_,}generators/**/*_generator.rb'].each do |generator|
241
+ mem << generator
242
+ end
243
+ mem
244
+ end
245
+ end
246
+ end
247
+
248
+ end
249
+ end
@@ -0,0 +1,53 @@
1
+ module Rails
2
+ module Generator
3
+
4
+ # Manifest captures the actions a generator performs. Instantiate
5
+ # a manifest with an optional target object, hammer it with actions,
6
+ # then replay or rewind on the object of your choice.
7
+ #
8
+ # Example:
9
+ # manifest = Manifest.new { |m|
10
+ # m.make_directory '/foo'
11
+ # m.create_file '/foo/bar.txt'
12
+ # }
13
+ # manifest.replay(creator)
14
+ # manifest.rewind(destroyer)
15
+ class Manifest
16
+ attr_reader :target
17
+
18
+ # Take a default action target. Yield self if block given.
19
+ def initialize(target = nil)
20
+ @target, @actions = target, []
21
+ yield self if block_given?
22
+ end
23
+
24
+ # Record an action.
25
+ def method_missing(action, *args, &block)
26
+ @actions << [action, args, block]
27
+ end
28
+
29
+ # Replay recorded actions.
30
+ def replay(target = nil)
31
+ send_actions(target || @target, @actions)
32
+ end
33
+
34
+ # Rewind recorded actions.
35
+ def rewind(target = nil)
36
+ send_actions(target || @target, @actions.reverse)
37
+ end
38
+
39
+ # Erase recorded actions.
40
+ def erase
41
+ @actions = []
42
+ end
43
+
44
+ private
45
+ def send_actions(target, actions)
46
+ actions.each do |method, args, block|
47
+ target.send(method, *args, &block)
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,150 @@
1
+ require 'optparse'
2
+
3
+ module Rails
4
+ module Generator
5
+ module Options
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ class << base
9
+ if respond_to?(:inherited)
10
+ alias_method :inherited_without_options, :inherited
11
+ end
12
+ alias_method :inherited, :inherited_with_options
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def inherited_with_options(sub)
18
+ inherited_without_options(sub) if respond_to?(:inherited_without_options)
19
+ sub.extend(Rails::Generator::Options::ClassMethods)
20
+ end
21
+
22
+ def mandatory_options(options = nil)
23
+ if options
24
+ write_inheritable_attribute(:mandatory_options, options)
25
+ else
26
+ read_inheritable_attribute(:mandatory_options) or write_inheritable_attribute(:mandatory_options, {})
27
+ end
28
+ end
29
+
30
+ def default_options(options = nil)
31
+ if options
32
+ write_inheritable_attribute(:default_options, options)
33
+ else
34
+ read_inheritable_attribute(:default_options) or write_inheritable_attribute(:default_options, {})
35
+ end
36
+ end
37
+
38
+ # Merge together our class options. In increasing precedence:
39
+ # default_options (class default options)
40
+ # runtime_options (provided as argument)
41
+ # mandatory_options (class mandatory options)
42
+ def full_options(runtime_options = {})
43
+ default_options.merge(runtime_options).merge(mandatory_options)
44
+ end
45
+
46
+ end
47
+
48
+ # Each instance has an options hash that's populated by #parse.
49
+ def options
50
+ @options ||= {}
51
+ end
52
+ attr_writer :options
53
+
54
+ protected
55
+ # Convenient access to class mandatory options.
56
+ def mandatory_options
57
+ self.class.mandatory_options
58
+ end
59
+
60
+ # Convenient access to class default options.
61
+ def default_options
62
+ self.class.default_options
63
+ end
64
+
65
+ # Merge together our instance options. In increasing precedence:
66
+ # default_options (class default options)
67
+ # options (instance options)
68
+ # runtime_options (provided as argument)
69
+ # mandatory_options (class mandatory options)
70
+ def full_options(runtime_options = {})
71
+ self.class.full_options(options.merge(runtime_options))
72
+ end
73
+
74
+ # Parse arguments into the options hash. Classes may customize
75
+ # parsing behavior by overriding these methods:
76
+ # #banner Usage: ./script/generate [options]
77
+ # #add_options! Options:
78
+ # some options..
79
+ # #add_general_options! General Options:
80
+ # general options..
81
+ def parse!(args, runtime_options = {})
82
+ self.options = {}
83
+
84
+ @option_parser = OptionParser.new do |opt|
85
+ opt.banner = banner
86
+ add_options!(opt)
87
+ add_general_options!(opt)
88
+ opt.parse!(args)
89
+ end
90
+
91
+ return args
92
+ ensure
93
+ self.options = full_options(runtime_options)
94
+ end
95
+
96
+ # Raise a usage error. Override usage_message to provide a blurb
97
+ # after the option parser summary.
98
+ def usage(message = usage_message)
99
+ raise UsageError, "#{@option_parser}\n#{message}"
100
+ end
101
+
102
+ def usage_message
103
+ ''
104
+ end
105
+
106
+ # Override with your own usage banner.
107
+ def banner
108
+ "Usage: #{$0} [options]"
109
+ end
110
+
111
+ # Override to add your options to the parser:
112
+ # def add_options!(opt)
113
+ # opt.on('-v', '--verbose') { |value| options[:verbose] = value }
114
+ # end
115
+ def add_options!(opt)
116
+ end
117
+
118
+ # Adds general options like -h and --quiet. Usually don't override.
119
+ def add_general_options!(opt)
120
+ opt.separator ''
121
+ opt.separator 'Rails Info:'
122
+ opt.on('-v', '--version', 'Show the Rails version number and quit.')
123
+ opt.on('-h', '--help', 'Show this help message and quit.') { |v| options[:help] = v }
124
+
125
+ opt.separator ''
126
+ opt.separator 'General Options:'
127
+
128
+ opt.on('-p', '--pretend', 'Run but do not make any changes.') { |v| options[:pretend] = v }
129
+ opt.on('-f', '--force', 'Overwrite files that already exist.') { options[:collision] = :force }
130
+ opt.on('-s', '--skip', 'Skip files that already exist.') { options[:collision] = :skip }
131
+ opt.on('-q', '--quiet', 'Suppress normal output.') { |v| options[:quiet] = v }
132
+ opt.on('-t', '--backtrace', 'Debugging: show backtrace on errors.') { |v| options[:backtrace] = v }
133
+ opt.on('-c', '--svn', 'Modify files with subversion. (Note: svn must be in path)') do
134
+ options[:svn] = `svn status`.inject({}) do |opt, e|
135
+ opt[e.chomp[7..-1]] = true
136
+ opt
137
+ end
138
+ end
139
+ opt.on('-g', '--git', 'Modify files with git. (Note: git must be in path)') do
140
+ options[:git] = `git status`.inject({:new => {}, :modified => {}}) do |opt, e|
141
+ opt[:new][e.chomp[14..-1]] = true if e =~ /new file:/
142
+ opt[:modified][e.chomp[14..-1]] = true if e =~ /modified:/
143
+ opt
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module Rails::Generator::Scripts
4
+ class Destroy < Base
5
+ mandatory_options :command => :destroy
6
+
7
+ protected
8
+ def usage_message
9
+ usage = "\nInstalled Generators\n"
10
+ Rails::Generator::Base.sources.each do |source|
11
+ label = source.label.to_s.capitalize
12
+ names = source.names
13
+ usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
14
+ end
15
+
16
+ usage << <<end_blurb
17
+
18
+ script/generate command. For instance, 'script/destroy migration CreatePost'
19
+ will delete the appropriate XXX_create_post.rb migration file in db/migrate,
20
+ while 'script/destroy scaffold Post' will delete the posts controller and
21
+ views, post model and migration, all associated tests, and the map.resources
22
+ :posts line in config/routes.rb.
23
+
24
+ For instructions on finding new generators, run script/generate.
25
+ end_blurb
26
+ return usage
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module Rails::Generator::Scripts
4
+ class Generate < Base
5
+ mandatory_options :command => :create
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module Rails::Generator::Scripts
4
+ class Update < Base
5
+ mandatory_options :command => :update
6
+
7
+ protected
8
+ def banner
9
+ "Usage: #{$0} [options] scaffold"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,89 @@
1
+ require File.dirname(__FILE__) + '/options'
2
+
3
+ module Rails
4
+ module Generator
5
+ module Scripts
6
+
7
+ # Generator scripts handle command-line invocation. Each script
8
+ # responds to an invoke! class method which handles option parsing
9
+ # and generator invocation.
10
+ class Base
11
+ include Options
12
+ default_options :collision => :ask, :quiet => false
13
+
14
+ # Run the generator script. Takes an array of unparsed arguments
15
+ # and a hash of parsed arguments, takes the generator as an option
16
+ # or first remaining argument, and invokes the requested command.
17
+ def run(args = [], runtime_options = {})
18
+ begin
19
+ parse!(args.dup, runtime_options)
20
+ rescue OptionParser::InvalidOption => e
21
+ # Don't cry, script. Generators want what you think is invalid.
22
+ end
23
+
24
+ # Generator name is the only required option.
25
+ unless options[:generator]
26
+ usage if args.empty?
27
+ options[:generator] ||= args.shift
28
+ end
29
+
30
+ # Look up generator instance and invoke command on it.
31
+ Rails::Generator::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
32
+ rescue => e
33
+ puts e
34
+ puts " #{e.backtrace.join("\n ")}\n" if options[:backtrace]
35
+ raise SystemExit
36
+ end
37
+
38
+ protected
39
+ # Override with your own script usage banner.
40
+ def banner
41
+ "Usage: #{$0} generator [options] [args]"
42
+ end
43
+
44
+ def usage_message
45
+ usage = "\nInstalled Generators\n"
46
+ Rails::Generator::Base.sources.inject([]) do |mem, source|
47
+ # Using an association list instead of a hash to preserve order,
48
+ # for aesthetic reasons more than anything else.
49
+ label = source.label.to_s.capitalize
50
+ pair = mem.assoc(label)
51
+ mem << (pair = [label, []]) if pair.nil?
52
+ pair[1] |= source.names
53
+ mem
54
+ end.each do |label, names|
55
+ usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
56
+ end
57
+
58
+ usage << <<end_blurb
59
+
60
+ More are available at http://wiki.rubyonrails.org/rails/pages/AvailableGenerators
61
+ 1. Download, for example, login_generator.zip
62
+ 2. Unzip to directory #{Dir.user_home}/.rails/generators/login
63
+ to use the generator with all your Rails apps
64
+ end_blurb
65
+
66
+ if Object.const_defined?(:RAILS_ROOT)
67
+ usage << <<end_blurb
68
+ or to #{File.expand_path(RAILS_ROOT)}/lib/generators/login
69
+ to use with this app only.
70
+ end_blurb
71
+ end
72
+
73
+ usage << <<end_blurb
74
+ 3. Run generate with no arguments for usage information
75
+ #{$0} login
76
+
77
+ Generator gems are also available:
78
+ 1. gem search -r generator
79
+ 2. gem install login_generator
80
+ 3. #{$0} login
81
+
82
+ end_blurb
83
+ return usage
84
+ end
85
+ end # Base
86
+
87
+ end
88
+ end
89
+ end