dry_crud 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/README.rdoc +32 -24
  2. data/Rakefile +73 -19
  3. data/VERSION +1 -1
  4. data/lib/generators/dry_crud/dry_crud_generator.rb +11 -2
  5. data/lib/generators/dry_crud/templates/app/assets/images/actions/delete.png +0 -0
  6. data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.scss +64 -0
  7. data/lib/generators/dry_crud/templates/app/assets/stylesheets/sample.scss +258 -0
  8. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +30 -24
  9. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +93 -7
  10. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +70 -16
  11. data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +1 -0
  12. data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +11 -3
  13. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +36 -45
  14. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +4 -3
  15. data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.erb +2 -2
  16. data/lib/generators/dry_crud/templates/app/views/crud/_actions_edit.html.haml +3 -0
  17. data/lib/generators/dry_crud/templates/app/views/crud/_actions_index.html.haml +1 -0
  18. data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.erb +2 -2
  19. data/lib/generators/dry_crud/templates/app/views/crud/_actions_show.html.haml +3 -0
  20. data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.erb +1 -1
  21. data/lib/generators/dry_crud/templates/app/views/crud/_attrs.html.haml +1 -0
  22. data/lib/generators/dry_crud/templates/app/views/crud/_form.html.haml +1 -0
  23. data/lib/generators/dry_crud/templates/app/views/crud/_list.html.haml +1 -0
  24. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.erb +0 -2
  25. data/lib/generators/dry_crud/templates/app/views/crud/edit.html.haml +5 -0
  26. data/lib/generators/dry_crud/templates/app/views/crud/new.html.erb +0 -2
  27. data/lib/generators/dry_crud/templates/app/views/crud/new.html.haml +5 -0
  28. data/lib/generators/dry_crud/templates/app/views/crud/show.html.erb +0 -2
  29. data/lib/generators/dry_crud/templates/app/views/crud/show.html.haml +7 -0
  30. data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.erb +8 -0
  31. data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.haml +4 -0
  32. data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.erb +3 -0
  33. data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.haml +3 -0
  34. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.erb +6 -0
  35. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.haml +3 -0
  36. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +40 -21
  37. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +42 -0
  38. data/lib/generators/dry_crud/templates/app/views/list/_actions_index.html.haml +0 -0
  39. data/lib/generators/dry_crud/templates/app/views/list/_list.html.haml +1 -0
  40. data/lib/generators/dry_crud/templates/app/views/list/_search.html.erb +4 -3
  41. data/lib/generators/dry_crud/templates/app/views/list/_search.html.haml +5 -0
  42. data/lib/generators/dry_crud/templates/app/views/list/index.html.erb +2 -4
  43. data/lib/generators/dry_crud/templates/app/views/list/index.html.haml +7 -0
  44. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +1 -1
  45. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.haml +6 -0
  46. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.erb +1 -1
  47. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.haml +3 -0
  48. data/lib/generators/dry_crud/templates/config/locales/en_crud.yml +6 -6
  49. data/lib/generators/dry_crud/templates/test/crud_test_model.rb +5 -1
  50. data/lib/generators/dry_crud/templates/test/custom_assertions.rb +4 -4
  51. data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +40 -32
  52. data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +3 -5
  53. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +5 -3
  54. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +4 -4
  55. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +11 -25
  56. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +9 -9
  57. data/test/templates/Gemfile +13 -6
  58. data/test/templates/app/controllers/admin/cities_controller.rb +14 -0
  59. data/test/templates/app/controllers/admin/countries_controller.rb +14 -0
  60. data/test/templates/app/controllers/people_controller.rb +1 -1
  61. data/test/templates/app/controllers/vips_controller.rb +2 -2
  62. data/test/templates/app/helpers/cities_helper.rb +9 -0
  63. data/test/templates/app/models/city.rb +4 -3
  64. data/test/templates/app/models/country.rb +14 -0
  65. data/test/templates/app/views/admin/cities/_actions_index.html.erb +2 -0
  66. data/test/templates/app/views/admin/cities/_actions_index.html.haml +2 -0
  67. data/test/templates/app/views/admin/cities/_form.html.erb +1 -0
  68. data/test/templates/app/views/admin/cities/_form.html.haml +1 -0
  69. data/test/templates/app/views/{cities → admin/cities}/_hello.html.erb +0 -0
  70. data/test/templates/app/views/admin/cities/_hello.html.haml +1 -0
  71. data/test/templates/app/views/admin/cities/_list.html.erb +6 -0
  72. data/test/templates/app/views/admin/cities/_list.html.haml +5 -0
  73. data/test/templates/app/views/admin/countries/_list.html.erb +5 -0
  74. data/test/templates/app/views/admin/countries/_list.html.haml +4 -0
  75. data/test/templates/app/views/ajax/_actions_index.html.haml +8 -0
  76. data/test/templates/app/views/ajax/_hello.html.haml +1 -0
  77. data/test/templates/app/views/ajax/ajax.js.haml +1 -0
  78. data/test/templates/app/views/layouts/_menu.html.erb +1 -1
  79. data/test/templates/app/views/layouts/_menu.html.haml +3 -0
  80. data/test/templates/app/views/people/_attrs.html.haml +4 -0
  81. data/test/templates/app/views/people/_list.html.haml +1 -0
  82. data/test/templates/config/database.yml +8 -9
  83. data/test/templates/config/locales/en_cities.yml +3 -3
  84. data/test/templates/config/routes.rb +16 -8
  85. data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +7 -7
  86. data/test/templates/db/seeds.rb +11 -5
  87. data/test/templates/test/fixtures/cities.yml +3 -3
  88. data/test/templates/test/fixtures/countries.yml +11 -0
  89. data/test/templates/test/functional/admin/cities_controller_test.rb +59 -0
  90. data/test/templates/test/functional/admin/countries_controller_test.rb +43 -0
  91. data/test/templates/test/functional/people_controller_test.rb +6 -1
  92. metadata +54 -15
  93. data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.css +0 -239
  94. data/test/templates/app/controllers/cities_controller.rb +0 -10
  95. data/test/templates/app/views/cities/_form.html.erb +0 -8
  96. data/test/templates/app/views/cities/_list.html.erb +0 -4
  97. data/test/templates/test/functional/cities_controller_test.rb +0 -45
@@ -7,12 +7,8 @@
7
7
  class CrudController < ListController
8
8
 
9
9
  include ERB::Util
10
-
11
- # Set up entry object to use in the various actions.
12
- before_filter :build_entry, :only => [:new, :create]
13
- before_filter :set_entry, :only => [:show, :edit, :update, :destroy]
14
10
 
15
- helper_method :full_entry_label
11
+ helper_method :entry, :full_entry_label
16
12
 
17
13
  delegate :model_identifier, :to => 'self.class'
18
14
 
@@ -33,15 +29,15 @@ class CrudController < ListController
33
29
  # GET /entries/1
34
30
  # GET /entries/1.json
35
31
  def show
36
- respond_with @entry
32
+ respond_with entry
37
33
  end
38
34
 
39
35
  # Display a form to create a new entry of this model.
40
36
  # GET /entries/new
41
37
  # GET /entries/new.json
42
38
  def new
43
- @entry.attributes = params[model_identifier]
44
- respond_with @entry
39
+ assign_attributes
40
+ respond_with entry
45
41
  end
46
42
 
47
43
  # Create a new entry of this model from the passed params.
@@ -51,16 +47,16 @@ class CrudController < ListController
51
47
  # POST /entries
52
48
  # POST /entries.json
53
49
  def create(&block)
54
- @entry.attributes = params[model_identifier]
55
- created = with_callbacks(:create, :save) { @entry.save }
50
+ assign_attributes
51
+ created = with_callbacks(:create, :save) { entry.save }
56
52
 
57
53
  customizable_respond_to(created, block) do |format|
58
54
  if created
59
55
  format.html { redirect_to_show success_notice }
60
- format.json { render :json => @entry, :status => :created, :location => @entry }
56
+ format.json { render :json => entry, :status => :created, :location => path_args(entry) }
61
57
  else
62
58
  format.html { render_with_callback 'new' }
63
- format.json { render :json => @entry.errors, :status => :unprocessable_entity }
59
+ format.json { render :json => entry.errors, :status => :unprocessable_entity }
64
60
  end
65
61
  end
66
62
  end
@@ -78,8 +74,8 @@ class CrudController < ListController
78
74
  # PUT /entries/1
79
75
  # PUT /entries/1.json
80
76
  def update(&block)
81
- @entry.attributes = params[model_identifier]
82
- updated = with_callbacks(:update, :save) { @entry.save }
77
+ assign_attributes
78
+ updated = with_callbacks(:update, :save) { entry.save }
83
79
 
84
80
  customizable_respond_to(updated, block) do |format|
85
81
  if updated
@@ -87,7 +83,7 @@ class CrudController < ListController
87
83
  format.json { head :ok }
88
84
  else
89
85
  format.html { render_with_callback 'edit' }
90
- format.json { render :json => @entry.errors, :status => :unprocessable_entity }
86
+ format.json { render :json => entry.errors, :status => :unprocessable_entity }
91
87
  end
92
88
  end
93
89
  end
@@ -99,7 +95,7 @@ class CrudController < ListController
99
95
  # DELETE /entries/1
100
96
  # DELETE /entries/1.json
101
97
  def destroy(&block)
102
- destroyed = run_callbacks(:destroy) { @entry.destroy }
98
+ destroyed = run_callbacks(:destroy) { entry.destroy }
103
99
 
104
100
  customizable_respond_to(destroyed, block) do |format|
105
101
  if destroyed
@@ -107,10 +103,10 @@ class CrudController < ListController
107
103
  format.json { head :ok }
108
104
  else
109
105
  format.html {
110
- flash.alert = @entry.errors.full_messages.join('<br/>')
106
+ flash.alert = entry.errors.full_messages.join('<br/>')
111
107
  request.env["HTTP_REFERER"].present? ? redirect_to(:back) : redirect_to_show
112
108
  }
113
- format.json { render :json => @entry.errors, :status => :unprocessable_entity }
109
+ format.json { render :json => entry.errors, :status => :unprocessable_entity }
114
110
  end
115
111
  end
116
112
  end
@@ -119,29 +115,39 @@ class CrudController < ListController
119
115
 
120
116
  ############# CUSTOMIZABLE HELPER METHODS ##############################
121
117
 
118
+ # Main accessor method for the handled model entry.
119
+ def entry
120
+ @entry ||= params[:id] ? find_entry : build_entry
121
+ end
122
+
122
123
  # Creates a new model entry.
123
124
  def build_entry
124
- @entry = model_class.new
125
+ model_scope.new
125
126
  end
126
127
 
127
128
  # Sets an existing model entry from the given id.
128
- def set_entry
129
- @entry = model_class.find(params[:id])
129
+ def find_entry
130
+ model_scope.find(params[:id])
131
+ end
132
+
133
+ # Assigns the attributes from the params to the model entry.
134
+ def assign_attributes
135
+ entry.attributes = params[model_identifier]
130
136
  end
131
137
 
132
138
  # A label for the current entry, including the model name.
133
139
  def full_entry_label
134
- "#{models_label(false)} <i>#{h(@entry)}</i>".html_safe
140
+ "#{models_label(false)} <i>#{h(entry)}</i>".html_safe
135
141
  end
136
142
 
137
143
  # Redirects to the show action of a single entry.
138
144
  def redirect_to_show(options = {})
139
- redirect_to @entry, options
145
+ redirect_to path_args(entry), options
140
146
  end
141
147
 
142
148
  # Redirects to the main action of this controller.
143
149
  def redirect_to_index(options = {})
144
- redirect_to polymorphic_path(model_class, :returning => true), options
150
+ redirect_to polymorphic_path(path_args(model_class), :returning => true), options
145
151
  end
146
152
 
147
153
  # Helper method the run the given block in between the before and after
@@ -6,7 +6,7 @@
6
6
  # the user the same list as he left it.
7
7
  class ListController < ApplicationController
8
8
 
9
- helper_method :model_class, :models_label
9
+ helper_method :model_class, :models_label, :path_args
10
10
 
11
11
  delegate :model_class, :models_label, :to => 'self.class'
12
12
 
@@ -27,8 +27,21 @@ class ListController < ApplicationController
27
27
 
28
28
  # The entries to be displayed in the current index page.
29
29
  def list_entries
30
+ model_scope
31
+ end
32
+
33
+ # The scope where model entries will be listed and created.
34
+ # This is mainly used for nested models to provide the
35
+ # required context.
36
+ def model_scope
30
37
  model_class.scoped
31
38
  end
39
+
40
+ # The path arguments to link to the given entry.
41
+ # If the controller is nested, this provides the required context.
42
+ def path_args(last)
43
+ last
44
+ end
32
45
 
33
46
  # Convenience method to respond to various formats with the given object.
34
47
  def respond_with(object)
@@ -57,7 +70,9 @@ class ListController < ApplicationController
57
70
  # A human readable plural name of the model.
58
71
  def models_label(plural = true)
59
72
  opts = {:count => (plural ? 3 : 1)}
60
- opts[:default] = model_class.model_name.human.pluralize if plural
73
+ opts[:default] = model_class.model_name.human.titleize
74
+ opts[:default] = opts[:default].pluralize if plural
75
+
61
76
  model_class.model_name.human(opts)
62
77
  end
63
78
 
@@ -95,10 +110,14 @@ class ListController < ApplicationController
95
110
  # Compose the search condition with a basic SQL OR query.
96
111
  def search_condition
97
112
  if search_support? && params[:q].present?
98
- clause = search_columns.collect {|f| "#{model_class.table_name}.#{f} LIKE ?" }.
99
- join(" OR ")
100
- param = "%#{params[:q]}%"
101
- ["(#{clause})"] + [param] * search_columns.size
113
+ terms = params[:q].split(/\s+/).collect { |t| "%#{t}%" }
114
+ clause = search_columns.collect do |f|
115
+ col = f.to_s.include?('.') ? f : "#{model_class.table_name}.#{f}"
116
+ "#{col} LIKE ?"
117
+ end.join(" OR ")
118
+ clause = terms.collect {|t| "(#{clause})" }.join(" AND ")
119
+
120
+ ["(#{clause})"] + terms.collect {|t| [t] * search_columns.size }.flatten
102
121
  end
103
122
  end
104
123
 
@@ -171,7 +190,7 @@ class ListController < ApplicationController
171
190
  def self.included(controller)
172
191
  # Define a list of param keys that should be remembered for the list action.
173
192
  controller.class_attribute :remember_params
174
- controller.remember_params = [:q, :sort, :sort_dir]
193
+ controller.remember_params = [:q, :sort, :sort_dir, :page]
175
194
 
176
195
  controller.before_filter :handle_remember_params, :only => [:index]
177
196
  end
@@ -219,4 +238,71 @@ class ListController < ApplicationController
219
238
 
220
239
  include Memory
221
240
 
241
+ # Provides functionality to nest controllers/resources.
242
+ # If a controller is nested, the parent classes and namespaces
243
+ # may be defined as an array in the :nesting class attribute.
244
+ # For example, a cities controller, nested in country and a admin
245
+ # namespace, may define this attribute as follows:
246
+ # self.nesting = :admin, Country
247
+ module Nesting
248
+
249
+ # Adds the :nesting class attribute and parent helper methods
250
+ # to the including controller.
251
+ def self.included(controller)
252
+ controller.class_attribute :nesting
253
+
254
+ controller.helper_method :parent, :parents
255
+
256
+ controller.alias_method_chain :model_scope, :nesting
257
+ controller.alias_method_chain :path_args, :nesting
258
+ end
259
+
260
+ protected
261
+
262
+ # Returns the direct parent ActiveRecord of the current request, if any.
263
+ def parent
264
+ parents.select {|p| p.is_a?(ActiveRecord::Base) }.last
265
+ end
266
+
267
+ # Returns the parent entries of the current request, if any.
268
+ # These are ActiveRecords or namespace symbols, corresponding
269
+ # to the defined nesting attribute.
270
+ def parents
271
+ @parents ||= Array(nesting).collect do |p|
272
+ if p.is_a?(Class) && p < ActiveRecord::Base
273
+ parent_entry(p)
274
+ else
275
+ p
276
+ end
277
+ end
278
+ end
279
+
280
+ # Loads the parent entry for the given ActiveRecord class.
281
+ # By default, performs a find with the class_name_id param.
282
+ def parent_entry(clazz)
283
+ clazz.find(params["#{clazz.name.underscore}_id"])
284
+ end
285
+
286
+ # An array of objects used in url_for and related functions.
287
+ def path_args_with_nesting(last)
288
+ parents + [last]
289
+ end
290
+
291
+ # Uses the parent entry (if any) to constrain the model scope.
292
+ def model_scope_with_nesting
293
+ if parent.present?
294
+ parent_scope
295
+ else
296
+ model_scope_without_nesting
297
+ end
298
+ end
299
+
300
+ # The model scope for the current parent resource.
301
+ def parent_scope
302
+ parent.send(model_class.name.underscore.pluralize)
303
+ end
304
+ end
305
+
306
+ include Nesting
307
+
222
308
  end
@@ -9,7 +9,7 @@ module CrudHelper
9
9
  # If a block is given, a custom form may be rendered and attrs is ignored.
10
10
  def crud_form(*attrs, &block)
11
11
  attrs = attrs_or_default(attrs) { default_attrs - [:created_at, :updated_at] }
12
- standard_form(@entry, *attrs, &block)
12
+ standard_form(path_args(entry), *attrs, &block)
13
13
  end
14
14
 
15
15
  # Create a table of the @entries variable with the default or
@@ -28,40 +28,94 @@ module CrudHelper
28
28
 
29
29
  # Adds a set of standard action link column (show, edit, destroy) to the given table.
30
30
  def add_table_actions(table)
31
- action_col(table) { |e| link_table_action_show(e) }
32
- action_col(table) { |e| link_table_action_edit(e) }
33
- action_col(table) { |e| link_table_action_destroy(e) }
31
+ action_col_show(table)
32
+ action_col_edit(table)
33
+ action_col_destroy(table)
34
34
  end
35
35
 
36
- # Action link to show inside a table.
37
- def link_table_action_show(record)
38
- link_table_action('show', record)
36
+ # Action link to show the row entry inside a table.
37
+ # A block may be given to define the link path for the row entry.
38
+ def action_col_show(table, &block)
39
+ action_col(table) { |e| link_table_action('zoom-in', action_path(e, &block)) }
39
40
  end
40
41
 
41
42
  # Action link to edit inside a table.
42
- def link_table_action_edit(record)
43
- link_table_action('edit', edit_polymorphic_path(record))
43
+ # A block may be given to define the link path for the row entry.
44
+ def action_col_edit(table, &block)
45
+ action_col(table) do |e|
46
+ path = action_path(e, &block)
47
+ link_table_action('pencil', path.is_a?(String) ? path : edit_polymorphic_path(path))
48
+ end
44
49
  end
45
50
 
46
51
  # Action link to destroy inside a table.
47
- def link_table_action_destroy(record)
48
- link_table_action('delete', record,
49
- :confirm => ti(:confirm_delete),
50
- :method => :delete)
52
+ # A block may be given to define the link path for the row entry.
53
+ def action_col_destroy(table, &block)
54
+ action_col(table) do |e|
55
+ link_table_action('remove', action_path(e, &block),
56
+ :confirm => ti(:confirm_delete),
57
+ :method => :delete)
58
+ end
51
59
  end
52
60
 
53
61
  # Generic action link inside a table.
54
- def link_table_action(image, url, html_options = {})
55
- link_to(action_icon(image), url, html_options)
62
+ def link_table_action(icon, url, html_options = {})
63
+ add_css_class html_options, "icon-#{icon}"
64
+ link_to('', url, html_options)
56
65
  end
57
66
 
58
67
  # Defines a column with an action link.
59
68
  def action_col(table, &block)
60
- table.col('', :class => 'center', &block)
69
+ table.col('', :class => 'action', &block)
70
+ end
71
+
72
+ ######## ACTION LINKS ###################################################### :nodoc:
73
+
74
+ # Standard link action to the show page of a given record.
75
+ # Uses the current record if none is given.
76
+ def link_action_show(path = nil)
77
+ path ||= path_args(entry)
78
+ link_action ti(:"link.show"), 'zoom-in', path
79
+ end
80
+
81
+ # Standard link action to the edit page of a given record.
82
+ # Uses the current record if none is given.
83
+ def link_action_edit(path = nil)
84
+ path ||= path_args(entry)
85
+ link_action ti(:"link.edit"), 'pencil', path.is_a?(String) ? path : edit_polymorphic_path(path)
86
+ end
87
+
88
+ # Standard link action to the destroy action of a given record.
89
+ # Uses the current record if none is given.
90
+ def link_action_destroy(path = nil)
91
+ path ||= path_args(entry)
92
+ link_action ti(:"link.delete"), 'remove', path,
93
+ :confirm => ti(:confirm_delete),
94
+ :method => :delete
95
+ end
96
+
97
+ # Standard link action to the list page.
98
+ # Links to the current model_class if no path is given.
99
+ def link_action_index(path = nil, url_options = {:returning => true})
100
+ path ||= path_args(model_class)
101
+ link_action ti(:"link.list"), 'list', path.is_a?(String) ? path : polymorphic_path(path, url_options)
102
+ end
103
+
104
+ # Standard link action to the new page.
105
+ # Links to the current model_class if no path is given.
106
+ def link_action_add(path = nil, url_options = {})
107
+ path ||= path_args(model_class)
108
+ link_action ti(:"link.add"), 'plus', path.is_a?(String) ? path : new_polymorphic_path(path, url_options)
61
109
  end
62
110
 
63
111
  private
64
112
 
113
+ # If a block is given, call it to get the path for the current row entry.
114
+ # Otherwise, return the standard path args.
115
+ def action_path(e, &block)
116
+ block_given? ? yield(e) : path_args(e)
117
+ end
118
+
65
119
  # Returns default attrs for a crud table if no others are passed.
66
120
  def attrs_or_default(attrs)
67
121
  options = attrs.extract_options!
@@ -23,4 +23,5 @@ module ListHelper
23
23
  attrs - [:id, :position, :password]
24
24
  end
25
25
 
26
+
26
27
  end
@@ -9,8 +9,8 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
9
9
 
10
10
  attr_reader :template
11
11
 
12
- delegate :association, :column_type, :column_property, :captionize, :ta,
13
- :to => :template
12
+ delegate :association, :column_type, :column_property, :captionize,
13
+ :content_tag, :ta, :add_css_class, :to => :template
14
14
 
15
15
  # Render multiple input fields together with a label for the given attributes.
16
16
  def labeled_input_fields(*attrs)
@@ -43,6 +43,7 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
43
43
 
44
44
  # Render a number field.
45
45
  def number_field(attr, html_options = {})
46
+ add_css_class html_options, 'span1'
46
47
  html_options[:size] ||= 10
47
48
  super(attr, html_options)
48
49
  end
@@ -79,16 +80,19 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
79
80
 
80
81
  # Render a field to select a date. You might want to customize this.
81
82
  def date_field(attr, html_options = {})
83
+ add_css_class html_options, 'span1'
82
84
  date_select(attr, {}, html_options)
83
85
  end
84
86
 
85
87
  # Render a field to enter a time. You might want to customize this.
86
88
  def time_field(attr, html_options = {})
89
+ add_css_class html_options, 'span1'
87
90
  time_select(attr, {}, html_options)
88
91
  end
89
92
 
90
93
  # Render a field to enter a date and time. You might want to customize this.
91
94
  def datetime_field(attr, html_options = {})
95
+ add_css_class html_options, 'span1'
92
96
  datetime_select(attr, {}, html_options)
93
97
  end
94
98
 
@@ -112,7 +116,11 @@ class StandardFormBuilder < ActionView::Helpers::FormBuilder
112
116
 
113
117
  # Render a label for the given attribute with the passed field html section.
114
118
  def labeled(attr, field_html = nil, &block)
115
- template.labeled(label(attr), field_html, &block)
119
+ field_html = capture(&block) if block_given?
120
+ content_tag(:div,
121
+ label(attr, :class => 'control-label') +
122
+ content_tag(:div, field_html, :class => 'controls'),
123
+ :class => 'control-group')
116
124
  end
117
125
 
118
126
  # Depending if the given attribute must be present, return
@@ -81,7 +81,7 @@ module StandardHelper
81
81
  yield t if block_given?
82
82
  end
83
83
  else
84
- content_tag(:div, ti(:no_list_entries), :class => 'list')
84
+ content_tag(:div, ti(:no_list_entries), :class => 'table')
85
85
  end
86
86
  end
87
87
 
@@ -91,8 +91,14 @@ module StandardHelper
91
91
  # If a block is given, custom input fields may be rendered and attrs is ignored.
92
92
  # An options hash may be given as the last argument.
93
93
  def standard_form(object, *attrs, &block)
94
- form_for(object, {:builder => StandardFormBuilder}.merge(attrs.extract_options!)) do |form|
95
- content = render('shared/error_messages', :errors => object.errors, :object => object)
94
+ options = attrs.extract_options!
95
+ options[:builder] ||= StandardFormBuilder
96
+ options[:html] ||= {}
97
+ add_css_class options[:html], 'form-horizontal'
98
+
99
+ form_for(object, options) do |form|
100
+ record = object.is_a?(Array) ? object.last : object
101
+ content = render('shared/error_messages', :errors => record.errors, :object => record)
96
102
 
97
103
  content << if block_given?
98
104
  capture(form, &block)
@@ -100,7 +106,11 @@ module StandardHelper
100
106
  form.labeled_input_fields(*attrs)
101
107
  end
102
108
 
103
- content << labeled(nil, form.submit(ti(:"button.save")) + cancel_link(object))
109
+ content << content_tag(:div,
110
+ form.button(ti(:"button.save"), :class => 'btn btn-primary') +
111
+ ' ' +
112
+ cancel_link(object),
113
+ :class => 'form-actions')
104
114
  content.html_safe
105
115
  end
106
116
  end
@@ -109,61 +119,24 @@ module StandardHelper
109
119
  link_to(ti(:"button.cancel"), polymorphic_path(object), :class => 'cancel')
110
120
  end
111
121
 
112
- # Alternate table row
113
- def tr_alt(cycle_name = 'row_class', &block)
114
- content_tag(:tr, :class => cycle("even", "odd", :name => cycle_name), &block)
115
- end
116
-
117
- # Renders a div with clear:both style.
118
- def clear
119
- content_tag(:div, '', :class => 'clear')
120
- end
121
-
122
122
 
123
123
  ######## ACTION LINKS ###################################################### :nodoc:
124
124
 
125
- # Standard link action to the show page of a given record.
126
- def link_action_show(record)
127
- link_action ti(:"link.show"), 'show', record
128
- end
129
-
130
- # Standard link action to the edit page of a given record.
131
- def link_action_edit(record)
132
- link_action ti(:"link.edit"), 'edit', edit_polymorphic_path(record)
133
- end
134
-
135
- # Standard link action to the destroy action of a given record.
136
- def link_action_destroy(record)
137
- link_action ti(:"link.delete"), 'delete', record,
138
- :confirm => ti(:confirm_delete),
139
- :method => :delete
140
- end
141
-
142
- # Standard link action to the list page.
143
- def link_action_index(url_options = {:action => 'index', :returning => true})
144
- link_action ti(:"link.list"), 'list', url_options
145
- end
146
-
147
- # Standard link action to the new page.
148
- def link_action_add(url_options = {:action => 'new'})
149
- link_action ti(:"link.add"), 'add', url_options
150
- end
151
-
152
125
  # A generic helper method to create action links.
153
126
  # These link could be styled to look like buttons, for example.
154
127
  def link_action(label, icon = nil, url = {}, html_options = {})
128
+ add_css_class html_options, 'action btn'
155
129
  link_to(icon ? action_icon(icon, label) : label,
156
- url,
157
- {:class => 'action'}.merge(html_options))
130
+ url, html_options)
158
131
  end
159
132
 
160
133
  # Outputs an icon for an action with an optional label.
161
134
  def action_icon(icon, label = nil)
162
- html = image_tag("actions/#{icon}.png", :size => '16x16')
135
+ html = content_tag(:i, "", :class => "icon-#{icon}")
163
136
  html << ' ' << label if label
164
137
  html
165
138
  end
166
-
139
+
167
140
  # Translates the passed key by looking it up over the controller hierarchy.
168
141
  # The key is searched in the following order:
169
142
  # - {controller}.{current_partial}.{key}
@@ -216,6 +189,24 @@ module StandardHelper
216
189
  alias_method :ta, :translate_association
217
190
 
218
191
 
192
+ # Returns the css class for the given flash level.
193
+ def flash_class(level)
194
+ case level
195
+ when :notice then 'success'
196
+ when :error then 'error'
197
+ when :alert then 'error'
198
+ end
199
+ end
200
+
201
+ # Adds a class to the given options, even if there are already classes.
202
+ def add_css_class(options, classes)
203
+ if options[:class]
204
+ options[:class] += ' ' + classes
205
+ else
206
+ options[:class] = classes
207
+ end
208
+ end
209
+
219
210
  protected
220
211
 
221
212
  # Helper methods that are not directly called from templates.
@@ -11,7 +11,7 @@ class StandardTableBuilder
11
11
  # Delegate called methods to template.
12
12
  # including StandardHelper would lead to problems with indirectly called methods.
13
13
  delegate :content_tag, :format_attr, :column_type, :association,
14
- :captionize, :tr_alt, :to => :template
14
+ :captionize, :add_css_class, :to => :template
15
15
 
16
16
  def initialize(entries, template, options = {})
17
17
  @entries = entries
@@ -55,7 +55,8 @@ class StandardTableBuilder
55
55
 
56
56
  # Renders the table as HTML.
57
57
  def to_html
58
- content_tag :table, :class => 'list' do
58
+ add_css_class options, 'table'
59
+ content_tag :table, options do
59
60
  content_tag(:thead, html_header) +
60
61
  content_tag(:tbody, safe_join(entries) { |e| html_row(e) })
61
62
  end
@@ -86,7 +87,7 @@ class StandardTableBuilder
86
87
  end
87
88
 
88
89
  def html_row(entry)
89
- tr_alt do
90
+ content_tag :tr do
90
91
  safe_join(cols) { |c| c.html_cell(entry) }
91
92
  end
92
93
  end
@@ -1,3 +1,3 @@
1
1
  <%= link_action_index %>
2
- <%= link_action_show @entry %>
3
- <%= link_action_destroy @entry %>
2
+ <%= link_action_show %>
3
+ <%= link_action_destroy %>
@@ -0,0 +1,3 @@
1
+ = link_action_index
2
+ = link_action_show
3
+ = link_action_destroy
@@ -1,3 +1,3 @@
1
1
  <%= link_action_index %>
2
- <%= link_action_edit(@entry) %>
3
- <%= link_action_destroy(@entry) %>
2
+ <%= link_action_edit %>
3
+ <%= link_action_destroy %>
@@ -0,0 +1,3 @@
1
+ = link_action_index
2
+ = link_action_edit
3
+ = link_action_destroy
@@ -1 +1 @@
1
- <%= render_attrs @entry, *default_attrs %>
1
+ <%= render_attrs entry, *default_attrs %>
@@ -0,0 +1 @@
1
+ = render_attrs entry, *default_attrs
@@ -2,6 +2,4 @@
2
2
 
3
3
  <% content_for(:actions, render('actions_edit')) %>
4
4
 
5
- <%= clear %>
6
-
7
5
  <%= render 'form' %>
@@ -0,0 +1,5 @@
1
+ - @title ||= ti(:title, :model => full_entry_label).html_safe
2
+
3
+ - content_for(:actions, render('actions_edit'))
4
+
5
+ = render 'form'