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