niftier-generators 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/CHANGELOG +7 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +89 -0
  4. data/Rakefile +18 -0
  5. data/features/niftier_authentication.feature +59 -0
  6. data/features/niftier_config.feature +17 -0
  7. data/features/niftier_layout.feature +19 -0
  8. data/features/niftier_scaffold.feature +22 -0
  9. data/features/step_definitions/common_steps.rb +37 -0
  10. data/features/step_definitions/rails_setup_steps.rb +6 -0
  11. data/features/support/env.rb +6 -0
  12. data/features/support/matchers.rb +7 -0
  13. data/lib/generators/niftier/authentication/USAGE +55 -0
  14. data/lib/generators/niftier/authentication/authentication_generator.rb +145 -0
  15. data/lib/generators/niftier/authentication/templates/authentication.rb +60 -0
  16. data/lib/generators/niftier/authentication/templates/authlogic_session.rb +2 -0
  17. data/lib/generators/niftier/authentication/templates/fixtures.yml +24 -0
  18. data/lib/generators/niftier/authentication/templates/migration.rb +20 -0
  19. data/lib/generators/niftier/authentication/templates/sessions_controller.rb +45 -0
  20. data/lib/generators/niftier/authentication/templates/sessions_helper.rb +2 -0
  21. data/lib/generators/niftier/authentication/templates/tests/rspec/sessions_controller.rb +39 -0
  22. data/lib/generators/niftier/authentication/templates/tests/rspec/user.rb +83 -0
  23. data/lib/generators/niftier/authentication/templates/tests/rspec/users_controller.rb +26 -0
  24. data/lib/generators/niftier/authentication/templates/tests/shoulda/sessions_controller.rb +40 -0
  25. data/lib/generators/niftier/authentication/templates/tests/shoulda/user.rb +85 -0
  26. data/lib/generators/niftier/authentication/templates/tests/shoulda/users_controller.rb +27 -0
  27. data/lib/generators/niftier/authentication/templates/tests/testunit/sessions_controller.rb +36 -0
  28. data/lib/generators/niftier/authentication/templates/tests/testunit/user.rb +88 -0
  29. data/lib/generators/niftier/authentication/templates/tests/testunit/users_controller.rb +23 -0
  30. data/lib/generators/niftier/authentication/templates/user.rb +42 -0
  31. data/lib/generators/niftier/authentication/templates/users_controller.rb +18 -0
  32. data/lib/generators/niftier/authentication/templates/users_helper.rb +2 -0
  33. data/lib/generators/niftier/authentication/templates/views/erb/login.html.erb +30 -0
  34. data/lib/generators/niftier/authentication/templates/views/erb/signup.html.erb +24 -0
  35. data/lib/generators/niftier/authentication/templates/views/haml/login.html.haml +30 -0
  36. data/lib/generators/niftier/authentication/templates/views/haml/signup.html.haml +24 -0
  37. data/lib/generators/niftier/config/USAGE +23 -0
  38. data/lib/generators/niftier/config/config_generator.rb +24 -0
  39. data/lib/generators/niftier/config/templates/config.yml +14 -0
  40. data/lib/generators/niftier/config/templates/load_config.rb +2 -0
  41. data/lib/generators/niftier/layout/USAGE +25 -0
  42. data/lib/generators/niftier/layout/layout_generator.rb +29 -0
  43. data/lib/generators/niftier/layout/templates/error_messages_helper.rb +23 -0
  44. data/lib/generators/niftier/layout/templates/layout.html.erb +24 -0
  45. data/lib/generators/niftier/layout/templates/layout.html.haml +26 -0
  46. data/lib/generators/niftier/layout/templates/layout_helper.rb +26 -0
  47. data/lib/generators/niftier/layout/templates/stylesheet.css +75 -0
  48. data/lib/generators/niftier/layout/templates/stylesheet.sass +66 -0
  49. data/lib/generators/niftier/scaffold/USAGE +51 -0
  50. data/lib/generators/niftier/scaffold/scaffold_generator.rb +241 -0
  51. data/lib/generators/niftier/scaffold/templates/actions/create.rb +9 -0
  52. data/lib/generators/niftier/scaffold/templates/actions/destroy.rb +6 -0
  53. data/lib/generators/niftier/scaffold/templates/actions/edit.rb +3 -0
  54. data/lib/generators/niftier/scaffold/templates/actions/index.rb +3 -0
  55. data/lib/generators/niftier/scaffold/templates/actions/new.rb +3 -0
  56. data/lib/generators/niftier/scaffold/templates/actions/show.rb +3 -0
  57. data/lib/generators/niftier/scaffold/templates/actions/update.rb +9 -0
  58. data/lib/generators/niftier/scaffold/templates/controller.rb +3 -0
  59. data/lib/generators/niftier/scaffold/templates/fixtures.yml +9 -0
  60. data/lib/generators/niftier/scaffold/templates/helper.rb +2 -0
  61. data/lib/generators/niftier/scaffold/templates/migration.rb +16 -0
  62. data/lib/generators/niftier/scaffold/templates/model.rb +3 -0
  63. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/create.rb +11 -0
  64. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/destroy.rb +6 -0
  65. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/edit.rb +4 -0
  66. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/index.rb +4 -0
  67. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/new.rb +4 -0
  68. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/show.rb +4 -0
  69. data/lib/generators/niftier/scaffold/templates/tests/rspec/actions/update.rb +11 -0
  70. data/lib/generators/niftier/scaffold/templates/tests/rspec/controller.rb +8 -0
  71. data/lib/generators/niftier/scaffold/templates/tests/rspec/model.rb +7 -0
  72. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/create.rb +13 -0
  73. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/destroy.rb +8 -0
  74. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/edit.rb +6 -0
  75. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/index.rb +6 -0
  76. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/new.rb +6 -0
  77. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/show.rb +6 -0
  78. data/lib/generators/niftier/scaffold/templates/tests/shoulda/actions/update.rb +13 -0
  79. data/lib/generators/niftier/scaffold/templates/tests/shoulda/controller.rb +5 -0
  80. data/lib/generators/niftier/scaffold/templates/tests/shoulda/model.rb +7 -0
  81. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/create.rb +11 -0
  82. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/destroy.rb +6 -0
  83. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/edit.rb +4 -0
  84. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/index.rb +4 -0
  85. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/new.rb +4 -0
  86. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/show.rb +4 -0
  87. data/lib/generators/niftier/scaffold/templates/tests/testunit/actions/update.rb +11 -0
  88. data/lib/generators/niftier/scaffold/templates/tests/testunit/controller.rb +5 -0
  89. data/lib/generators/niftier/scaffold/templates/tests/testunit/model.rb +7 -0
  90. data/lib/generators/niftier/scaffold/templates/views/erb/_form.html.erb +10 -0
  91. data/lib/generators/niftier/scaffold/templates/views/erb/edit.html.erb +14 -0
  92. data/lib/generators/niftier/scaffold/templates/views/erb/index.html.erb +29 -0
  93. data/lib/generators/niftier/scaffold/templates/views/erb/new.html.erb +7 -0
  94. data/lib/generators/niftier/scaffold/templates/views/erb/show.html.erb +20 -0
  95. data/lib/generators/niftier/scaffold/templates/views/haml/_form.html.haml +10 -0
  96. data/lib/generators/niftier/scaffold/templates/views/haml/edit.html.haml +14 -0
  97. data/lib/generators/niftier/scaffold/templates/views/haml/index.html.haml +25 -0
  98. data/lib/generators/niftier/scaffold/templates/views/haml/new.html.haml +7 -0
  99. data/lib/generators/niftier/scaffold/templates/views/haml/show.html.haml +20 -0
  100. data/lib/generators/niftier.rb +15 -0
  101. data/test/test_helper.rb +119 -0
  102. data/test/test_niftier_authentication_generator.rb +274 -0
  103. data/test/test_niftier_config_generator.rb +37 -0
  104. data/test/test_niftier_layout_generator.rb +42 -0
  105. data/test/test_niftier_scaffold_generator.rb +534 -0
  106. metadata +173 -0
@@ -0,0 +1,24 @@
1
+ - title "Sign up"
2
+
3
+ %p== Already have an account? #{link_to "Log in", login_path}.
4
+
5
+ - form_for @<%= user_singular_name %> do |f|
6
+ = f.error_messages
7
+ %p
8
+ = f.label :username
9
+ %br
10
+ = f.text_field :username
11
+ %p
12
+ = f.label :email, "Email Address"
13
+ %br
14
+ = f.text_field :email
15
+ %p
16
+ = f.label :password
17
+ %br
18
+ = f.password_field :password
19
+ %p
20
+ = f.label :password_confirmation, "Confirm Password"
21
+ %br
22
+ = f.password_field :password_confirmation
23
+ %p
24
+ = f.submit "Sign up"
@@ -0,0 +1,23 @@
1
+ Description:
2
+ The niftier_config generator creates YAML file in your config
3
+ directory and an initializer to load this config. The config has a
4
+ separate section for each environment. This is a great place to put
5
+ any config settings you don't want in your app.
6
+
7
+ The config is loaded into a constant called APP_CONFIG by default,
8
+ this changes depending on the name you choose to pass the generator.
9
+ Use this constant to access the config settings like this.
10
+
11
+ APP_CONFIG[:some_setting]
12
+
13
+
14
+ Examples:
15
+ rails generate niftier:config
16
+
17
+ Config: config/app_config.yml
18
+ Initializer: config/initializers/load_app_config.rb
19
+
20
+ rails generate niftier:config passwords
21
+
22
+ Config: config/passwords_config.yml
23
+ Initializer: config/initializers/load_passwords_config.rb
@@ -0,0 +1,24 @@
1
+ require 'generators/niftier'
2
+
3
+ module Niftier
4
+ module Generators
5
+ class ConfigGenerator < Base
6
+ argument :config_name, :type => :string, :default => 'app', :banner => 'config_name'
7
+
8
+ def create_config
9
+ template "load_config.rb", "config/initializers/load_#{file_name}_config.rb"
10
+ copy_file "config.yml", "config/#{file_name}_config.yml"
11
+ end
12
+
13
+ private
14
+
15
+ def file_name
16
+ config_name.underscore
17
+ end
18
+
19
+ def constant_name
20
+ config_name.underscore.upcase
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ global: &global_settings
2
+ site_name: Site Name
3
+
4
+ development:
5
+ domain: localhost:3000
6
+ <<: *global_settings
7
+
8
+ test:
9
+ domain: test.host
10
+ <<: *global_settings
11
+
12
+ production:
13
+ domain: example.com
14
+ <<: *global_settings
@@ -0,0 +1,2 @@
1
+ raw_config = File.read("#{Rails.root}/config/<%= file_name %>_config.yml")
2
+ <%= constant_name %>_CONFIG = YAML.load(raw_config)[Rails.env].symbolize_keys
@@ -0,0 +1,25 @@
1
+ Description:
2
+ The niftier_layout generator creates a basic layout, stylesheet and
3
+ helper which will give some structure to a starting Rails app.
4
+
5
+ The generator takes one argument which will be the name of the
6
+ layout and stylesheet files. If no argument is passed then it defaults
7
+ to "application".
8
+
9
+ The helper module includes some methods which can be called in any
10
+ template or partial to set variables to be used in the layout, such as
11
+ page title and javascript/stylesheet includes.
12
+
13
+ Examples:
14
+ rails generate niftier:layout
15
+
16
+ Layout: app/views/layouts/application.html.erb
17
+ Stylesheet: public/stylesheets/application.css
18
+ Helper: app/helpers/layout_helper.rb
19
+
20
+
21
+ rails generate niftier:layout admin
22
+
23
+ Layout: app/views/layouts/admin.html.erb
24
+ Stylesheet: public/stylesheets/admin.css
25
+ Helper: app/helpers/layout_helper.rb
@@ -0,0 +1,29 @@
1
+ require 'generators/niftier'
2
+
3
+ module Niftier
4
+ module Generators
5
+ class LayoutGenerator < Base
6
+ argument :layout_name, :type => :string, :default => 'application', :banner => 'layout_name'
7
+
8
+ class_option :haml, :desc => 'Generate HAML for view, and SASS for stylesheet.', :type => :boolean
9
+
10
+ def create_layout
11
+ if options.haml?
12
+ template 'layout.html.haml', "app/views/layouts/#{file_name}.html.haml"
13
+ copy_file 'stylesheet.sass', "public/stylesheets/sass/#{file_name}.sass"
14
+ else
15
+ template 'layout.html.erb', "app/views/layouts/#{file_name}.html.erb"
16
+ copy_file 'stylesheet.css', "public/stylesheets/#{file_name}.css"
17
+ end
18
+ copy_file 'layout_helper.rb', 'app/helpers/layout_helper.rb'
19
+ copy_file 'error_messages_helper.rb', 'app/helpers/error_messages_helper.rb'
20
+ end
21
+
22
+ private
23
+
24
+ def file_name
25
+ layout_name.underscore
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module ErrorMessagesHelper
2
+ # Render error messages for the given objects. The :message and :header_message options are allowed.
3
+ def error_messages_for(*objects)
4
+ options = objects.extract_options!
5
+ options[:header_message] ||= "Invalid Fields"
6
+ options[:message] ||= "Correct the following errors and try again."
7
+ messages = objects.compact.map { |o| o.errors.full_messages }.flatten
8
+ unless messages.empty?
9
+ content_tag(:div, :class => "error_messages") do
10
+ list_items = messages.map { |msg| content_tag(:li, msg) }
11
+ content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe)
12
+ end
13
+ end
14
+ end
15
+
16
+ module FormBuilderAdditions
17
+ def error_messages(options = {})
18
+ @template.error_messages_for(@object, options)
19
+ end
20
+ end
21
+ end
22
+
23
+ ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions)
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%%= content_for?(:title) ? yield(:title) : "Untitled" %></title>
5
+ <%% stylesheet "<%= file_name %>" %>
6
+ <%% javascript :defaults %>
7
+ <%%= csrf_meta_tag %>
8
+ <%%= yield(:stylesheets) %>
9
+ </head>
10
+ <body>
11
+ <div id="container">
12
+ <%% flash.each do |name, msg| %>
13
+ <%%= content_tag :div, msg, :id => "flash_#{name}" %>
14
+ <%% end %>
15
+ <%%= content_tag :h1, yield(:title) if show_title? %>
16
+ <%%= yield %>
17
+ </div>
18
+
19
+ <%%= yield(:javascripts) %>
20
+ <%% if content_for?(:onload_scripts) %>
21
+ <%%= javascript_tag "$(document).ready(function() { #{yield(:onload_scripts)} });" %>
22
+ <%% end %>
23
+ </body>
24
+ </html>
@@ -0,0 +1,26 @@
1
+ !!!
2
+ %html
3
+
4
+ %head
5
+ %title
6
+ = content_for?(:title) ? yield(:title) : "Untitled"
7
+ %meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}/
8
+ - stylesheet "<%= file_name %>"
9
+ - javascript :defaults
10
+ = csrf_meta_tag
11
+ = yield(:stylesheets)
12
+
13
+ %body
14
+ #container
15
+ - flash.each do |name, msg|
16
+ = content_tag :div, msg, :id => "flash_#{name}"
17
+
18
+ - if show_title?
19
+ %h1= yield(:title)
20
+
21
+ = yield
22
+
23
+ = yield(:javascripts)
24
+ - if content_for?(:onload_scripts)
25
+ :javascript
26
+ $(document).ready(function() { #{yield(:onload_scripts)} });
@@ -0,0 +1,26 @@
1
+ # These helper methods can be called in your template to set variables to be used in the layout
2
+ # This module should be included in all views globally,
3
+ # to do so you may need to add this line to your ApplicationController
4
+ # helper :layout
5
+ module LayoutHelper
6
+ def title(page_title, show_title = true)
7
+ content_for(:title) { page_title.to_s }
8
+ @show_title = show_title
9
+ end
10
+
11
+ def show_title?
12
+ @show_title
13
+ end
14
+
15
+ def stylesheet(*args)
16
+ content_for(:stylesheets) { stylesheet_link_tag(*args) }
17
+ end
18
+
19
+ def javascript(*args)
20
+ content_for(:javascripts) { javascript_include_tag(*args) }
21
+ end
22
+
23
+ def onload(str)
24
+ content_for(:onload_scripts) { str + "\n" }
25
+ end
26
+ end
@@ -0,0 +1,75 @@
1
+ body {
2
+ background-color: #4B7399;
3
+ font-family: Verdana, Helvetica, Arial;
4
+ font-size: 14px;
5
+ }
6
+
7
+ a img {
8
+ border: none;
9
+ }
10
+
11
+ a {
12
+ color: #0000FF;
13
+ }
14
+
15
+ .clear {
16
+ clear: both;
17
+ height: 0;
18
+ overflow: hidden;
19
+ }
20
+
21
+ #container {
22
+ width: 75%;
23
+ margin: 0 auto;
24
+ background-color: #FFF;
25
+ padding: 20px 40px;
26
+ border: solid 1px black;
27
+ margin-top: 20px;
28
+ }
29
+
30
+ #flash_notice, #flash_error, #flash_alert {
31
+ padding: 5px 8px;
32
+ margin: 10px 0;
33
+ }
34
+
35
+ #flash_notice {
36
+ background-color: #CFC;
37
+ border: solid 1px #6C6;
38
+ }
39
+
40
+ #flash_error, #flash_alert {
41
+ background-color: #FCC;
42
+ border: solid 1px #C66;
43
+ }
44
+
45
+ .fieldWithErrors {
46
+ display: inline;
47
+ }
48
+
49
+ .error_messages {
50
+ width: 400px;
51
+ border: 2px solid #CF0000;
52
+ padding: 0px;
53
+ padding-bottom: 12px;
54
+ margin-bottom: 20px;
55
+ background-color: #f0f0f0;
56
+ font-size: 12px;
57
+ }
58
+
59
+ .error_messages h2 {
60
+ text-align: left;
61
+ font-weight: bold;
62
+ padding: 5px 10px;
63
+ font-size: 12px;
64
+ margin: 0;
65
+ background-color: #c00;
66
+ color: #fff;
67
+ }
68
+
69
+ .error_messages p {
70
+ margin: 8px 10px;
71
+ }
72
+
73
+ .error_messages ul {
74
+ margin: 0;
75
+ }
@@ -0,0 +1,66 @@
1
+ !primary_color = #4B7399
2
+
3
+ body
4
+ background-color = !primary_color
5
+ font:
6
+ family: Verdana, Helvetica, Arial
7
+ size: 14px
8
+
9
+ a
10
+ color: #0000FF
11
+ img
12
+ border: none
13
+
14
+ .clear
15
+ clear: both
16
+ height: 0
17
+ overflow: hidden
18
+
19
+ #container
20
+ width: 75%
21
+ margin: 0 auto
22
+ background: #fff
23
+ padding: 20px 40px
24
+ border: solid 1px black
25
+ margin-top: 20px
26
+
27
+ #flash_notice,
28
+ #flash_error,
29
+ #flash_alert
30
+ padding: 5px 8px
31
+ margin: 10px 0
32
+
33
+ #flash_notice
34
+ background-color: #CFC
35
+ border: solid 1px #6C6
36
+
37
+ #flash_error,
38
+ #flash_alert
39
+ background-color: #FCC
40
+ border: solid 1px #C66
41
+
42
+ .fieldWithErrors
43
+ display: inline
44
+
45
+ .error_messages
46
+ width: 400px
47
+ border: 2px solid #CF0000
48
+ padding: 0
49
+ padding-bottom: 12px
50
+ margin-bottom: 20px
51
+ background-color: #f0f0f0
52
+ font:
53
+ size: 12px
54
+ h2
55
+ text-align: left
56
+ padding: 5px 5px 5px 15px
57
+ margin: 0
58
+ font:
59
+ weight: bold
60
+ size: 12px
61
+ background-color: #c00
62
+ color: #fff
63
+ p
64
+ margin: 8px 10px
65
+ ul
66
+ margin: 0
@@ -0,0 +1,51 @@
1
+ Description:
2
+ Scaffolds an entire resource, from model and migration to controller and
3
+ views. The resource is ready to use as a starting point for your restful,
4
+ resource-oriented application. Tests or specs are also generated depending
5
+ on if you have a "spec" directory or not.
6
+
7
+ IMPORTANT: This generator uses the "title" helper method which is generated
8
+ by the niftier_layout generator. You may want to run that generator first.
9
+
10
+ Usage:
11
+ Pass the name of the model, either CamelCased or under_scored, as the first
12
+ argument along with an optional list of attribute pairs and controller actions.
13
+
14
+ If no controller actions are specified, they will default to index, show,
15
+ new, create, edit, update, and destroy.
16
+
17
+ IMPORTANT: If no attribute pairs are specified, no model will be generated.
18
+ It will try to determine the attributes from an existing model.
19
+
20
+ Attribute pairs are column_name:sql_type arguments specifying the
21
+ model's attributes. Timestamps are added by default, so you don't have to
22
+ specify them by hand as 'created_at:datetime updated_at:datetime'.
23
+
24
+ For example, `niftier:scaffold post name:string content:text hidden:boolean`
25
+ gives you a model with those three attributes, a controller that handles
26
+ the create/show/update/destroy, forms to create and edit your posts, and
27
+ an index that lists them all, as well as a map.resources :posts
28
+ declaration in config/routes.rb.
29
+
30
+ Adding an "!" in the mix of arguments will invert the passed controller
31
+ actions. This will include all 7 controller actitons except the ones
32
+ mentioned. This option doesn't affect model attributes.
33
+
34
+ Examples:
35
+ rails generate niftier:scaffold post
36
+
37
+ Will create a controller called "posts" it will contain all seven
38
+ CRUD actions along with the views. A model will NOT be created,
39
+ instead it will look for an existing model and use those attributes.
40
+
41
+ rails generate niftier:scaffold post name:string content:text index new edit
42
+
43
+ Will create a Post model and migration file with the name and content
44
+ attributes. It will also create a controller with index, new, create,
45
+ edit, and update actions. Notice the create and update actions are
46
+ added automatically with new and edit.
47
+
48
+ rails generate niftier:scaffold post ! show new
49
+
50
+ Creates a posts controller (no model) with index, edit, update, and
51
+ destroy actions.
@@ -0,0 +1,241 @@
1
+ require 'generators/niftier'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/generated_attribute'
4
+
5
+ module Niftier
6
+ module Generators
7
+ class ScaffoldGenerator < Base
8
+ include Rails::Generators::Migration
9
+ no_tasks { attr_accessor :model_name, :model_attributes, :controller_actions }
10
+
11
+ argument :model_name, :type => :string, :required => true, :banner => 'ModelName'
12
+ argument :args_for_c_m, :type => :array, :default => [], :banner => 'controller_actions and model:attributes'
13
+
14
+ class_option :skip_model, :desc => 'Don\'t generate a model or migration file.', :type => :boolean
15
+ class_option :skip_migration, :desc => 'Dont generate migration file for model.', :type => :boolean
16
+ class_option :skip_timestamps, :desc => 'Don\'t add timestamps to migration file.', :type => :boolean
17
+ class_option :skip_controller, :desc => 'Don\'t generate controller, helper, or views.', :type => :boolean
18
+ class_option :invert, :desc => 'Generate all controller actions except these mentioned.', :type => :boolean
19
+ class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean
20
+
21
+ class_option :testunit, :desc => 'Use test/unit for test files.', :group => 'Test framework', :type => :boolean
22
+ class_option :rspec, :desc => 'Use RSpec for test files.', :group => 'Test framework', :type => :boolean
23
+ class_option :shoulda, :desc => 'Use shoulda for test files.', :group => 'Test framework', :type => :boolean
24
+
25
+ def initialize(*args, &block)
26
+ super
27
+
28
+ @controller_actions = []
29
+ @model_attributes = []
30
+
31
+ args_for_c_m.each do |arg|
32
+ if arg == '!'
33
+ options[:invert] = true
34
+ elsif arg.include?(':')
35
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(*arg.split(':'))
36
+ else
37
+ @controller_actions << arg
38
+ @controller_actions << 'create' if arg == 'new'
39
+ @controller_actions << 'update' if arg == 'edit'
40
+ end
41
+ end
42
+
43
+ @controller_actions.uniq!
44
+ @model_attributes.uniq!
45
+
46
+ if options.invert? || @controller_actions.empty?
47
+ @controller_actions = all_actions - @controller_actions
48
+ end
49
+
50
+ if @model_attributes.empty?
51
+ options[:skip_model] = true # default to skipping model if no attributes passed
52
+ if model_exists?
53
+ model_columns_for_attributes.each do |column|
54
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(column.name.to_s, column.type.to_s)
55
+ end
56
+ else
57
+ @model_attributes << Rails::Generators::GeneratedAttribute.new('name', 'string')
58
+ end
59
+ end
60
+ end
61
+
62
+ def create_model
63
+ unless options.skip_model?
64
+ template 'model.rb', "app/models/#{singular_name}.rb"
65
+ if options.rspec?
66
+ template "tests/rspec/model.rb", "spec/models/#{singular_name}_spec.rb"
67
+ template 'fixtures.yml', "spec/fixtures/#{plural_name}.yml"
68
+ else
69
+ template "tests/#{test_framework}/model.rb", "test/unit/#{singular_name}_test.rb"
70
+ template 'fixtures.yml', "test/fixtures/#{plural_name}.yml"
71
+ end
72
+ end
73
+ end
74
+
75
+ def create_migration
76
+ unless options.skip_model? || options.skip_migration?
77
+ migration_template 'migration.rb', "db/migrate/create_#{plural_name}.rb"
78
+ end
79
+ end
80
+
81
+ def create_controller
82
+ unless options.skip_controller?
83
+ template 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
84
+
85
+ template 'helper.rb', "app/helpers/#{plural_name}_helper.rb"
86
+
87
+ controller_actions.each do |action|
88
+ if %w[index show new edit].include?(action) # Actions with templates
89
+ template "views/#{view_language}/#{action}.html.#{view_language}", "app/views/#{plural_name}/#{action}.html.#{view_language}"
90
+ end
91
+ end
92
+
93
+ if form_partial?
94
+ template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{plural_name}/_form.html.#{view_language}"
95
+ end
96
+
97
+ route "resources #{plural_name.to_sym.inspect}"
98
+
99
+ if options.rspec?
100
+ template "tests/#{test_framework}/controller.rb", "spec/controllers/#{plural_name}_controller_spec.rb"
101
+ else
102
+ template "tests/#{test_framework}/controller.rb", "test/functional/#{plural_name}_controller_test.rb"
103
+ end
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def form_partial?
110
+ actions? :new, :edit
111
+ end
112
+
113
+ def all_actions
114
+ %w[index show new create edit update destroy]
115
+ end
116
+
117
+ def action?(name)
118
+ controller_actions.include? name.to_s
119
+ end
120
+
121
+ def actions?(*names)
122
+ names.all? { |name| action? name }
123
+ end
124
+
125
+ def singular_name
126
+ model_name.underscore
127
+ end
128
+
129
+ def plural_name
130
+ model_name.underscore.pluralize
131
+ end
132
+
133
+ def class_name
134
+ model_name.camelize
135
+ end
136
+
137
+ def plural_class_name
138
+ plural_name.camelize
139
+ end
140
+
141
+ def controller_methods(dir_name)
142
+ controller_actions.map do |action|
143
+ read_template("#{dir_name}/#{action}.rb")
144
+ end.join(" \n").strip
145
+ end
146
+
147
+ def render_form
148
+ if form_partial?
149
+ if options.haml?
150
+ "= render 'form'"
151
+ else
152
+ "<%= render 'form' %>"
153
+ end
154
+ else
155
+ read_template("views/#{view_language}/_form.html.#{view_language}")
156
+ end
157
+ end
158
+
159
+ def items_path(suffix = 'path')
160
+ if action? :index
161
+ "#{plural_name}_#{suffix}"
162
+ else
163
+ "root_#{suffix}"
164
+ end
165
+ end
166
+
167
+ def item_path(suffix = 'path')
168
+ if action? :show
169
+ "@#{singular_name}"
170
+ else
171
+ items_path(suffix)
172
+ end
173
+ end
174
+
175
+ def item_path_for_spec(suffix = 'path')
176
+ if action? :show
177
+ "#{singular_name}_#{suffix}(assigns[:#{singular_name}])"
178
+ else
179
+ items_path(suffix)
180
+ end
181
+ end
182
+
183
+ def item_path_for_test(suffix = 'path')
184
+ if action? :show
185
+ "#{singular_name}_#{suffix}(assigns(:#{singular_name}))"
186
+ else
187
+ items_path(suffix)
188
+ end
189
+ end
190
+
191
+ def model_columns_for_attributes
192
+ class_name.constantize.columns.reject do |column|
193
+ column.name.to_s =~ /^(id|created_at|updated_at)$/
194
+ end
195
+ end
196
+
197
+ def view_language
198
+ options.haml? ? 'haml' : 'erb'
199
+ end
200
+
201
+ def test_framework
202
+ return @test_framework if defined?(@test_framework)
203
+ if options.testunit?
204
+ return @test_framework = :testunit
205
+ elsif options.rspec?
206
+ return @test_framework = :rspec
207
+ elsif options.shoulda?
208
+ return @test_framework = :shoulda
209
+ else
210
+ return @test_framework = default_test_framework
211
+ end
212
+ end
213
+
214
+ def default_test_framework
215
+ File.exist?(destination_path("spec")) ? :rspec : :testunit
216
+ end
217
+
218
+ def model_exists?
219
+ File.exist? destination_path("app/models/#{singular_name}.rb")
220
+ end
221
+
222
+ def read_template(relative_path)
223
+ ERB.new(File.read(find_in_source_paths(relative_path)), nil, '-').result(binding)
224
+ end
225
+
226
+ def destination_path(path)
227
+ File.join(destination_root, path)
228
+ end
229
+
230
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
231
+ # Implement the required interface for Rails::Generators::Migration.
232
+ def self.next_migration_number(dirname) #:nodoc:
233
+ if ActiveRecord::Base.timestamped_migrations
234
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
235
+ else
236
+ "%.3d" % (current_migration_number(dirname) + 1)
237
+ end
238
+ end
239
+ end
240
+ end
241
+ end