controller_scaffolding 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/lib/controller_scaffolding.rb +1 -2
- data/lib/controller_scaffolding/add_generator.rb +1 -0
- data/lib/controller_scaffolding/version.rb +1 -1
- data/lib/generators/controller/controller_scaffolding_generator.rb +2 -0
- data/lib/generators/controller_generator_base.rb +213 -0
- data/lib/generators/erb/controller/controller_scaffolding_generator.rb +16 -0
- data/lib/generators/erb/controller/partials/_flash_messages.html.erb +3 -0
- data/lib/generators/erb/controller/partials/_pagination.html.erb +21 -0
- data/lib/generators/erb/controller/partials/_validation_errors.html.erb +11 -0
- data/lib/generators/haml/controller/controller_scaffolding_generator.rb +4 -216
- data/lib/templates/erb/controller/_form.html.erb +27 -0
- data/lib/templates/erb/controller/edit.html.erb +2 -0
- data/lib/templates/erb/controller/index.html.erb +59 -0
- data/lib/templates/erb/controller/new.html.erb +2 -0
- data/lib/templates/erb/controller/view.html.erb +4 -0
- data/test/dummy/config/environments/development.rb +1 -1
- data/test/dummy/config/routes.rb +1 -2
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +1258 -0
- data/test/dummy/log/test.log +13295 -0
- data/test/dummy/spec/requests/fellows_spec.rb +2 -2
- data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- metadata +12 -4
- data/test/dummy/tmp/pids/server.pid +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c184df390b751a9bf077a405d17ff3a1921d5db
|
4
|
+
data.tar.gz: c764161c7286cb1c3273bf804aff1c2bbdfc0046
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01fd17c94b58d927c84b6974d2a104f08b4e88d79fe5261dd23b5ad619ad364b1eb821098491aeb01b77896cabc176747f98e47de5cda81db658bfcab5ed7792
|
7
|
+
data.tar.gz: b53554a2be4b3f47800084ac3f2295632ac8e2504d28fa93dbdfb25708ca236f02f33d639dd3b2421e5f441f6a8c5e115f8609b9b5e1bcf77aa99e1466f6ae9e
|
data/README.md
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/controller_scaffolding.svg)](http://badge.fury.io/rb/controller_scaffolding)
|
4
4
|
|
5
5
|
#### Description ####
|
6
|
-
The generator acts somewhat like scaffolding, but you must specify an *existing* model and pass in any of the RESTful actions you are interested in (or no actions if you want all of them). With no options passed in
|
6
|
+
The generator acts somewhat like scaffolding, but you must specify an *existing* model and pass in any of the RESTful actions you are interested in (or no actions if you want all of them). With no options passed in it generates index pages with search/sort* functionality and basic pagination. On the forms it adds optional date/time pickers** and displays flash messages and validation errors. It also adds some styling for the index page and the new/edit form which makes it a bit easier on the eyes until you have a chance to add your own styling.
|
7
7
|
|
8
8
|
\* https://github.com/jomalley2112/sql_search_n_sort
|
9
|
+
|
9
10
|
\*\* https://github.com/jomalley2112/hot_date_rails
|
10
11
|
|
11
12
|
|
@@ -28,7 +29,7 @@ $ rails g controller_scaffolding users index new create edit update destroy --te
|
|
28
29
|
```
|
29
30
|
All Options:
|
30
31
|
```bash
|
31
|
-
$ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --template-engine=haml
|
32
|
+
$ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --template-engine=erb|haml
|
32
33
|
[--skip-ext-index-nav] [--skip-ext-form-submit] [--skip-datepicker] [--skip-assets] [--skip-test-framework] [--skip-helper] [--quiet] [--force] [--skip-search-sort]
|
33
34
|
```
|
34
35
|
|
@@ -41,7 +42,7 @@ $ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --t
|
|
41
42
|
#### Options ####
|
42
43
|
| Option | Description | Optional?
|
43
44
|
| ---------------------- | ------------------------------------------------------ | ---------- |
|
44
|
-
| --template-engine
|
45
|
+
| --template-engine | Specify template engine...erb or haml (erb is default) | yes |
|
45
46
|
| --skip-ext-index-nav | Do not include extended index navigation functionality | yes |
|
46
47
|
| --skip-ext-form-submit | Do not include extended form submission functionality | yes |
|
47
48
|
| --skip-datepicker | Do not include date/time picker functionality | yes |
|
@@ -84,10 +85,6 @@ $ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --t
|
|
84
85
|
* Adds functionality to display flash messages and validation errors.
|
85
86
|
* Adds some styling to the form
|
86
87
|
|
87
|
-
#### Datepicker ####
|
88
|
-
* Uses [hot_date_rails](https://github.com/jomalley2112/hot_date_rails) to attach date, time and datetime pickers to appropriate form input fields.
|
89
|
-
|
90
|
-
|
91
88
|
#### Assets ####
|
92
89
|
* Javascript
|
93
90
|
* Installs ext_index_nav.js if extended index navigation is selected.
|
@@ -98,6 +95,9 @@ $ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --t
|
|
98
95
|
#### Search and Sort ####
|
99
96
|
* see README.md at https://github.com/jomalley2112/sql_search_n_sort
|
100
97
|
|
98
|
+
#### Datepicker ####
|
99
|
+
* Uses [hot_date_rails](https://github.com/jomalley2112/hot_date_rails) to attach date, time and datetime pickers to appropriate form input fields.
|
100
|
+
|
101
101
|
### Testing ###
|
102
102
|
* Generator tests: run `rake test` from the root directory.
|
103
103
|
* Integration test specs: run `rspec spec` from 'test/dummy'
|
@@ -121,7 +121,7 @@ $ rails g|d controller_scaffolding plural_model_name action1 action2 action3 --t
|
|
121
121
|
- "database_cleaner"
|
122
122
|
|
123
123
|
#### TODO ####
|
124
|
-
- Add
|
124
|
+
- Add non-RESTful routes (see issue #3)
|
125
125
|
- See if we can support case where existing model has been removed after generator has been run and then the user decides to uninstall (revoke) controller_scaffolding.
|
126
126
|
- Add search results message like "9 Results match 'you search string'"
|
127
127
|
- Nail down versions for dependencies
|
@@ -2,9 +2,8 @@ module ControllerScaffolding
|
|
2
2
|
require "haml-rails"
|
3
3
|
require "will_paginate"
|
4
4
|
require 'jquery-rails'
|
5
|
-
#require "factory_girl_rails" if Rails.env == 'test'
|
6
5
|
require 'controller_scaffolding/add_generator' if defined?(Rails)
|
7
6
|
require 'controller_scaffolding/railtie' if defined?(Rails)
|
8
|
-
require 'sql_search_n_sort'
|
7
|
+
require 'sql_search_n_sort'
|
9
8
|
require 'hot_date_rails'
|
10
9
|
end
|
@@ -3,6 +3,7 @@ module ControllerScaffolding
|
|
3
3
|
generators do
|
4
4
|
require "generators/controller/controller_scaffolding_generator"
|
5
5
|
require "generators/haml/controller/controller_scaffolding_generator"
|
6
|
+
require "generators/erb/controller/controller_scaffolding_generator"
|
6
7
|
end
|
7
8
|
end
|
8
9
|
end
|
@@ -66,6 +66,8 @@ module Rails
|
|
66
66
|
|
67
67
|
def add_routes
|
68
68
|
#TODO Handle nested resources here (look at namespace_ladder in scaffold generators)
|
69
|
+
#TODO: make this a little more intelligent so if an action specified to the
|
70
|
+
# generator is Non-RESTful just add a simple "get" route for it
|
69
71
|
route "resources :#{plural_table_name.to_sym}"
|
70
72
|
end
|
71
73
|
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module Generators
|
2
|
+
require 'rails/generators/erb/controller/controller_generator'
|
3
|
+
require 'rails/generators/erb/scaffold/scaffold_generator'
|
4
|
+
class ControllerGeneratorBase < Erb::Generators::ControllerGenerator
|
5
|
+
|
6
|
+
argument :actions, type: :array, default: [], banner: "action action"
|
7
|
+
class_option :ext_index_nav, :type => :boolean, :default => true, :desc => "Include extended index page features."
|
8
|
+
class_option :ext_form_submit, :type => :boolean, :default => true, :desc => "Include extended form submission features."
|
9
|
+
class_option :search_sort, :type => :boolean, :default => true, :desc => "Add search and sort functionality to index page."
|
10
|
+
class_option :datepicker, :type => :boolean, :default => true, :desc => "Use datepicker for date/time fields."
|
11
|
+
|
12
|
+
|
13
|
+
#This method seems to always get run first
|
14
|
+
def copy_view_files #do NOT change the name of this method
|
15
|
+
# it must be overriding an existing one in a parent class
|
16
|
+
base_path = File.join("app/views", class_path, file_name)
|
17
|
+
empty_directory base_path
|
18
|
+
@actions = actions.nil? || actions.empty? ? %w(index new create edit update destroy) : actions
|
19
|
+
@attr_cols = ::Rails::Generators::attr_cols(table_name)
|
20
|
+
@col_count = @attr_cols.count
|
21
|
+
@col_count += 1 if @actions.include?("edit")
|
22
|
+
@col_count += 1 if @actions.include?("destroy")
|
23
|
+
@search_sort = options.search_sort?
|
24
|
+
(@actions - %w(create update destroy)).each do |action|
|
25
|
+
@action = action
|
26
|
+
formats.each do |format|
|
27
|
+
@path = File.join(base_path, filename_with_extensions(action, format))
|
28
|
+
set_template(@action, @path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def gen_form_partial
|
34
|
+
base_path = File.join("app/views", class_path, file_name)
|
35
|
+
unless (@actions & %w(edit new)).empty? #Remember that "&" is Array#intersect
|
36
|
+
@path = File.join(base_path, filename_with_extensions("_form", format))
|
37
|
+
set_template("_form", @path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def handle_ext_index
|
42
|
+
if options.ext_index_nav?
|
43
|
+
copy_controller_concern("ext_index_nav.rb")
|
44
|
+
inject_into_file "app/controllers/application_controller.rb",
|
45
|
+
after: "class ApplicationController < ActionController::Base\n" do
|
46
|
+
"\n\tinclude ExtIndexNav\n"
|
47
|
+
end
|
48
|
+
copy_partial("_pagination")
|
49
|
+
add_pagination_to_locale_file
|
50
|
+
copy_ext_index_js
|
51
|
+
inc_jquery_scripts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def handle_ext_form
|
56
|
+
if options.ext_form_submit?
|
57
|
+
copy_controller_concern("ext_form_submit.rb")
|
58
|
+
|
59
|
+
inject_into_file "app/controllers/application_controller.rb",
|
60
|
+
after: "class ApplicationController < ActionController::Base\n" do
|
61
|
+
"\n\tinclude ExtFormSubmit\n"
|
62
|
+
end
|
63
|
+
copy_partial("_flash_messages")
|
64
|
+
inject_into_file "app/views/layouts/application.html.erb",
|
65
|
+
before: "<%= yield %>\n" do
|
66
|
+
"\n<%= render 'flash_messages' %>\n"
|
67
|
+
end
|
68
|
+
copy_partial("_validation_errors")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def handle_datepicker
|
73
|
+
if options.datepicker?
|
74
|
+
inc_jquery_scripts
|
75
|
+
inject_into_file "app/assets/javascripts/application.js",
|
76
|
+
after: "\n//= require_tree ." do
|
77
|
+
"\n//= require hot_date_rails"
|
78
|
+
end
|
79
|
+
inject_into_file "app/assets/stylesheets/application.css",
|
80
|
+
before: "\n *= require_tree ." do
|
81
|
+
"\n *= require hot_date_rails"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def copy_stylesheet
|
87
|
+
if options.ext_form_submit? || options.ext_index_nav?
|
88
|
+
source_paths << File.expand_path('../../../lib/generators/assets/stylesheets', __FILE__)
|
89
|
+
base_path = "app/assets/stylesheets"
|
90
|
+
path = File.join(base_path, 'controller_scaffolding.css.scss')
|
91
|
+
copy_file('controller_scaffolding.css.scss', path) if file_action(path)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
#This is the code that add SnS functionality to the model specified in the controller generator
|
96
|
+
def handle_search_n_sort
|
97
|
+
if @search_sort
|
98
|
+
inject_into_file "app/models/#{table_name.singularize}.rb",
|
99
|
+
before: /^end/ do
|
100
|
+
"\n\textend SqlSearchableSortable\n"
|
101
|
+
end
|
102
|
+
inject_into_file "app/models/#{table_name.singularize}.rb",
|
103
|
+
before: /^end/ do
|
104
|
+
"\n\tsql_searchable #{searchable_cols_as_symbols}\n"
|
105
|
+
end
|
106
|
+
inject_into_file "app/models/#{table_name.singularize}.rb",
|
107
|
+
before: /^end/ do
|
108
|
+
"\n\tsql_sortable #{cols_to_symbols}\n"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
def print_warnings
|
115
|
+
if @unsearchable_model && behavior == :invoke && !options.quiet?
|
116
|
+
warn("WARNING: Model #{table_name.classify} is extending SqlSearchableSortable," \
|
117
|
+
" but doesn't have any searchable attributes at this point.")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
#================================= P R I V A T E =====================================
|
121
|
+
private
|
122
|
+
|
123
|
+
def inc_jquery_scripts
|
124
|
+
inject_into_file "app/assets/javascripts/application.js",
|
125
|
+
before: "\n//= require_tree ." do
|
126
|
+
"\n//= require jquery\n//= require jquery_ujs"
|
127
|
+
end unless @injected_jquery_ujs #shouldn't allow duplicate text, but just to be safe
|
128
|
+
@injected_jquery_ujs = true
|
129
|
+
end
|
130
|
+
|
131
|
+
def searchable_cols_as_symbols
|
132
|
+
retval = @attr_cols.select{ |col| [:string, :text].include? col.type}
|
133
|
+
.map { |col| col.name.to_sym }.to_s.gsub(/\[(.*)\]/, '\1')
|
134
|
+
@unsearchable_model = true if retval.empty?
|
135
|
+
return retval
|
136
|
+
end
|
137
|
+
|
138
|
+
def cols_to_symbols
|
139
|
+
# going from [:col1, :col2, :col3] to ":col1, :col2, :col3"
|
140
|
+
#ugly, but I can't find another way to keep the symbols and lose the brackets
|
141
|
+
@attr_cols.map { |col| col.name.to_sym }.to_s.gsub(/\[(.*)\]/, '\1')
|
142
|
+
end
|
143
|
+
|
144
|
+
def set_template(action, path)
|
145
|
+
template filename_with_extensions(action.to_sym, format), path
|
146
|
+
rescue Thor::Error => e
|
147
|
+
say("Falling back to the 'view.html.#{handler}' template because #{action}.html.#{handler} doesn't exist",
|
148
|
+
:magenta) unless options.quiet? || behavior == :revoke
|
149
|
+
template filename_with_extensions(:view, format), @path
|
150
|
+
end
|
151
|
+
|
152
|
+
def copy_partial(file)
|
153
|
+
source_paths << File.expand_path("../../../lib/generators/#{handler}/controller/partials", __FILE__)
|
154
|
+
base_path = "app/views/application"
|
155
|
+
path = File.join(base_path, filename_with_extensions( file, format))
|
156
|
+
copy_file(filename_with_extensions(file, format), path) if file_action(path)
|
157
|
+
end
|
158
|
+
|
159
|
+
def copy_controller_concern(file_w_ext)
|
160
|
+
source_paths << File.expand_path('../../../lib/generators/controller/concerns', __FILE__)
|
161
|
+
base_path = "app/controllers/concerns"
|
162
|
+
path = File.join(base_path, file_w_ext)
|
163
|
+
copy_file(file_w_ext, path) if file_action(path)
|
164
|
+
end
|
165
|
+
|
166
|
+
def copy_ext_index_js
|
167
|
+
source_paths << File.expand_path('../../../lib/generators/assets/javascripts', __FILE__)
|
168
|
+
base_path = "app/assets/javascripts"
|
169
|
+
path = File.join(base_path, 'ext_index_nav.js')
|
170
|
+
copy_file('ext_index_nav.js', path) if file_action(path)
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_pagination_to_locale_file
|
174
|
+
#TODO: Could put some kind of logic in here when revoking that removes some lines
|
175
|
+
# from the locale file, but it shouldn't hurt anything if we don't
|
176
|
+
lang = I18n.locale.to_s
|
177
|
+
locale_config = YAML.load_file("#{destination_root}/config/locales/#{lang}.yml")
|
178
|
+
locale_config[I18n.locale.to_s] = {} unless locale_config[lang]
|
179
|
+
lc_wp = locale_config[I18n.locale.to_s]['will_paginate'] ||=
|
180
|
+
locale_config[I18n.locale.to_s]['will_paginate'] = {}
|
181
|
+
wp_models = lc_wp['models'] || lc_wp['models'] = {}
|
182
|
+
curr_model = wp_models[table_name] ||
|
183
|
+
wp_models[table_name] = { "zero"=>table_name.humanize,
|
184
|
+
"one"=>file_name.singularize.humanize,
|
185
|
+
"other"=>table_name.humanize }
|
186
|
+
wp_pei = lc_wp['page_entries_info'] || lc_wp['page_entries_info'] = {}
|
187
|
+
pei_mph = wp_pei['multi_page_html'] || wp_pei['multi_page_html'] =
|
188
|
+
"Displaying <b>%{from} - %{to}</b> of <b>%{count}</b> %{model}"
|
189
|
+
|
190
|
+
pei_sph = wp_pei['single_page_html'] || wp_pei['single_page_html'] = {}
|
191
|
+
pei_sph['zero'] || pei_sph['zero'] = "No %{model} found"
|
192
|
+
pei_sph['one'] || pei_sph['one'] = "Displaying <b>1</b> %{model}"
|
193
|
+
pei_sph['other'] || pei_sph['other'] = "Displaying <b>all %{count}</b> %{model}"
|
194
|
+
File.open("#{destination_root}/config/locales/#{lang}.yml", "w") { |f| YAML.dump(locale_config, f) }
|
195
|
+
end
|
196
|
+
|
197
|
+
def file_action(path)
|
198
|
+
return true if options.force?
|
199
|
+
if behavior == :revoke
|
200
|
+
verb = "Remove"
|
201
|
+
elsif File.exists?(path)
|
202
|
+
verb = "Overwrite existing"
|
203
|
+
else
|
204
|
+
return true
|
205
|
+
end
|
206
|
+
return yes?("#{verb} shared file #{path}? (y or n)", :yellow)
|
207
|
+
end
|
208
|
+
|
209
|
+
def inc_link?(name)
|
210
|
+
@actions.include?(name)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'generators/controller_generator_base'
|
2
|
+
|
3
|
+
module Erb
|
4
|
+
module Generators
|
5
|
+
class ControllerScaffoldingGenerator < ::Generators::ControllerGeneratorBase
|
6
|
+
|
7
|
+
source_paths << File.expand_path('../../../../templates/erb/controller', __FILE__)
|
8
|
+
|
9
|
+
protected
|
10
|
+
def handler
|
11
|
+
:erb
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% item_type = coll.length > 0 ? coll.first.class.table_name.humanize.pluralize : "Entries" %>
|
2
|
+
<% opts_arr = %w(10 15 20 25 30 40 50 75 100 All).map { |n| [n, n] } %>
|
3
|
+
<div class="outer-pagination">
|
4
|
+
<div class="c_scaff_pagination">
|
5
|
+
<%= will_paginate coll %>
|
6
|
+
</div>
|
7
|
+
<table style="width: 100%">
|
8
|
+
<tr>
|
9
|
+
<td class="page-info left-page-info">
|
10
|
+
<%= page_entries_info coll, model: item_type %>
|
11
|
+
</td>
|
12
|
+
<td class="page-info right-page-info">
|
13
|
+
<%= label_tag :per_page, "#{item_type} per page:" %>
|
14
|
+
|
15
|
+
<%= select_tag(:per_page, options_for_select(opts_arr, (@selected_val || @per_page || 25)), :style => "width: 65px", :onchange => "set_per_page(this);") %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
</table>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
|
@@ -1,228 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#To Teardown manually:
|
4
|
-
# rails d controller_scaffolding people index new create edit update destroy custom_action --template-engine=haml
|
5
|
-
|
6
|
-
require 'rails/generators/erb/controller/controller_generator'
|
7
|
-
require 'rails/generators/erb/scaffold/scaffold_generator'
|
1
|
+
require 'generators/controller_generator_base'
|
8
2
|
|
9
3
|
module Haml
|
10
4
|
module Generators
|
11
|
-
class ControllerScaffoldingGenerator <
|
12
|
-
argument :actions, type: :array, default: [], banner: "action action"
|
13
|
-
class_option :ext_index_nav, :type => :boolean, :default => true, :desc => "Include extended index page features."
|
14
|
-
class_option :ext_form_submit, :type => :boolean, :default => true, :desc => "Include extended form submission features."
|
15
|
-
class_option :search_sort, :type => :boolean, :default => true, :desc => "Add search and sort functionality to index page."
|
16
|
-
class_option :datepicker, :type => :boolean, :default => true, :desc => "Use datepicker for date/time fields."
|
5
|
+
class ControllerScaffoldingGenerator < ::Generators::ControllerGeneratorBase
|
17
6
|
|
18
|
-
|
19
7
|
source_paths << File.expand_path('../../../../templates/haml/controller', __FILE__)
|
20
8
|
|
21
|
-
|
22
|
-
#This method seems to always get run first
|
23
|
-
def copy_view_files #do NOT change the name of this method
|
24
|
-
# it must be overriding an existing one in a parent class
|
25
|
-
base_path = File.join("app/views", class_path, file_name)
|
26
|
-
empty_directory base_path
|
27
|
-
@actions = actions.nil? || actions.empty? ? %w(index new create edit update destroy) : actions
|
28
|
-
@attr_cols = ::Rails::Generators::attr_cols(table_name)
|
29
|
-
@col_count = @attr_cols.count
|
30
|
-
@col_count += 1 if @actions.include?("edit")
|
31
|
-
@col_count += 1 if @actions.include?("destroy")
|
32
|
-
@search_sort = options.search_sort?
|
33
|
-
(@actions - %w(create update destroy)).each do |action|
|
34
|
-
@action = action
|
35
|
-
formats.each do |format|
|
36
|
-
@path = File.join(base_path, filename_with_extensions(action, format))
|
37
|
-
set_template(@action, @path)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def gen_form_partial
|
43
|
-
base_path = File.join("app/views", class_path, file_name)
|
44
|
-
unless (@actions & %w(edit new)).empty? #Remember that "&" is Array#intersect
|
45
|
-
@path = File.join(base_path, filename_with_extensions("_form", format))
|
46
|
-
set_template("_form", @path)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def handle_ext_index
|
51
|
-
if options.ext_index_nav?
|
52
|
-
copy_controller_concern("ext_index_nav.rb")
|
53
|
-
inject_into_file "app/controllers/application_controller.rb",
|
54
|
-
after: "class ApplicationController < ActionController::Base\n" do
|
55
|
-
"\n\tinclude ExtIndexNav\n"
|
56
|
-
end
|
57
|
-
copy_partial("_pagination")
|
58
|
-
add_pagination_to_locale_file
|
59
|
-
copy_ext_index_js
|
60
|
-
inc_jquery_scripts
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def handle_ext_form
|
65
|
-
if options.ext_form_submit?
|
66
|
-
copy_controller_concern("ext_form_submit.rb")
|
67
|
-
|
68
|
-
inject_into_file "app/controllers/application_controller.rb",
|
69
|
-
after: "class ApplicationController < ActionController::Base\n" do
|
70
|
-
"\n\tinclude ExtFormSubmit\n"
|
71
|
-
end
|
72
|
-
copy_partial("_flash_messages")
|
73
|
-
inject_into_file "app/views/layouts/application.html.erb",
|
74
|
-
before: "<%= yield %>\n" do
|
75
|
-
"\n<%= render 'flash_messages' %>\n"
|
76
|
-
end
|
77
|
-
copy_partial("_validation_errors")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def handle_datepicker
|
82
|
-
if options.datepicker?
|
83
|
-
inc_jquery_scripts
|
84
|
-
inject_into_file "app/assets/javascripts/application.js",
|
85
|
-
before: "\n//= require_tree ." do
|
86
|
-
"\n//= require hot_date_rails"
|
87
|
-
end
|
88
|
-
inject_into_file "app/assets/stylesheets/application.css",
|
89
|
-
before: "\n *= require_tree ." do
|
90
|
-
"\n *= require hot_date_rails"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def copy_stylesheet
|
96
|
-
if options.ext_form_submit? || options.ext_index_nav?
|
97
|
-
source_paths << File.expand_path('../../../../generators/assets/stylesheets', __FILE__)
|
98
|
-
base_path = "app/assets/stylesheets"
|
99
|
-
path = File.join(base_path, 'controller_scaffolding.css.scss')
|
100
|
-
copy_file('controller_scaffolding.css.scss', path) if file_action(path)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
#This is the code that add SnS functionality to the model specified in the controller generator
|
105
|
-
def handle_search_n_sort
|
106
|
-
if @search_sort
|
107
|
-
inject_into_file "app/models/#{table_name.singularize}.rb",
|
108
|
-
before: /^end/ do
|
109
|
-
"\n\textend SqlSearchableSortable\n"
|
110
|
-
end
|
111
|
-
inject_into_file "app/models/#{table_name.singularize}.rb",
|
112
|
-
before: /^end/ do
|
113
|
-
"\n\tsql_searchable #{searchable_cols_as_symbols}\n"
|
114
|
-
end
|
115
|
-
inject_into_file "app/models/#{table_name.singularize}.rb",
|
116
|
-
before: /^end/ do
|
117
|
-
"\n\tsql_sortable #{cols_to_symbols}\n"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
def print_warnings
|
124
|
-
if @unsearchable_model && behavior == :invoke && !options.quiet?
|
125
|
-
warn("WARNING: Model #{table_name.classify} is extending SqlSearchableSortable," \
|
126
|
-
" but doesn't have any searchable attributes at this point.")
|
127
|
-
end
|
128
|
-
end
|
129
|
-
#================================= P R O T E C T E D =================================
|
130
9
|
protected
|
131
|
-
|
10
|
+
def handler
|
132
11
|
:haml
|
133
12
|
end
|
134
|
-
|
135
|
-
private
|
136
|
-
|
137
|
-
def inc_jquery_scripts
|
138
|
-
inject_into_file "app/assets/javascripts/application.js",
|
139
|
-
before: "\n//= require_tree ." do
|
140
|
-
"\n//= require jquery\n//= require jquery_ujs"
|
141
|
-
end unless @injected_jquery_ujs #shouldn't allow duplicate text, but just to be safe
|
142
|
-
@injected_jquery_ujs = true
|
143
|
-
end
|
144
|
-
|
145
|
-
def searchable_cols_as_symbols
|
146
|
-
retval = @attr_cols.select{ |col| [:string, :text].include? col.type}
|
147
|
-
.map { |col| col.name.to_sym }.to_s.gsub(/\[(.*)\]/, '\1')
|
148
|
-
@unsearchable_model = true if retval.empty?
|
149
|
-
return retval
|
150
|
-
end
|
151
|
-
|
152
|
-
def cols_to_symbols
|
153
|
-
# going from [:col1, :col2, :col3] to ":col1, :col2, :col3"
|
154
|
-
#ugly, but I can't find another way to keep the symbols and lose the brackets
|
155
|
-
@attr_cols.map { |col| col.name.to_sym }.to_s.gsub(/\[(.*)\]/, '\1')
|
156
|
-
end
|
157
|
-
|
158
|
-
def set_template(action, path)
|
159
|
-
template filename_with_extensions(action.to_sym, format), path
|
160
|
-
rescue Thor::Error => e
|
161
|
-
say("Falling back to the 'view.html.haml' template because #{action}.html.haml doesn't exist",
|
162
|
-
:magenta) unless options.quiet?
|
163
|
-
template filename_with_extensions(:view, format), @path
|
164
|
-
end
|
165
|
-
|
166
|
-
def copy_partial(file)
|
167
|
-
source_paths << File.expand_path('../partials', __FILE__)
|
168
|
-
base_path = "app/views/application"
|
169
|
-
path = File.join(base_path, filename_with_extensions( file, format))
|
170
|
-
copy_file(filename_with_extensions(file, format), path) if file_action(path)
|
171
|
-
end
|
172
|
-
|
173
|
-
def copy_controller_concern(file_w_ext)
|
174
|
-
source_paths << File.expand_path('../../../../generators/controller/concerns', __FILE__)
|
175
|
-
base_path = "app/controllers/concerns"
|
176
|
-
path = File.join(base_path, file_w_ext)
|
177
|
-
copy_file(file_w_ext, path) if file_action(path)
|
178
|
-
end
|
179
|
-
|
180
|
-
def copy_ext_index_js
|
181
|
-
source_paths << File.expand_path('../../../../generators/assets/javascripts', __FILE__)
|
182
|
-
base_path = "app/assets/javascripts"
|
183
|
-
path = File.join(base_path, 'ext_index_nav.js')
|
184
|
-
copy_file('ext_index_nav.js', path) if file_action(path)
|
185
|
-
end
|
186
|
-
|
187
|
-
def add_pagination_to_locale_file
|
188
|
-
#TODO: Could put some kind of logic in here when revoking that removes some lines
|
189
|
-
# from the locale file, but it shouldn't hurt anything if we don't
|
190
|
-
lang = I18n.locale.to_s
|
191
|
-
locale_config = YAML.load_file("#{destination_root}/config/locales/#{lang}.yml")
|
192
|
-
locale_config[I18n.locale.to_s] = {} unless locale_config[lang]
|
193
|
-
lc_wp = locale_config[I18n.locale.to_s]['will_paginate'] ||=
|
194
|
-
locale_config[I18n.locale.to_s]['will_paginate'] = {}
|
195
|
-
wp_models = lc_wp['models'] || lc_wp['models'] = {}
|
196
|
-
curr_model = wp_models[table_name] ||
|
197
|
-
wp_models[table_name] = { "zero"=>table_name.humanize,
|
198
|
-
"one"=>file_name.singularize.humanize,
|
199
|
-
"other"=>table_name.humanize }
|
200
|
-
wp_pei = lc_wp['page_entries_info'] || lc_wp['page_entries_info'] = {}
|
201
|
-
pei_mph = wp_pei['multi_page_html'] || wp_pei['multi_page_html'] =
|
202
|
-
"Displaying <b>%{from} - %{to}</b> of <b>%{count}</b> %{model}"
|
203
|
-
|
204
|
-
pei_sph = wp_pei['single_page_html'] || wp_pei['single_page_html'] = {}
|
205
|
-
pei_sph['zero'] || pei_sph['zero'] = "No %{model} found"
|
206
|
-
pei_sph['one'] || pei_sph['one'] = "Displaying <b>1</b> %{model}"
|
207
|
-
pei_sph['other'] || pei_sph['other'] = "Displaying <b>all %{count}</b> %{model}"
|
208
|
-
File.open("#{destination_root}/config/locales/#{lang}.yml", "w") { |f| YAML.dump(locale_config, f) }
|
209
|
-
end
|
210
|
-
|
211
|
-
def file_action(path)
|
212
|
-
return true if options.force?
|
213
|
-
if behavior == :revoke
|
214
|
-
verb = "Remove"
|
215
|
-
elsif File.exists?(path)
|
216
|
-
verb = "Overwrite existing"
|
217
|
-
else
|
218
|
-
return true
|
219
|
-
end
|
220
|
-
return yes?("#{verb} shared file #{path}? (y or n)", :yellow)
|
221
|
-
end
|
222
|
-
|
223
|
-
def inc_link?(name)
|
224
|
-
@actions.include?(name)
|
225
|
-
end
|
13
|
+
|
226
14
|
end
|
227
15
|
end
|
228
16
|
end
|