zoo-generators 0.1.0

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