nifty-generators-improved 0.5

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 (112) hide show
  1. data/CHANGELOG +198 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +111 -0
  4. data/LICENSE +20 -0
  5. data/README.rdoc +109 -0
  6. data/Rakefile +10 -0
  7. data/features/nifty_authentication.feature +80 -0
  8. data/features/nifty_config.feature +17 -0
  9. data/features/nifty_layout.feature +20 -0
  10. data/features/nifty_scaffold.feature +80 -0
  11. data/features/step_definitions/common_steps.rb +62 -0
  12. data/features/step_definitions/rails_setup_steps.rb +6 -0
  13. data/features/support/env.rb +6 -0
  14. data/features/support/matchers.rb +7 -0
  15. data/lib/generators/nifty.rb +28 -0
  16. data/lib/generators/nifty/authentication/USAGE +50 -0
  17. data/lib/generators/nifty/authentication/authentication_generator.rb +154 -0
  18. data/lib/generators/nifty/authentication/templates/authlogic_session.rb +2 -0
  19. data/lib/generators/nifty/authentication/templates/controller_authentication.rb +60 -0
  20. data/lib/generators/nifty/authentication/templates/fixtures.yml +24 -0
  21. data/lib/generators/nifty/authentication/templates/migration.rb +20 -0
  22. data/lib/generators/nifty/authentication/templates/sessions_controller.rb +41 -0
  23. data/lib/generators/nifty/authentication/templates/sessions_helper.rb +2 -0
  24. data/lib/generators/nifty/authentication/templates/tests/rspec/sessions_controller.rb +39 -0
  25. data/lib/generators/nifty/authentication/templates/tests/rspec/user.rb +83 -0
  26. data/lib/generators/nifty/authentication/templates/tests/rspec/users_controller.rb +56 -0
  27. data/lib/generators/nifty/authentication/templates/tests/shoulda/sessions_controller.rb +40 -0
  28. data/lib/generators/nifty/authentication/templates/tests/shoulda/user.rb +85 -0
  29. data/lib/generators/nifty/authentication/templates/tests/shoulda/users_controller.rb +61 -0
  30. data/lib/generators/nifty/authentication/templates/tests/testunit/sessions_controller.rb +36 -0
  31. data/lib/generators/nifty/authentication/templates/tests/testunit/user.rb +88 -0
  32. data/lib/generators/nifty/authentication/templates/tests/testunit/users_controller.rb +53 -0
  33. data/lib/generators/nifty/authentication/templates/user.rb +38 -0
  34. data/lib/generators/nifty/authentication/templates/users_controller.rb +32 -0
  35. data/lib/generators/nifty/authentication/templates/users_helper.rb +2 -0
  36. data/lib/generators/nifty/authentication/templates/views/erb/_form.html.erb +20 -0
  37. data/lib/generators/nifty/authentication/templates/views/erb/edit.html.erb +3 -0
  38. data/lib/generators/nifty/authentication/templates/views/erb/login.html.erb +30 -0
  39. data/lib/generators/nifty/authentication/templates/views/erb/signup.html.erb +5 -0
  40. data/lib/generators/nifty/authentication/templates/views/haml/_form.html.haml +16 -0
  41. data/lib/generators/nifty/authentication/templates/views/haml/edit.html.haml +3 -0
  42. data/lib/generators/nifty/authentication/templates/views/haml/login.html.haml +26 -0
  43. data/lib/generators/nifty/authentication/templates/views/haml/signup.html.haml +5 -0
  44. data/lib/generators/nifty/config/USAGE +23 -0
  45. data/lib/generators/nifty/config/config_generator.rb +24 -0
  46. data/lib/generators/nifty/config/templates/config.yml +8 -0
  47. data/lib/generators/nifty/config/templates/load_config.rb +2 -0
  48. data/lib/generators/nifty/layout/USAGE +25 -0
  49. data/lib/generators/nifty/layout/layout_generator.rb +29 -0
  50. data/lib/generators/nifty/layout/templates/error_messages_helper.rb +23 -0
  51. data/lib/generators/nifty/layout/templates/layout.html.erb +19 -0
  52. data/lib/generators/nifty/layout/templates/layout.html.haml +17 -0
  53. data/lib/generators/nifty/layout/templates/layout_helper.rb +17 -0
  54. data/lib/generators/nifty/layout/templates/stylesheet.css +83 -0
  55. data/lib/generators/nifty/layout/templates/stylesheet.css.scss +88 -0
  56. data/lib/generators/nifty/scaffold/USAGE +51 -0
  57. data/lib/generators/nifty/scaffold/scaffold_generator.rb +318 -0
  58. data/lib/generators/nifty/scaffold/templates/actions/create.rb +8 -0
  59. data/lib/generators/nifty/scaffold/templates/actions/destroy.rb +5 -0
  60. data/lib/generators/nifty/scaffold/templates/actions/edit.rb +3 -0
  61. data/lib/generators/nifty/scaffold/templates/actions/index.rb +3 -0
  62. data/lib/generators/nifty/scaffold/templates/actions/new.rb +3 -0
  63. data/lib/generators/nifty/scaffold/templates/actions/show.rb +3 -0
  64. data/lib/generators/nifty/scaffold/templates/actions/update.rb +8 -0
  65. data/lib/generators/nifty/scaffold/templates/controller.rb +3 -0
  66. data/lib/generators/nifty/scaffold/templates/fixtures.yml +9 -0
  67. data/lib/generators/nifty/scaffold/templates/helper.rb +2 -0
  68. data/lib/generators/nifty/scaffold/templates/migration.rb +16 -0
  69. data/lib/generators/nifty/scaffold/templates/model.rb +4 -0
  70. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/create.rb +11 -0
  71. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/destroy.rb +6 -0
  72. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/edit.rb +4 -0
  73. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/index.rb +4 -0
  74. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/new.rb +4 -0
  75. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/show.rb +4 -0
  76. data/lib/generators/nifty/scaffold/templates/tests/rspec/actions/update.rb +11 -0
  77. data/lib/generators/nifty/scaffold/templates/tests/rspec/controller.rb +8 -0
  78. data/lib/generators/nifty/scaffold/templates/tests/rspec/model.rb +7 -0
  79. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/create.rb +13 -0
  80. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/destroy.rb +8 -0
  81. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/edit.rb +6 -0
  82. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/index.rb +6 -0
  83. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/new.rb +6 -0
  84. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/show.rb +6 -0
  85. data/lib/generators/nifty/scaffold/templates/tests/shoulda/actions/update.rb +13 -0
  86. data/lib/generators/nifty/scaffold/templates/tests/shoulda/controller.rb +5 -0
  87. data/lib/generators/nifty/scaffold/templates/tests/shoulda/model.rb +7 -0
  88. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/create.rb +11 -0
  89. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/destroy.rb +6 -0
  90. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/edit.rb +4 -0
  91. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/index.rb +4 -0
  92. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/new.rb +4 -0
  93. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/show.rb +4 -0
  94. data/lib/generators/nifty/scaffold/templates/tests/testunit/actions/update.rb +11 -0
  95. data/lib/generators/nifty/scaffold/templates/tests/testunit/controller.rb +5 -0
  96. data/lib/generators/nifty/scaffold/templates/tests/testunit/model.rb +7 -0
  97. data/lib/generators/nifty/scaffold/templates/views/erb/_form.html.erb +10 -0
  98. data/lib/generators/nifty/scaffold/templates/views/erb/edit.html.erb +14 -0
  99. data/lib/generators/nifty/scaffold/templates/views/erb/index.html.erb +29 -0
  100. data/lib/generators/nifty/scaffold/templates/views/erb/new.html.erb +7 -0
  101. data/lib/generators/nifty/scaffold/templates/views/erb/show.html.erb +20 -0
  102. data/lib/generators/nifty/scaffold/templates/views/haml/_form.html.haml +9 -0
  103. data/lib/generators/nifty/scaffold/templates/views/haml/edit.html.haml +14 -0
  104. data/lib/generators/nifty/scaffold/templates/views/haml/index.html.haml +25 -0
  105. data/lib/generators/nifty/scaffold/templates/views/haml/new.html.haml +7 -0
  106. data/lib/generators/nifty/scaffold/templates/views/haml/show.html.haml +20 -0
  107. data/test/test_helper.rb +119 -0
  108. data/test/test_nifty_authentication_generator.rb +274 -0
  109. data/test/test_nifty_config_generator.rb +37 -0
  110. data/test/test_nifty_layout_generator.rb +42 -0
  111. data/test/test_nifty_scaffold_generator.rb +534 -0
  112. metadata +231 -0
@@ -0,0 +1,24 @@
1
+ require 'generators/nifty'
2
+
3
+ module Nifty
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,8 @@
1
+ development:
2
+ domain: localhost:3000
3
+
4
+ test:
5
+ domain: test.host
6
+
7
+ production:
8
+ domain: example.com
@@ -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 nifty_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 nifty: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 nifty: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/nifty'
2
+
3
+ module Nifty
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.css.scss', "app/assets/stylesheets/#{file_name}.scss"
14
+ else
15
+ template 'layout.html.erb', "app/views/layouts/#{file_name}.html.erb"
16
+ copy_file 'stylesheet.css', "app/assets/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] ||= I18n.t(:"activerecord.errors.header", :default => "Invalid Fields")
6
+ options[:message] ||= I18n.t(:"activerecord.errors.message", :default => "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.html_safe) }
11
+ content_tag(:h2, options[:header_message].html_safe) + content_tag(:p, options[:message].html_safe) + 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,19 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%%= content_for?(:title) ? yield(:title) : "Untitled" %></title>
5
+ <%%= stylesheet_link_tag "<%= file_name %>" %>
6
+ <%%= javascript_include_tag :defaults %>
7
+ <%%= csrf_meta_tag %>
8
+ <%%= yield(:head) %>
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) %>
16
+ <%%= yield %>
17
+ </div>
18
+ </body>
19
+ </html>
@@ -0,0 +1,17 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= yield(:title) || "Untitled"
5
+ = stylesheet_link_tag "<%= file_name %>"
6
+ = javascript_include_tag :defaults
7
+ = csrf_meta_tag
8
+ = yield(:head)
9
+ %body
10
+ #container
11
+ - flash.each do |name, msg|
12
+ = content_tag :div, msg, :id => "flash_#{name}"
13
+
14
+ %header
15
+ %h1= yield(:title)
16
+
17
+ = yield
@@ -0,0 +1,17 @@
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)
7
+ content_for(:title) { h(page_title.to_s) }
8
+ end
9
+
10
+ def stylesheet(*args)
11
+ content_for(:head) { stylesheet_link_tag(*args) }
12
+ end
13
+
14
+ def javascript(*args)
15
+ content_for(:head) { javascript_include_tag(*args) }
16
+ end
17
+ end
@@ -0,0 +1,83 @@
1
+ html, 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
+ .error_messages {
46
+ width: 400px;
47
+ border: 2px solid #CF0000;
48
+ padding: 0px;
49
+ padding-bottom: 12px;
50
+ margin-bottom: 20px;
51
+ background-color: #f0f0f0;
52
+ font-size: 12px;
53
+ }
54
+
55
+ .error_messages h2 {
56
+ text-align: left;
57
+ font-weight: bold;
58
+ padding: 5px 10px;
59
+ font-size: 12px;
60
+ margin: 0;
61
+ background-color: #c00;
62
+ color: #fff;
63
+ }
64
+
65
+ .error_messages p {
66
+ margin: 8px 10px;
67
+ }
68
+
69
+ .error_messages ul {
70
+ margin: 0;
71
+ }
72
+
73
+ .field_with_errors {
74
+ display: inline;
75
+ }
76
+
77
+ form .field, form .actions {
78
+ margin: 10px 0;
79
+ }
80
+
81
+ form label {
82
+ display: block;
83
+ }
@@ -0,0 +1,88 @@
1
+ $primary_color: #4b7399;
2
+
3
+ body {
4
+ background-color: $primary_color;
5
+ font-family: Verdana, Helvetica, Arial;
6
+ font-size: 14px;
7
+ }
8
+
9
+ a{
10
+ color: blue;
11
+ img{
12
+ border: none;
13
+ }
14
+ }
15
+
16
+ .clear {
17
+ clear: both;
18
+ height: 0;
19
+ overflow: hidden;
20
+ }
21
+
22
+ #container {
23
+ width: 75%;
24
+ margin: 0 auto;
25
+ background: white;
26
+ padding: 20px 40px;
27
+ border: solid 1px black;
28
+ margin-top: 20px;
29
+ }
30
+
31
+ #flash_notice,
32
+ #flash_error,
33
+ #flash_alert {
34
+ padding: 5px 8px;
35
+ margin: 10px 0;
36
+ }
37
+
38
+ #flash_notice {
39
+ background-color: #ccffcc;
40
+ border: solid 1px #66cc66;
41
+ }
42
+
43
+ #flash_error,
44
+ #flash_alert {
45
+ background-color: #ffcccc;
46
+ border: solid 1px #cc6666;
47
+ }
48
+
49
+ .error_messages {
50
+ width: 400px;
51
+ border: 2px solid #cf0000;
52
+ padding: 0;
53
+ padding-bottom: 12px;
54
+ margin-bottom: 20px;
55
+ background-color: #f0f0f0;
56
+ font-size: 12px;
57
+
58
+ h2 {
59
+ text-align: left;
60
+ padding: 5px 5px 5px 15px;
61
+ margin: 0;
62
+ font-weight: bold;
63
+ font-size: 12px;
64
+ background-color: #cc0000;
65
+ color: white;
66
+ }
67
+
68
+ p {
69
+ margin: 8px 10px;
70
+ }
71
+
72
+ ul {
73
+ margin: 0;
74
+ }
75
+ }
76
+
77
+ .field_with_errors {
78
+ display: inline;
79
+ }
80
+
81
+ form .field,
82
+ form .actions {
83
+ margin: 10px 0;
84
+ }
85
+
86
+ form label {
87
+ display: block;
88
+ }
@@ -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 nifty_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, `nifty: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 nifty: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 nifty: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 nifty:scaffold post ! show new
49
+
50
+ Creates a posts controller (no model) with index, edit, update, and
51
+ destroy actions.
@@ -0,0 +1,318 @@
1
+ require 'generators/nifty'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/generated_attribute'
4
+
5
+ module Nifty
6
+ module Generators
7
+ class ScaffoldGenerator < Base
8
+ include Rails::Generators::Migration
9
+ no_tasks { attr_accessor :scaffold_name, :model_attributes, :controller_actions }
10
+
11
+ argument :scaffold_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 :namespace_model, :desc => 'If the resource is namespaced, include the model in the namespace.', :type => :boolean
20
+ class_option :haml, :desc => 'Generate HAML views instead of ERB.', :type => :boolean
21
+
22
+ class_option :testunit, :desc => 'Use test/unit for test files.', :group => 'Test framework', :type => :boolean
23
+ class_option :rspec, :desc => 'Use RSpec for test files.', :group => 'Test framework', :type => :boolean
24
+ class_option :shoulda, :desc => 'Use shoulda for test files.', :group => 'Test framework', :type => :boolean
25
+
26
+ def initialize(*args, &block)
27
+ super
28
+
29
+ print_usage unless scaffold_name.underscore =~ /^[a-z][a-z0-9_\/]+$/
30
+
31
+ @controller_actions = []
32
+ @model_attributes = []
33
+ @skip_model = options.skip_model?
34
+ @namespace_model = options.namespace_model?
35
+ @invert_actions = options.invert?
36
+
37
+ args_for_c_m.each do |arg|
38
+ if arg == '!'
39
+ @invert_actions = true
40
+ elsif arg.include?(':')
41
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(*arg.split(':'))
42
+ else
43
+ @controller_actions << arg
44
+ @controller_actions << 'create' if arg == 'new'
45
+ @controller_actions << 'update' if arg == 'edit'
46
+ end
47
+ end
48
+
49
+ @controller_actions.uniq!
50
+ @model_attributes.uniq!
51
+
52
+ if @invert_actions || @controller_actions.empty?
53
+ @controller_actions = all_actions - @controller_actions
54
+ end
55
+
56
+ if @model_attributes.empty?
57
+ @skip_model = true # skip model if no attributes
58
+ if model_exists?
59
+ model_columns_for_attributes.each do |column|
60
+ @model_attributes << Rails::Generators::GeneratedAttribute.new(column.name.to_s, column.type.to_s)
61
+ end
62
+ else
63
+ @model_attributes << Rails::Generators::GeneratedAttribute.new('name', 'string')
64
+ end
65
+ end
66
+ end
67
+
68
+ def add_gems
69
+ add_gem "mocha", :group => :test
70
+ end
71
+
72
+ def create_model
73
+ unless @skip_model
74
+ template 'model.rb', "app/models/#{model_path}.rb"
75
+ if test_framework == :rspec
76
+ template "tests/rspec/model.rb", "spec/models/#{model_path}_spec.rb"
77
+ template 'fixtures.yml', "spec/fixtures/#{model_path.pluralize}.yml"
78
+ else
79
+ template "tests/#{test_framework}/model.rb", "test/unit/#{model_path}_test.rb"
80
+ template 'fixtures.yml', "test/fixtures/#{model_path.pluralize}.yml"
81
+ end
82
+ end
83
+ end
84
+
85
+ def create_migration
86
+ unless @skip_model || options.skip_migration?
87
+ migration_template 'migration.rb', "db/migrate/create_#{model_path.pluralize.gsub('/', '_')}.rb"
88
+ end
89
+ end
90
+
91
+ def create_controller
92
+ unless options.skip_controller?
93
+ template 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
94
+
95
+ template 'helper.rb', "app/helpers/#{plural_name}_helper.rb"
96
+
97
+ controller_actions.each do |action|
98
+ if %w[index show new edit].include?(action) # Actions with templates
99
+ template "views/#{view_language}/#{action}.html.#{view_language}", "app/views/#{plural_name}/#{action}.html.#{view_language}"
100
+ end
101
+ end
102
+
103
+ if form_partial?
104
+ template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{plural_name}/_form.html.#{view_language}"
105
+ end
106
+
107
+ namespaces = plural_name.split('/')
108
+ resource = namespaces.pop
109
+ route namespaces.reverse.inject("resources :#{resource}") { |acc, namespace|
110
+ "namespace(:#{namespace}){ #{acc} }"
111
+ }
112
+
113
+ if test_framework == :rspec
114
+ template "tests/#{test_framework}/controller.rb", "spec/controllers/#{plural_name}_controller_spec.rb"
115
+ else
116
+ template "tests/#{test_framework}/controller.rb", "test/functional/#{plural_name}_controller_test.rb"
117
+ end
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def form_partial?
124
+ actions? :new, :edit
125
+ end
126
+
127
+ def all_actions
128
+ %w[index show new create edit update destroy]
129
+ end
130
+
131
+ def action?(name)
132
+ controller_actions.include? name.to_s
133
+ end
134
+
135
+ def actions?(*names)
136
+ names.all? { |name| action? name }
137
+ end
138
+
139
+ def singular_name
140
+ scaffold_name.underscore
141
+ end
142
+
143
+ def plural_name
144
+ scaffold_name.underscore.pluralize
145
+ end
146
+
147
+ def table_name
148
+ if scaffold_name.include?('::') && @namespace_model
149
+ plural_name.gsub('/', '_')
150
+ end
151
+ end
152
+
153
+ def class_name
154
+ if @namespace_model
155
+ scaffold_name.camelize
156
+ else
157
+ scaffold_name.split('::').last.camelize
158
+ end
159
+ end
160
+
161
+ def model_path
162
+ class_name.underscore
163
+ end
164
+
165
+ def plural_class_name
166
+ plural_name.camelize
167
+ end
168
+
169
+ def instance_name
170
+ if @namespace_model
171
+ singular_name.gsub('/','_')
172
+ else
173
+ singular_name.split('/').last
174
+ end
175
+ end
176
+
177
+ def instances_name
178
+ instance_name.pluralize
179
+ end
180
+
181
+ def controller_methods(dir_name)
182
+ controller_actions.map do |action|
183
+ read_template("#{dir_name}/#{action}.rb")
184
+ end.join("\n").strip
185
+ end
186
+
187
+ def render_form
188
+ if form_partial?
189
+ if options.haml?
190
+ "= render \"form\""
191
+ else
192
+ "<%= render \"form\" %>"
193
+ end
194
+ else
195
+ read_template("views/#{view_language}/_form.html.#{view_language}")
196
+ end
197
+ end
198
+
199
+ def item_resource
200
+ scaffold_name.underscore.gsub('/','_')
201
+ end
202
+
203
+ def items_path
204
+ if action? :index
205
+ "#{item_resource.pluralize}_path"
206
+ else
207
+ "root_path"
208
+ end
209
+ end
210
+
211
+ def item_path(options = {})
212
+ name = options[:instance_variable] ? "@#{instance_name}" : instance_name
213
+ suffix = options[:full_url] ? "url" : "path"
214
+ if options[:action].to_s == "new"
215
+ "new_#{item_resource}_#{suffix}"
216
+ elsif options[:action].to_s == "edit"
217
+ "edit_#{item_resource}_#{suffix}(#{name})"
218
+ else
219
+ if scaffold_name.include?('::') && !@namespace_model
220
+ namespace = singular_name.split('/')[0..-2]
221
+ "[:#{namespace.join(', :')}, #{name}]"
222
+ else
223
+ name
224
+ end
225
+ end
226
+ end
227
+
228
+ def item_url
229
+ if action? :show
230
+ item_path(:full_url => true, :instance_variable => true)
231
+ else
232
+ items_url
233
+ end
234
+ end
235
+
236
+ def items_url
237
+ if action? :index
238
+ item_resource.pluralize + '_url'
239
+ else
240
+ "root_url"
241
+ end
242
+ end
243
+
244
+ def item_path_for_spec(suffix = 'path')
245
+ if action? :show
246
+ "#{item_resource}_#{suffix}(assigns[:#{instance_name}])"
247
+ else
248
+ if suffix == 'path'
249
+ items_path
250
+ else
251
+ items_url
252
+ end
253
+ end
254
+ end
255
+
256
+ def item_path_for_test(suffix = 'path')
257
+ if action? :show
258
+ "#{item_resource}_#{suffix}(assigns(:#{instance_name}))"
259
+ else
260
+ if suffix == 'path'
261
+ items_path
262
+ else
263
+ items_url
264
+ end
265
+ end
266
+ end
267
+
268
+ def model_columns_for_attributes
269
+ class_name.constantize.columns.reject do |column|
270
+ column.name.to_s =~ /^(id|created_at|updated_at)$/
271
+ end
272
+ end
273
+
274
+ def view_language
275
+ options.haml? ? 'haml' : 'erb'
276
+ end
277
+
278
+ def test_framework
279
+ return @test_framework if defined?(@test_framework)
280
+ if options.testunit?
281
+ return @test_framework = :testunit
282
+ elsif options.rspec?
283
+ return @test_framework = :rspec
284
+ elsif options.shoulda?
285
+ return @test_framework = :shoulda
286
+ else
287
+ return @test_framework = default_test_framework
288
+ end
289
+ end
290
+
291
+ def default_test_framework
292
+ File.exist?(destination_path("spec")) ? :rspec : :testunit
293
+ end
294
+
295
+ def model_exists?
296
+ File.exist? destination_path("app/models/#{singular_name}.rb")
297
+ end
298
+
299
+ def read_template(relative_path)
300
+ ERB.new(File.read(find_in_source_paths(relative_path)), nil, '-').result(binding)
301
+ end
302
+
303
+ def destination_path(path)
304
+ File.join(destination_root, path)
305
+ end
306
+
307
+ # FIXME: Should be proxied to ActiveRecord::Generators::Base
308
+ # Implement the required interface for Rails::Generators::Migration.
309
+ def self.next_migration_number(dirname) #:nodoc:
310
+ if ActiveRecord::Base.timestamped_migrations
311
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
312
+ else
313
+ "%.3d" % (current_migration_number(dirname) + 1)
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end