1 class AuthenticatedGenerator < Rails::Generator::NamedBase
2 attr_reader :controller_name,
3 :controller_class_path,
5 :controller_class_nesting,
6 :controller_class_nesting_depth,
7 :controller_class_name,
8 :controller_singular_name,
9 :controller_plural_name
10 alias_method :controller_file_name, :controller_singular_name
11 alias_method :controller_table_name, :controller_plural_name
12 attr_reader :model_controller_name,
13 :model_controller_class_path,
14 :model_controller_file_path,
15 :model_controller_class_nesting,
16 :model_controller_class_nesting_depth,
17 :model_controller_class_name,
18 :model_controller_singular_name,
19 :model_controller_plural_name
20 alias_method :model_controller_file_name, :model_controller_singular_name
21 alias_method :model_controller_table_name, :model_controller_plural_name
23 def initialize(runtime_args, runtime_options = {})
26 @controller_name = args.shift || 'sessions'
27 @model_controller_name = @name.pluralize
30 base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
31 @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
33 if @controller_class_nesting.empty?
34 @controller_class_name = @controller_class_name_without_nesting
36 @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
40 base_name, @model_controller_class_path, @model_controller_file_path, @model_controller_class_nesting, @model_controller_class_nesting_depth = extract_modules(@model_controller_name)
41 @model_controller_class_name_without_nesting, @model_controller_singular_name, @model_controller_plural_name = inflect_names(base_name)
43 if @model_controller_class_nesting.empty?
44 @model_controller_class_name = @model_controller_class_name_without_nesting
46 @model_controller_class_name = "#{@model_controller_class_nesting}::#{@model_controller_class_name_without_nesting}"
51 recorded_session = record do |m|
52 # Check for class naming collisions.
53 m.class_collisions controller_class_path, "#{controller_class_name}Controller", # Sessions Controller
54 "#{controller_class_name}Helper"
55 m.class_collisions model_controller_class_path, "#{model_controller_class_name}Controller", # Model Controller
56 "#{model_controller_class_name}Helper"
57 m.class_collisions class_path, "#{class_name}", "#{class_name}Mailer", "#{class_name}MailerTest", "#{class_name}Observer"
58 m.class_collisions [], 'AuthenticatedSystem', 'AuthenticatedTestHelper'
60 # Controller, helper, views, and test directories.
61 m.directory File.join('app/models', class_path)
62 m.directory File.join('app/controllers', controller_class_path)
63 m.directory File.join('app/controllers', model_controller_class_path)
64 m.directory File.join('app/helpers', controller_class_path)
65 m.directory File.join('app/views', controller_class_path, controller_file_name)
66 m.directory File.join('app/views', class_path, "#{file_name}_mailer") if options[:include_activation]
67 m.directory File.join('test/functional', controller_class_path)
68 m.directory File.join('app/controllers', model_controller_class_path)
69 m.directory File.join('app/helpers', model_controller_class_path)
70 m.directory File.join('app/views', model_controller_class_path, model_controller_file_name)
71 m.directory File.join('test/functional', model_controller_class_path)
72 m.directory File.join('test/unit', class_path)
74 m.template 'model.rb',
75 File.join('app/models',
79 if options[:include_activation]
80 %w( mailer observer ).each do |model_type|
81 m.template "#{model_type}.rb", File.join('app/models',
83 "#{file_name}_#{model_type}.rb")
87 m.template 'controller.rb',
88 File.join('app/controllers',
89 controller_class_path,
90 "#{controller_file_name}_controller.rb")
92 m.template 'model_controller.rb',
93 File.join('app/controllers',
94 model_controller_class_path,
95 "#{model_controller_file_name}_controller.rb")
97 m.template 'authenticated_system.rb',
98 File.join('lib', 'authenticated_system.rb')
100 m.template 'authenticated_test_helper.rb',
101 File.join('lib', 'authenticated_test_helper.rb')
103 m.template 'functional_test.rb',
104 File.join('test/functional',
105 controller_class_path,
106 "#{controller_file_name}_controller_test.rb")
108 m.template 'model_functional_test.rb',
109 File.join('test/functional',
110 model_controller_class_path,
111 "#{model_controller_file_name}_controller_test.rb")
113 m.template 'helper.rb',
114 File.join('app/helpers',
115 controller_class_path,
116 "#{controller_file_name}_helper.rb")
118 m.template 'model_helper.rb',
119 File.join('app/helpers',
120 model_controller_class_path,
121 "#{model_controller_file_name}_helper.rb")
123 m.template 'unit_test.rb',
124 File.join('test/unit',
126 "#{file_name}_test.rb")
128 if options[:include_activation]
129 m.template 'mailer_test.rb', File.join('test/unit', class_path, "#{file_name}_mailer_test.rb")
132 m.template 'fixtures.yml',
133 File.join('test/fixtures',
136 # Controller templates
137 m.template 'login.rhtml', File.join('app/views', controller_class_path, controller_file_name, "new.rhtml")
138 m.template 'signup.rhtml', File.join('app/views', model_controller_class_path, model_controller_file_name, "new.rhtml")
140 if options[:include_activation]
142 %w( activation signup_notification ).each do |action|
143 m.template "#{action}.rhtml",
144 File.join('app/views', "#{file_name}_mailer", "#{action}.rhtml")
148 unless options[:skip_migration]
149 m.migration_template 'migration.rb', 'db/migrate', :assigns => {
150 :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}"
151 }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}"
156 action = $0.split("/")[1]
161 puts "Don't forget to:"
163 puts " - add restful routes in config/routes.rb"
164 puts " map.resources :#{model_controller_file_name}"
165 puts " map.resource :#{controller_singular_name.singularize}"
167 puts " Rails 1.2.3 may need a :controller option for the singular resource:"
168 puts " - map.resource :#{controller_singular_name.singularize}, :controller => '#{controller_file_name}'"
170 if options[:include_activation]
171 puts " map.activate '/activate/:activation_code', :controller => '#{model_controller_file_name}', :action => 'activate'"
173 puts " - add an observer to config/environment.rb"
174 puts " config.active_record.observers = :#{file_name}_observer"
177 puts "Try these for some familiar login URLs if you like:"
179 puts " map.signup '/signup', :controller => '#{model_controller_file_name}', :action => 'new'"
180 puts " map.login '/login', :controller => '#{controller_file_name}', :action => 'new'"
181 puts " map.logout '/logout', :controller => '#{controller_file_name}', :action => 'destroy'"
189 puts "Thanks for using restful_authentication"
191 puts "Don't forget to comment out the observer line in environment.rb"
192 puts " (This was optional so it may not even be there)"
193 puts " # config.active_record.observers = :#{file_name}_observer"
205 # Override with your own usage banner.
207 "Usage: #{$0} authenticated ModelName [ControllerName]"
210 def add_options!(opt)
212 opt.separator 'Options:'
213 opt.on("--skip-migration",
214 "Don't generate a migration file for this model") { |v| options[:skip_migration] = v }
215 opt.on("--include-activation",
216 "Generate signup 'activation code' confirmation via email") { |v| options[:include_activation] = v }