root/trunk/lib/merb/generators/merb_generator_helpers.rb

Revision 1215, 11.4 kB (checked in by e.@brainspl.at, 11 months ago)

add support for generators for PartControllers? closes #416 [siebertm85@googlemail.com]

Line 
1 # Provides some basic generator support that is generally required in various
2 # Generators
3
4 module Merb
5   module GeneratorHelpers
6    
7     class ModelGeneratorBase < RubiGen::Base
8
9       default_options :author => nil
10       attr_reader :name, :model_attributes
11       attr_accessor :model_template_name, :model_test_generator_name, :migration_generator_name
12      
13       def initialize(runtime_args, runtime_options = {})
14         super
15         usage if args.empty?
16         @class_name = args.shift.snake_case.to_const_string
17         extract_options
18       end
19
20       def manifest
21         unless @class_name
22           puts banner
23           exit 1
24         end
25         record do |m|
26
27           # ensure there are no other definitions of this model already defined.
28           m.class_collisions(@class_name)
29           # Ensure appropriate folder(s) exists
30           m.directory 'app/models'
31           #
32           model_filename = @class_name.snake_case
33           spec_filename = @class_name.snake_case.pluralize
34           table_name = spec_filename
35
36
37           # Create stubs
38           m.template  model_template_name,
39                       "app/models/#{model_filename}.rb",
40                       :assigns => {  :class_name => @class_name,
41                                      :table_attributes => model_attributes}
42
43           # Check to see if a scope has been set for which test framework to use.
44           # If we try to run the dependency without an :rspec or :test_unit scope an
45           # error will be raised.
46           scopes = RubiGen::Base.sources.select{ |s| s.is_a?( RubiGen::PathFilteredSource )}.first.filters
47           if scopes.include?(:rspec) || scopes.include?(:test_unit)
48             unless options[:skip_testing]
49               m.dependency model_test_generator_name, [@class_name]
50             end
51           else
52             puts "\nSelect a scope for :rspec or :test_unit in script/generate if you want to generate test stubs\n\n"
53           end
54
55           unless options[:skip_migration]
56             m.dependency migration_generator_name,["add_model_#{spec_filename}"], :table_name => table_name, :table_attributes => model_attributes
57           end
58
59         end   
60       end
61
62       protected
63         def banner
64             <<-EOS
65 Creates a new model for merb
66
67 USAGE: #{$0} #{spec.name} NameOfModel [field:type field:type]
68
69 Example:
70   #{$0} #{spec.name} person
71
72   If you already have 3 migrations, this will create the AddModelPeople migration in
73   schema/migration/004_add_model_people.rb
74
75 Options:
76   --skip-migration will not create a migration file
77
78 EOS
79           end
80
81         def add_options!(opts)
82           opts.separator ''
83           opts.separator 'Options:'
84           # For each option below, place the default
85           # at the top of the file next to "default_options"
86           # opts.on("-a", "--author=\"Your Name\"", String,
87           #         "Some comment about this option",
88           #         "Default: none") { |options[:author]| }
89           # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
90           opts.on( "--skip-migration", "Don't generate a migration for this model") { |options[:skip_migration]| }
91           opts.on( "--skip-testing", "Don't generate a test or spec file for this model") { |options[:skip_testing]| }
92         end
93
94         def extract_options
95           # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
96           # Templates can access these value via the attr_reader-generated methods, but not the
97           # raw instance variable value.
98           # @author = options[:author]
99           # get the attributes into a format that can be used.
100           attribute = Struct.new(:name, :type)
101           @model_attributes = args.map{ |b| b.split(":").size > 1 ? attribute.new(*b.split(":")) : nil }.compact
102         end
103     end
104    
105     class MigrationGeneratorBase < RubiGen::Base
106
107       default_options :author => nil
108
109       attr_reader :name
110       attr_accessor :migration_template_name
111      
112       def initialize(runtime_args, runtime_options = {})
113         super
114         usage if args.empty?
115         @class_name = args.shift
116         options[:table_name] ||= runtime_options[:table_name]
117         extract_options
118       end
119
120       def manifest
121         unless @class_name
122           puts banner
123           exit 1
124         end
125         record do |m|
126           # Ensure appropriate folder(s) exists
127           m.directory 'schema/migrations'
128
129           # Create stubs
130           highest_migration = Dir[Dir.pwd+'/schema/migrations/*'].map{|f| File.basename(f) =~ /^(\d+)/; $1}.max
131           filename = format("%03d_%s", (highest_migration.to_i+1), @class_name.snake_case)
132           m.template "new_migration.erb", "schema/migrations/#{filename}.rb",
133             :assigns => { :class_name => @class_name,
134                           :table_name => options[:table_name],
135                           :table_attributes => options[:table_attributes] }
136
137         end
138       end
139
140       protected
141         def banner
142           <<-EOS
143 Creates a new migration for merb
144
145 USAGE: #{$0} #{spec.name} NameOfMigration [field:type field:type]
146
147 Example:
148   #{$0} #{spec.name} AddPeople
149
150   If you already have 3 migrations, this will create the AddPeople migration in
151   schema/migration/004_add_people.rb
152
153   #{$0} #{spec.name} project --table-name projects_table name:string created_at:timestamp
154
155   This will create a migration that creates a table call projects_table with these attributes:
156     string :name
157     timestamp :created_at
158
159 EOS
160         end
161
162         def add_options!(opts)
163           opts.separator ''
164           opts.separator 'Options:'
165           # For each option below, place the default
166           # at the top of the file next to "default_options"
167           # opts.on("-a", "--author=\"Your Name\"", String,
168           #         "Some comment about this option",
169           #         "Default: none") { |options[:author]| }
170           # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
171           opts.on( "--table-name=\"table_name_for_migration\"",
172                     String,
173                     "Include a create table with the given table name"){ |options[:table_name]| }
174         end
175
176         def extract_options
177           # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
178           # Templates can access these value via the attr_reader-generated methods, but not the
179           # raw instance variable value.
180           # @author = options[:author]
181           if !options[:table_attributes]
182             attribute = Struct.new(:name, :type)
183             options[:table_attributes] = args.map{ |b| b.split(":").size == 2 ? attribute.new(*b.split(":")) : nil }.compact
184           end
185         end
186     end
187    
188     class MerbModelTestGenerator < RubiGen::Base
189
190       default_options :author => nil
191
192       attr_reader :name, :model_test_template_name, :model_test_path_name, :model_test_file_suffix
193
194       def initialize(runtime_args, runtime_options = {})
195         super
196         usage if args.empty?
197         @class_name = args.shift.snake_case.to_const_string
198         extract_options
199       end
200
201       def manifest
202         unless @class_name
203           puts banner
204           exit 1
205         end
206         record do |m|
207           # ensure there are no other definitions of this model already defined.
208           # Ensure appropriate folder(s) exists
209           m.directory model_test_path_name
210           #
211           model_filename = @class_name.snake_case
212
213           # Create stubs
214           m.template model_test_template_name,
215             "#{model_test_path_name}/#{model_filename}_#{model_test_file_suffix}.rb",
216             :assigns => {:class_name => @class_name}
217         end
218       end
219
220       protected
221
222
223         def add_options!(opts)
224           # opts.separator ''
225           # opts.separator 'Options:'
226           # For each option below, place the default
227           # at the top of the file next to "default_options"
228           # opts.on("-a", "--author=\"Your Name\"", String,
229           #         "Some comment about this option",
230           #         "Default: none") { |options[:author]| }
231           # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
232         end
233
234         def extract_options
235           # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
236           # Templates can access these value via the attr_reader-generated methods, but not the
237           # raw instance variable value.
238           # @author = options[:author]
239         end
240     end
241    
242     # Pass the following options are available to this generatrs
243     class ControllerGeneratorBase < RubiGen::Base
244
245       default_options :author => nil
246
247       attr_reader :name, :class_name, :file_name
248
249       def initialize(runtime_args, runtime_options = {})
250         super
251         usage if args.empty?
252         @name             = args.shift
253         @class_name       = @name.camel_case #.pluralize
254         @file_name        = @name.snake_case #.pluralize
255         @engine           = runtime_options[:engine] || "erb" # set by subclasses only
256         @template_actions = runtime_options[:actions] || %w[index] # Used by subclasses only
257         @test_generator   = runtime_options[:test_stub_generator] || "merb_controller_test"
258         @base_dest_folder = runtime_options[:base_dest_folder] || "app"
259         extract_options
260       end
261
262       def manifest
263         record do |m|
264          
265           # ensure there are no other definitions of this model already defined.
266           m.class_collisions(@class_name)
267          
268           m.directory "#{@base_dest_folder}/controllers"
269           m.template "controller.rb", "#{@base_dest_folder}/controllers/#{file_name}.rb", :assigns => {:actions => @template_actions}
270          
271           m.directory "#{@base_dest_folder}/views/#{file_name}"
272          
273           # Include templates if they exist
274           @template_actions.each do |the_action| 
275             template_name = "#{the_action}.html.#{@engine}"
276             template_path = "/" + source_path(spec.name).split("/")[0..-2].join("/")
277
278             if File.exists?(File.join(template_path,template_name))
279               m.template template_name, "#{@base_dest_folder}/views/#{file_name}/#{template_name}"
280             end
281           end
282
283           m.directory "#{@base_dest_folder}/helpers/"
284           m.template "helper.rb", "#{@base_dest_folder}/helpers/#{file_name}_helper.rb"
285           m.dependency @test_generator, [name], :destination => destination_root, :template_actions => @template_actions
286         end
287       end
288
289       protected
290         def banner
291           <<-EOS
292     Creates a Merb controller
293
294     USAGE: #{$0} #{spec.name} name"
295    EOS
296         end
297
298         def add_options!(opts)
299           # opts.separator ''
300           # opts.separator 'Options:'
301           # For each option below, place the default
302           # at the top of the file next to "default_options"
303           # opts.on("-a", "--author=\"Your Name\"", String,
304           #         "Some comment about this option",
305           #         "Default: none") { |options[:author]| }
306           # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
307         end
308
309         def extract_options
310           # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
311           # Templates can access these value via the attr_reader-generated methods, but not the
312           # raw instance variable value.
313           # @author = options[:author]
314         end
315     end
316    
317   end
318 end
Note: See TracBrowser for help on using the browser.