zoo-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 (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