dry_crud 1.2.0 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.rdoc +28 -11
  2. data/Rakefile +2 -1
  3. data/VERSION +1 -1
  4. data/lib/generators/dry_crud/templates/INSTALL +0 -1
  5. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +11 -183
  6. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +212 -0
  7. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +10 -20
  8. data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +25 -0
  9. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +5 -4
  10. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +2 -2
  11. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +1 -1
  12. data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +1 -1
  13. data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +1 -1
  14. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +5 -1
  15. data/lib/generators/dry_crud/templates/app/views/list/_actions_index.html.erb +0 -0
  16. data/lib/generators/dry_crud/templates/app/views/list/_list.html.erb +1 -0
  17. data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +7 -0
  18. data/lib/generators/dry_crud/templates/app/views/{crud → list}/index.html.erb +1 -1
  19. data/lib/generators/dry_crud/templates/public/stylesheets/crud.css +13 -10
  20. data/lib/generators/dry_crud/templates/test/crud_test_model.rb +50 -25
  21. data/lib/generators/dry_crud/templates/test/custom_assertions.rb +8 -0
  22. data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +23 -3
  23. data/lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb +18 -0
  24. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +22 -75
  25. data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +139 -0
  26. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +4 -7
  27. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +6 -10
  28. data/test/templates/app/controllers/people_controller.rb +1 -0
  29. data/test/templates/app/controllers/vips_controller.rb +24 -0
  30. data/test/templates/app/views/cities/_list.html.erb +3 -3
  31. data/test/templates/app/views/layouts/application.html.erb +33 -0
  32. data/test/templates/app/views/people/_list.html.erb +1 -0
  33. data/test/templates/config/routes.rb +2 -0
  34. data/test/templates/db/seeds.rb +1 -1
  35. data/test/templates/public/stylesheets/demo.css +113 -0
  36. metadata +15 -7
  37. data/lib/generators/dry_crud/templates/app/views/crud/_search.html.erb +0 -8
  38. data/test/templates/app/views/layouts/crud.html.erb +0 -26
data/README.rdoc CHANGED
@@ -73,18 +73,18 @@ This only displays these three attributes in the table. All other templates, as
73
73
 
74
74
  Next, let's adapt a part of the general behavior used in all CRUD controllers. As an example, we include pagination with will_paginate[http://wiki.github.com/mislav/will_paginate/] in all our overview tables:
75
75
 
76
- In <tt>app/controllers/crud_controller.rb</tt>, change the index action to
76
+ In <tt>app/controllers/list_controller.rb</tt>, change the index action to
77
77
 
78
78
  def index
79
79
  @entries = list_entries.paginate(:page => params[:page])
80
80
  respond_with @entries
81
81
  end
82
82
 
83
- In <tt>app/views/crud/index.html.erb</tt>, add the following line for the pagination links:
83
+ In <tt>app/views/list/index.html.erb</tt>, add the following line for the pagination links:
84
84
  <%= will_paginate @entries %>
85
85
 
86
- And we are done again. All our controllers inheriting from +CrudController+, including above +PeopleController+, now have paginated index views. Because our customization for the people table is in the separate <tt> _list</tt> partial, no further modifications are required.
87
- If the current page should be remembered while viewing or editing an entry, just add :page to the remembered_params in <tt>CrudController::Memory</tt>:
86
+ And we are done again. All our controllers inheriting from +ListController+, including above +PeopleController+, now have paginated index views. Because our customization for the people table is in the separate <tt>_list</tt> partial, no further modifications are required.
87
+ If the current page should be remembered while viewing or editing an entry, just add :page to the remembered_params in <tt>ListController::Memory</tt>:
88
88
 
89
89
  controller.remember_params = [:q, :sort, :sort_dir, :page]
90
90
 
@@ -180,7 +180,9 @@ All generated files are supposed to provide a reasonable foundation for the CRUD
180
180
 
181
181
  === Controller:
182
182
 
183
- {controller/crud_controller.rb}[http://codez.ch/dry_crud/?q=CrudController]:: Abstract controller providing basic CRUD actions. This implementation mainly follows the one of the Rails scaffolding controller and responses to HTML and XML requests. Some enhancements were made to ease extendability. Several protected helper methods are there to be (optionally) overriden by subclasses. There are two modules included that provide search and sort functionality for the table displayed in the index action. With the help of additional callbacks, it is possible to hook into the action procedures without overriding the entire method.
183
+ {controller/crud_controller.rb}[http://codez.ch/dry_crud/?q=CrudController]:: Abstract controller providing basic CRUD actions. This implementation mainly follows the one of the Rails scaffolding controller and responses to HTML and XML requests. Some enhancements were made to ease extendability. Several protected helper methods are there to be (optionally) overriden by subclasses. With the help of additional callbacks, it is possible to hook into the action procedures without overriding the entire method. This class is based on ListController.
184
+
185
+ {controller/list_controller.rb}[http://codez.ch/dry_crud/?q=ListController]:: Abstract controller providing a basic list action. There are two sub-modules that provide search and sort functionality for the table displayed in the list action. A third sub-module remembers the list parameters in order to return to an identical list.
184
186
 
185
187
  {controller/render_inheritable.rb}[http://codez.ch/dry_crud/?q=RenderInheritable]:: A controller enhancement that allows one to render inheritable views and partials. If no view file is found for the current controller, the corresponding file is looked up in its superclass hierarchy. Thus, only views or partials that look differently have to be overwritten.
186
188
 
@@ -191,6 +193,8 @@ All generated files are supposed to provide a reasonable foundation for the CRUD
191
193
 
192
194
  {helpers/crud_helper.rb}[http://codez.ch/dry_crud/?q=CrudHelper]:: A small helper for CrudController to render tables and forms with a default set of attributes.
193
195
 
196
+ {helpers/list_helper.rb}[http://codez.ch/dry_crud/?q=ListHelper]:: A small helper for ListController to render the list table with a default set of attributes.
197
+
194
198
  {helpers/standard_table_builder.rb}[http://codez.ch/dry_crud/?q=StandardTableBuilder]:: A simple helper object to easily define tables listing several rows of the same data type.
195
199
 
196
200
  {helpers/standard_form_builder.rb}[http://codez.ch/dry_crud/?q=StandardFormBuilder]:: A form builder that automatically selects the corresponding input element for ActiveRecord columns. Input elements are rendered with a corresponding label by default.
@@ -198,25 +202,38 @@ All generated files are supposed to provide a reasonable foundation for the CRUD
198
202
 
199
203
  === Views:
200
204
 
201
- views/crud/index.html.erb:: The index view displaying a table with all entries and an action link to add new ones. If you have +search_columns+ defined for your controller, then a search box is rendered as well.
202
-
203
- views/crud/_list.html.erb:: A partial defining the table in the index view. To change the displayed attributes in your CRUD model, just create an own _list.html.erb in your models view directory.
205
+ All templates in the +crud+ folder may be 'overriden' individually in a respective view folder. Define the basic structure of your CRUD views here and adapt it as required for each single model.
204
206
 
205
- views/crud/_search.html.erb:: A partial defining a simple search form that is displayed when +search_columns+ are defined in a subclassing controller.
206
207
 
207
208
  views/crud/show.html.erb:: The show view displaying all the attributes of one entry and the various actions to perform on it.
208
209
 
209
210
  views/crud/_attrs.html.erb:: A partial defining the attributes to be displayed in the show view.
210
211
 
212
+ views/crud/_list.html.erb:: A partial defining the table in the index view. To change the displayed attributes for your list model, just create an own _list.html.erb in your controller's view directory.
213
+
211
214
  views/crud/new.html.erb:: The view to create a new entry.
212
215
 
213
216
  views/crud/edit.html.erb:: The view to edit an existing entry.
214
217
 
215
- views/crud/_form.html.erb:: The form used to create and edit entries. If you would like to customize this form for various models, just create an own _form.html.erb in your models view directory.
218
+ views/crud/_form.html.erb:: The form used to create and edit entries. If you would like to customize this form for various models, just create an own _form.html.erb in your controller's view directory.
219
+
220
+ views/crud/_actions_index.html.erb:: The action links available in the index view.
221
+
222
+ views/crud/_actions_show.html.erb:: The action links available in the show view.
223
+
224
+ views/crud/_actions_edit.html.erb:: The action links available in the edit view.
225
+
226
+ views/list/index.html.erb:: The index view displaying a sortable table with all entries. If you have +search_columns+ defined for your controller, then a search box is rendered as well.
227
+
228
+ views/list/_list.html.erb:: A partial defining the table in the index view. To change the displayed attributes for your list model, just create an own _list.html.erb in your controller's view directory.
229
+
230
+ views/list/_search.html.erb:: A partial defining a simple search form that is displayed when +search_columns+ are defined in a subclassing controller.
231
+
232
+ views/list/_actions_index.html.erb:: The action links available in the index view. None by default.
216
233
 
217
234
  views/shared/_labeled.html.erb:: Partial to define the layout for an arbitrary content with a label.
218
235
 
219
- views/layouts/crud.html.erb:: An example layout showing how to use the @title and +flash+. Most probably you want to include this in your application.html.erb or adapt this main crud templates, so you wont need this file.
236
+ views/layouts/crud.html.erb:: An example layout showing how to use the @title and +flash+. Most probably you want to merge this with your application.html.erb or adapt the main CRUD templates, so you wont need this file.
220
237
 
221
238
  public/stylesheets/crud.css:: A simple CSS with all the classes and ids used in the CRUD code.
222
239
 
data/Rakefile CHANGED
@@ -51,8 +51,9 @@ namespace :test do
51
51
  desc "Initializes the test application with a couple of classes"
52
52
  task :init => :generate_crud do
53
53
  FileUtils.cp_r(File.join(File.dirname(__FILE__), 'test', 'templates', '.'), TEST_APP_ROOT)
54
+ FileUtils.rm_f(File.join(TEST_APP_ROOT, 'app', 'views', 'layouts', 'crud.html.erb'))
54
55
  FileUtils.cd(TEST_APP_ROOT) do
55
- sh "rake db:migrate db:test:prepare"
56
+ sh "rake db:migrate db:seed db:test:prepare"
56
57
  end
57
58
  end
58
59
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.0
1
+ 1.2.5
@@ -11,4 +11,3 @@ required:
11
11
  * Add a :label method to your models for a human-friendly representation.
12
12
 
13
13
  Enjoy dry_crud and stay DRY!
14
-
@@ -4,31 +4,24 @@
4
4
  # Several protected helper methods are there to be (optionally) overriden by subclasses.
5
5
  # With the help of additional callbacks, it is possible to hook into the action procedures without
6
6
  # overriding the entire method.
7
- class CrudController < ApplicationController
8
-
9
- include RenderInheritable
10
-
7
+ class CrudController < ListController
8
+
11
9
  # Set up entry object to use in the various actions.
12
10
  before_filter :build_entry, :only => [:new, :create]
13
11
  before_filter :set_entry, :only => [:show, :edit, :update, :destroy]
14
12
 
15
- helper :standard
16
- helper_method :model_class, :models_label, :full_entry_label
13
+ helper_method :full_entry_label
17
14
 
18
- delegate :model_class, :model_identifier, :models_label, :to => 'self.class'
15
+ delegate :model_identifier, :to => 'self.class'
19
16
 
20
- hide_action :model_class, :models_label, :model_identifier, :run_callbacks, :inheritable_root_controller
21
-
22
-
23
- # Callbacks
24
- extend ActiveModel::Callbacks
17
+ hide_action :model_identifier, :run_callbacks
18
+
25
19
 
26
20
  # Defines before and after callback hooks for create, update, save and destroy.
27
21
  define_model_callbacks :create, :update, :save, :destroy
28
22
 
29
23
  # Defines before callbacks for the render actions.
30
- define_model_callbacks :render_index,
31
- :render_show,
24
+ define_model_callbacks :render_show,
32
25
  :render_new,
33
26
  :render_edit,
34
27
  :only => :before,
@@ -43,14 +36,7 @@ class CrudController < ApplicationController
43
36
 
44
37
 
45
38
  ############## ACTIONS ############################################
46
-
47
- # List all entries of this model.
48
- # GET /entries
49
- # GET /entries.xml
50
- def index
51
- @entries = list_entries
52
- respond_with @entries
53
- end
39
+
54
40
 
55
41
  # Show one entry of this model.
56
42
  # GET /entries/1
@@ -112,14 +98,7 @@ class CrudController < ApplicationController
112
98
  protected
113
99
 
114
100
  ############# CUSTOMIZABLE HELPER METHODS ##############################
115
-
116
- # Convenience method to respond to various formats with the given object.
117
- def respond_with(object)
118
- respond_to do |format|
119
- format.html { render_with_callback action_name }
120
- format.xml { render :xml => object }
121
- end
122
- end
101
+
123
102
 
124
103
  # Convenience method to respond to various formats if the performed
125
104
  # action may succeed or fail. In case of failure, a standard response
@@ -151,12 +130,7 @@ class CrudController < ApplicationController
151
130
  def full_entry_label
152
131
  "#{models_label.singularize} '#{@entry.label}'"
153
132
  end
154
-
155
- # The entries to be displayed in the current index page.
156
- def list_entries
157
- model_class.scoped
158
- end
159
-
133
+
160
134
  # Redirects to the show action of a single entry.
161
135
  def redirect_to_show
162
136
  redirect_to @entry
@@ -166,13 +140,6 @@ class CrudController < ApplicationController
166
140
  def redirect_to_index
167
141
  redirect_to polymorphic_path(model_class, :returning => true)
168
142
  end
169
-
170
- # Helper method to run before_render callbacks and render the action.
171
- # If a callback renders or redirects, the action is not rendered.
172
- def render_with_callback(action)
173
- run_callbacks(:"render_#{action}")
174
- render :action => action unless performed?
175
- end
176
143
 
177
144
  # Saves the current entry with callbacks.
178
145
  def save_entry
@@ -186,151 +153,12 @@ class CrudController < ApplicationController
186
153
  end
187
154
 
188
155
  class << self
189
- # The ActiveRecord class of the model.
190
- def model_class
191
- @model_class ||= controller_name.classify.constantize
192
- end
193
-
194
156
  # The identifier of the model used for form parameters.
195
157
  # I.e., the symbol of the underscored model name.
196
158
  def model_identifier
197
159
  @model_identifier ||= model_class.name.underscore.to_sym
198
160
  end
199
-
200
- # A human readable plural name of the model.
201
- def models_label
202
- @models_label ||= model_class.model_name.human.pluralize
203
- end
204
- end
205
-
206
- # The search functionality for the index table.
207
- # Extracted into an own module for convenience.
208
- module Search
209
- # Adds a :search_columns class attribute.
210
- def self.included(controller)
211
- # Define an array of searchable columns in your subclassing controllers.
212
- controller.class_attribute :search_columns
213
- controller.search_columns = []
214
-
215
- controller.helper_method :search_support?
216
-
217
- controller.alias_method_chain :list_entries, :search
218
- end
219
-
220
- protected
221
-
222
- # Enhance the list entries with an optional search criteria
223
- def list_entries_with_search
224
- list_entries_without_search.where(search_condition)
225
- end
226
-
227
- # Compose the search condition with a basic SQL OR query.
228
- def search_condition
229
- if search_support? && params[:q].present?
230
- clause = search_columns.collect {|f| "#{model_class.table_name}.#{f} LIKE ?" }.
231
- join(" OR ")
232
- param = "%#{params[:q]}%"
233
- ["(#{clause})"] + [param] * search_columns.size
234
- end
235
- end
236
-
237
- # Returns true if this controller has searchable columns.
238
- def search_support?
239
- search_columns.present?
240
- end
241
-
242
- end
243
-
244
- include Search
245
-
246
- # Sort functionality for the index table.
247
- # Extracted into an own module for convenience.
248
- module Sorting
249
- # Adds a :sort_mappings class attribute.
250
- def self.included(controller)
251
- # Define a map of (virtual) attributes to SQL order expressions.
252
- # May be used for sorting table columns that do not appear directly
253
- # in the database table. E.g., map :city_id => 'cities.name' to
254
- # sort the displayed city names.
255
- controller.class_attribute :sort_mappings
256
- controller.sort_mappings = {}
257
-
258
- controller.helper_method :sortable?
259
-
260
- controller.alias_method_chain :list_entries, :sort
261
- end
262
-
263
- protected
264
-
265
- # Enhance the list entries with an optional sort order.
266
- def list_entries_with_sort
267
- if params[:sort].present? && sortable?(params[:sort])
268
- list_entries_without_sort.except(:order).order(sort_expression)
269
- else
270
- list_entries_without_sort
271
- end
272
- end
273
-
274
- # Return the sort expression to be used in the list query.
275
- def sort_expression
276
- col = sort_mappings[params[:sort].to_sym] ||
277
- "#{model_class.table_name}.#{params[:sort]}"
278
- "#{col} #{sort_dir}"
279
- end
280
-
281
- # The sort direction, either 'asc' or 'desc'.
282
- def sort_dir
283
- params[:sort_dir] == 'desc' ? 'desc' : 'asc'
284
- end
285
-
286
- # Returns true if the passed attribute is sortable.
287
- def sortable?(attr)
288
- model_class.column_names.include?(attr.to_s) ||
289
- sort_mappings.include?(attr.to_sym)
290
- end
161
+
291
162
  end
292
163
 
293
- include Sorting
294
-
295
- # Remembers certain params of the index action in order to return
296
- # to the same list after an entry was viewed or edited.
297
- # If the index is called with a param :returning, the remembered params
298
- # will be re-used.
299
- # Extracted into an own module for convenience.
300
- module Memory
301
-
302
- # Adds the :remember_paramas class attribute and a before filter to the index action.
303
- def self.included(controller)
304
- # Define a list of param keys that should be remembered for the list action.
305
- controller.class_attribute :remember_params
306
- controller.remember_params = [:q, :sort, :sort_dir]
307
-
308
- controller.before_filter :handle_remember_params, :only => [:index]
309
- end
310
-
311
- private
312
-
313
- # Store and restore the corresponding params.
314
- def handle_remember_params
315
- remembered = remembered_params
316
- if params[:returning]
317
- # restore params
318
- remember_params.each {|p| params[p] ||= remembered[p] }
319
- end
320
-
321
- # store current params
322
- remember_params.each {|p| remembered[p] = params[p].presence }
323
- end
324
-
325
- # Get the params stored in the session.
326
- # Params are stored by request path to play nice when a controller
327
- # is used in different routes.
328
- def remembered_params
329
- session[:list_params] ||= {}
330
- session[:list_params][request.path] ||= {}
331
- end
332
- end
333
-
334
- include Memory
335
-
336
164
  end
@@ -0,0 +1,212 @@
1
+ # Abstract controller providing a basic list action.
2
+ # This action lists all entries of a certain model and provides functionality to
3
+ # search and sort this list.
4
+ # Furthermore, it remembers the last search and sort parameters. When the action
5
+ # is called with a param returning=true, these parameters are reused to present
6
+ # the user the same list as he left it.
7
+ class ListController < ApplicationController
8
+
9
+ include RenderInheritable
10
+
11
+ # Move this declaration to the application controller.
12
+ helper :standard
13
+
14
+ helper_method :model_class, :models_label
15
+
16
+ delegate :model_class, :models_label, :to => 'self.class'
17
+
18
+ hide_action :model_class, :models_label, :inheritable_root_controller
19
+
20
+
21
+ # Callbacks
22
+ extend ActiveModel::Callbacks
23
+
24
+ # Defines before callbacks for the render actions.
25
+ define_model_callbacks :render_index,
26
+ :only => :before,
27
+ :terminator => "result == false || performed?"
28
+
29
+
30
+ ############## ACTIONS ############################################
31
+
32
+ # List all entries of this model.
33
+ # GET /entries
34
+ # GET /entries.xml
35
+ def index
36
+ @entries = list_entries
37
+ respond_with @entries
38
+ end
39
+
40
+
41
+ protected
42
+
43
+ # The entries to be displayed in the current index page.
44
+ def list_entries
45
+ model_class.scoped
46
+ end
47
+
48
+ # Convenience method to respond to various formats with the given object.
49
+ def respond_with(object)
50
+ respond_to do |format|
51
+ format.html { render_with_callback action_name }
52
+ format.xml { render :xml => object }
53
+ end
54
+ end
55
+
56
+
57
+ # Helper method to run before_render callbacks and render the action.
58
+ # If a callback renders or redirects, the action is not rendered.
59
+ def render_with_callback(action)
60
+ run_callbacks(:"render_#{action}")
61
+ render :action => action unless performed?
62
+ end
63
+
64
+
65
+ class << self
66
+ # The ActiveRecord class of the model.
67
+ def model_class
68
+ @model_class ||= controller_name.classify.constantize
69
+ end
70
+
71
+ # A human readable plural name of the model.
72
+ def models_label
73
+ @models_label ||= model_class.model_name.human.pluralize
74
+ end
75
+ end
76
+
77
+ # The search functionality for the index table.
78
+ # Extracted into an own module for convenience.
79
+ module Search
80
+ def self.included(controller)
81
+ # Define an array of searchable columns in your subclassing controllers.
82
+ controller.class_attribute :search_columns
83
+ controller.search_columns = []
84
+
85
+ controller.helper_method :search_support?
86
+
87
+ controller.alias_method_chain :list_entries, :search
88
+ end
89
+
90
+ protected
91
+
92
+ # Enhance the list entries with an optional search criteria
93
+ def list_entries_with_search
94
+ list_entries_without_search.where(search_condition)
95
+ end
96
+
97
+ # Compose the search condition with a basic SQL OR query.
98
+ def search_condition
99
+ if search_support? && params[:q].present?
100
+ clause = search_columns.collect {|f| "#{model_class.table_name}.#{f} LIKE ?" }.
101
+ join(" OR ")
102
+ param = "%#{params[:q]}%"
103
+ ["(#{clause})"] + [param] * search_columns.size
104
+ end
105
+ end
106
+
107
+ # Returns true if this controller has searchable columns.
108
+ def search_support?
109
+ search_columns.present?
110
+ end
111
+
112
+ end
113
+
114
+ include Search
115
+
116
+ # Sort functionality for the index table.
117
+ # Extracted into an own module for convenience.
118
+ module Sorting
119
+ # Adds a :sort_mappings class attribute.
120
+ def self.included(controller)
121
+ # Define a map of (virtual) attributes to SQL order expressions.
122
+ # May be used for sorting table columns that do not appear directly
123
+ # in the database table. E.g., map :city_id => 'cities.name' to
124
+ # sort the displayed city names.
125
+ controller.class_attribute :sort_mappings
126
+ controller.sort_mappings = {}
127
+
128
+ controller.helper_method :sortable?
129
+
130
+ controller.alias_method_chain :list_entries, :sort
131
+ end
132
+
133
+ protected
134
+
135
+ # Enhance the list entries with an optional sort order.
136
+ def list_entries_with_sort
137
+ if params[:sort].present? && sortable?(params[:sort])
138
+ list_entries_without_sort.except(:order).order(sort_expression)
139
+ else
140
+ list_entries_without_sort
141
+ end
142
+ end
143
+
144
+ # Return the sort expression to be used in the list query.
145
+ def sort_expression
146
+ col = sort_mappings[params[:sort].to_sym] ||
147
+ "#{model_class.table_name}.#{params[:sort]}"
148
+ "#{col} #{sort_dir}"
149
+ end
150
+
151
+ # The sort direction, either 'asc' or 'desc'.
152
+ def sort_dir
153
+ params[:sort_dir] == 'desc' ? 'desc' : 'asc'
154
+ end
155
+
156
+ # Returns true if the passed attribute is sortable.
157
+ def sortable?(attr)
158
+ model_class.column_names.include?(attr.to_s) ||
159
+ sort_mappings.include?(attr.to_sym)
160
+ end
161
+ end
162
+
163
+ include Sorting
164
+
165
+ # Remembers certain params of the index action in order to return
166
+ # to the same list after an entry was viewed or edited.
167
+ # If the index is called with a param :returning, the remembered params
168
+ # will be re-used.
169
+ # Extracted into an own module for convenience.
170
+ module Memory
171
+
172
+ # Adds the :remember_params class attribute and a before filter to the index action.
173
+ def self.included(controller)
174
+ # Define a list of param keys that should be remembered for the list action.
175
+ controller.class_attribute :remember_params
176
+ controller.remember_params = [:q, :sort, :sort_dir]
177
+
178
+ controller.before_filter :handle_remember_params, :only => [:index]
179
+ end
180
+
181
+ private
182
+
183
+ # Store and restore the corresponding params.
184
+ def handle_remember_params
185
+ remembered = remembered_params
186
+ if params[:returning]
187
+ # restore params
188
+ remember_params.each {|p| params[p] ||= remembered[p] }
189
+ end
190
+
191
+ # store current params
192
+ remember_params.each do |p|
193
+ remembered[p] = params[p].presence
194
+ remembered.delete(p) if remembered[p].nil?
195
+ end
196
+
197
+ # clear void params
198
+ session[:list_params].delete(request.path) if remembered.blank?
199
+ end
200
+
201
+ # Get the params stored in the session.
202
+ # Params are stored by request path to play nice when a controller
203
+ # is used in different routes.
204
+ def remembered_params
205
+ session[:list_params] ||= {}
206
+ session[:list_params][request.path] ||= {}
207
+ end
208
+ end
209
+
210
+ include Memory
211
+
212
+ end
@@ -6,23 +6,21 @@ module CrudHelper
6
6
  # Create a table of the @entries variable with the default or
7
7
  # the passed attributes in its columns.
8
8
  def crud_table(*attrs, &block)
9
- # only use default attrs if no attrs and no block are given
10
- attributes = (block_given? || attrs.present?) ? attrs : default_attrs
11
- table(@entries) do |t|
12
- t.sortable_attrs(*attributes)
13
- if block_given?
14
- yield t
15
- else
16
- add_list_actions(t)
17
- end
9
+ if block_given?
10
+ list_table(*attrs, &block)
11
+ else
12
+ attrs = default_attrs if attrs.blank?
13
+ list_table(*attrs) do |t|
14
+ add_list_actions(t)
15
+ end
18
16
  end
19
17
  end
20
18
 
21
19
  # Adds a set of standard action link column (show, edit, destroy) to the given table.
22
20
  def add_list_actions(table)
23
- table.col { |e| link_action_show(e) }
24
- table.col { |e| link_action_edit(e) }
25
- table.col { |e| link_action_destroy(e) }
21
+ table.col('', :class => 'center') { |e| link_action_show(e) }
22
+ table.col('', :class => 'center') { |e| link_action_edit(e) }
23
+ table.col('', :class => 'center') { |e| link_action_destroy(e) }
26
24
  end
27
25
 
28
26
  # Renders a generic form for the current entry with :default_attrs or the
@@ -36,12 +34,4 @@ module CrudHelper
36
34
  standard_form(@entry, attrs, &block)
37
35
  end
38
36
 
39
- # The default attributes to use in attrs, list and form partials.
40
- # These are all defined attributes except certain special ones like 'id' or 'position'.
41
- def default_attrs
42
- attrs = model_class.column_names.collect(&:to_sym)
43
- [:id, :position].each {|a| attrs.delete(a) }
44
- attrs
45
- end
46
-
47
37
  end
@@ -0,0 +1,25 @@
1
+ # Extension of StandardHelper functionality to provide a set of default
2
+ # attributes for the current model to be used in tables and forms. This helper
3
+ # is included in CrudController.
4
+ module ListHelper
5
+
6
+ # Create a table of the @entries variable with the default or
7
+ # the passed attributes in its columns.
8
+ def list_table(*attrs, &block)
9
+ # only use default attrs if no attrs and no block are given
10
+ attributes = (block_given? || attrs.present?) ? attrs : default_attrs
11
+ table(@entries) do |t|
12
+ t.sortable_attrs(*attributes)
13
+ yield t if block_given?
14
+ end
15
+ end
16
+
17
+ # The default attributes to use in attrs, list and form partials.
18
+ # These are all defined attributes except certain special ones like 'id' or 'position'.
19
+ def default_attrs
20
+ attrs = model_class.column_names.collect(&:to_sym)
21
+ [:id, :position].each {|a| attrs.delete(a) }
22
+ attrs
23
+ end
24
+
25
+ end
@@ -178,11 +178,12 @@ module StandardHelper
178
178
  val = obj.send(attr)
179
179
  return EMPTY_STRING if val.nil?
180
180
  case column_type(obj, attr)
181
- when :time then val.strftime(TIME_FORMAT)
182
- when :date then val.to_date.to_s
183
- when :text then simple_format(h(val))
181
+ when :time then f(val.to_time)
182
+ when :date then f(val.to_date)
183
+ when :datetime, :timestamp then "#{f(val.to_date)} #{f(val.to_time)}"
184
+ when :text then val.present? ? simple_format(h(val)) : EMPTY_STRING
184
185
  when :decimal then f(val.to_s.to_f)
185
- else f(val)
186
+ else f(val)
186
187
  end
187
188
  end
188
189
 
@@ -65,9 +65,9 @@ class StandardTableBuilder
65
65
  entry = entries.first
66
66
  case column_type(entry, attr)
67
67
  when :integer, :float, :decimal
68
- 'right_align' unless association(entry, attr, :belongs_to)
68
+ 'right' unless association(entry, attr, :belongs_to)
69
69
  when :boolean
70
- 'center_align'
70
+ 'center'
71
71
  end
72
72
  end
73
73