niftier-generators 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 (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