dry_crud 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/README.rdoc +24 -19
  2. data/Rakefile +12 -4
  3. data/VERSION +1 -1
  4. data/lib/generators/dry_crud/dry_crud_generator.rb +7 -7
  5. data/lib/generators/dry_crud/templates/app/assets/stylesheets/crud.scss +18 -7
  6. data/lib/generators/dry_crud/templates/app/assets/stylesheets/sample.scss +13 -18
  7. data/lib/generators/dry_crud/templates/app/controllers/crud_controller.rb +74 -87
  8. data/lib/generators/dry_crud/templates/app/controllers/list_controller.rb +95 -50
  9. data/lib/generators/dry_crud/templates/app/helpers/crud_helper.rb +11 -11
  10. data/lib/generators/dry_crud/templates/app/helpers/list_helper.rb +7 -7
  11. data/lib/generators/dry_crud/templates/app/helpers/standard_form_builder.rb +55 -27
  12. data/lib/generators/dry_crud/templates/app/helpers/standard_helper.rb +83 -30
  13. data/lib/generators/dry_crud/templates/app/helpers/standard_table_builder.rb +5 -13
  14. data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.erb +1 -4
  15. data/lib/generators/dry_crud/templates/app/views/layouts/_flash.html.haml +1 -3
  16. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.erb +6 -6
  17. data/lib/generators/dry_crud/templates/app/views/layouts/_nav.html.haml +5 -3
  18. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.erb +13 -11
  19. data/lib/generators/dry_crud/templates/app/views/layouts/crud.html.haml +15 -15
  20. data/lib/generators/dry_crud/templates/app/views/shared/_error_messages.html.erb +10 -10
  21. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.erb +2 -2
  22. data/lib/generators/dry_crud/templates/app/views/shared/_labeled.html.haml +2 -2
  23. data/lib/generators/dry_crud/templates/config/initializers/field_error_proc.rb +1 -0
  24. data/lib/generators/dry_crud/templates/config/locales/en_crud.yml +1 -0
  25. data/lib/generators/dry_crud/templates/test/crud_test_model.rb +72 -17
  26. data/lib/generators/dry_crud/templates/test/custom_assertions.rb +1 -1
  27. data/lib/generators/dry_crud/templates/test/functional/crud_controller_test_helper.rb +42 -26
  28. data/lib/generators/dry_crud/templates/test/functional/crud_test_models_controller_test.rb +135 -29
  29. data/lib/generators/dry_crud/templates/test/unit/custom_assertions_test.rb +4 -4
  30. data/lib/generators/dry_crud/templates/test/unit/helpers/crud_helper_test.rb +4 -2
  31. data/lib/generators/dry_crud/templates/test/unit/helpers/list_helper_test.rb +2 -0
  32. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_form_builder_test.rb +94 -16
  33. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_helper_test.rb +58 -18
  34. data/lib/generators/dry_crud/templates/test/unit/helpers/standard_table_builder_test.rb +4 -4
  35. data/test/templates/Gemfile +1 -0
  36. data/test/templates/app/controllers/admin/cities_controller.rb +0 -7
  37. data/test/templates/app/controllers/admin/countries_controller.rb +2 -3
  38. data/test/templates/app/controllers/ajax_controller.rb +2 -0
  39. data/test/templates/app/controllers/people_controller.rb +1 -1
  40. data/test/templates/app/models/city.rb +2 -0
  41. data/test/templates/app/models/country.rb +2 -0
  42. data/test/templates/app/models/person.rb +2 -0
  43. data/test/templates/app/views/admin/cities/_attrs.html.erb +1 -0
  44. data/test/templates/app/views/admin/cities/_attrs.html.haml +1 -0
  45. data/test/templates/app/views/admin/cities/_form.html.erb +7 -1
  46. data/test/templates/app/views/admin/cities/_form.html.haml +5 -1
  47. data/test/templates/app/views/admin/cities/_list.html.erb +1 -4
  48. data/test/templates/app/views/admin/cities/_list.html.haml +1 -3
  49. data/test/templates/app/views/ajax/_actions_show.html.erb +4 -0
  50. data/test/templates/app/views/ajax/_actions_show.html.haml +4 -0
  51. data/test/templates/app/views/ajax/_form.html.erb +2 -0
  52. data/test/templates/app/views/ajax/_form.html.haml +2 -0
  53. data/test/templates/app/views/ajax/edit.js.erb +1 -0
  54. data/test/templates/app/views/ajax/edit.js.haml +1 -0
  55. data/test/templates/app/views/ajax/show.js.erb +1 -0
  56. data/test/templates/app/views/ajax/show.js.haml +1 -0
  57. data/test/templates/app/views/ajax/update.js.erb +5 -0
  58. data/test/templates/app/views/ajax/update.js.haml +5 -0
  59. data/test/templates/app/views/layouts/_nav.html.erb +6 -0
  60. data/test/templates/app/views/layouts/_nav.html.haml +5 -0
  61. data/test/templates/app/views/layouts/bootstrap.html.erb +68 -0
  62. data/test/templates/app/views/layouts/bootstrap.html.haml +49 -0
  63. data/test/templates/app/views/people/_attrs.html.erb +2 -2
  64. data/test/templates/app/views/people/_attrs.html.haml +2 -2
  65. data/test/templates/config/routes.rb +5 -5
  66. data/test/templates/db/migrate/20100511174904_create_people_and_cities.rb +1 -1
  67. data/test/templates/db/seeds.rb +52 -52
  68. data/test/templates/test/functional/admin/cities_controller_test.rb +15 -15
  69. data/test/templates/test/functional/admin/countries_controller_test.rb +4 -5
  70. data/test/templates/test/functional/people_controller_test.rb +32 -4
  71. metadata +22 -9
  72. data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.erb +0 -3
  73. data/lib/generators/dry_crud/templates/app/views/layouts/_menu.html.haml +0 -3
  74. data/test/templates/app/views/layouts/_menu.html.erb +0 -3
  75. data/test/templates/app/views/layouts/_menu.html.haml +0 -3
@@ -22,7 +22,7 @@ module StandardHelper
22
22
  end
23
23
 
24
24
  # Formats an arbitrary attribute of the given ActiveRecord object.
25
- # If no specific format_{type}_{attr} or format_{attr} method is found,
25
+ # If no specific format_{type}_{attr} or format_{attr} method is found,
26
26
  # formats the value as follows:
27
27
  # If the value is an associated model, renders the label of this object.
28
28
  # Otherwise, calls format_type.
@@ -35,6 +35,8 @@ module StandardHelper
35
35
  send(format_attr_method, obj)
36
36
  elsif assoc = association(obj, attr, :belongs_to)
37
37
  format_assoc(obj, assoc)
38
+ elsif assoc = association(obj, attr, :has_many, :has_and_belongs_to_many)
39
+ format_many_assoc(obj, assoc)
38
40
  else
39
41
  format_type(obj, attr)
40
42
  end
@@ -52,17 +54,18 @@ module StandardHelper
52
54
 
53
55
  # Transform the given text into a form as used by labels or table headers.
54
56
  def captionize(text, clazz = nil)
57
+ text = text.to_s
55
58
  if clazz.respond_to?(:human_attribute_name)
56
- clazz.human_attribute_name(text)
59
+ clazz.human_attribute_name(text.end_with?('_ids') ? text[0..-5].pluralize : text)
57
60
  else
58
- text.to_s.humanize.titleize
61
+ text.humanize.titleize
59
62
  end
60
63
  end
61
64
 
62
65
  # Renders a list of attributes with label and value for a given object.
63
66
  # Optionally surrounded with a div.
64
67
  def render_attrs(obj, *attrs)
65
- attrs.collect { |a| labeled_attr(obj, a) }.join("\n").html_safe
68
+ safe_join(attrs) { |a| labeled_attr(obj, a) }
66
69
  end
67
70
 
68
71
  # Renders the formatted content of the given attribute with a label.
@@ -95,7 +98,7 @@ module StandardHelper
95
98
  options[:builder] ||= StandardFormBuilder
96
99
  options[:html] ||= {}
97
100
  add_css_class options[:html], 'form-horizontal'
98
-
101
+
99
102
  form_for(object, options) do |form|
100
103
  record = object.is_a?(Array) ? object.last : object
101
104
  content = render('shared/error_messages', :errors => record.errors, :object => record)
@@ -106,19 +109,39 @@ module StandardHelper
106
109
  form.labeled_input_fields(*attrs)
107
110
  end
108
111
 
109
- content << content_tag(:div,
110
- form.button(ti(:"button.save"), :class => 'btn btn-primary') +
111
- ' ' +
112
- cancel_link(object),
113
- :class => 'form-actions')
112
+ content << content_tag(:div, :class => 'form-actions') do
113
+ form.button(ti(:"button.save"), :class => 'btn btn-primary') +
114
+ ' ' +
115
+ cancel_link(object)
116
+ end
114
117
  content.html_safe
115
118
  end
116
119
  end
117
120
 
118
121
  def cancel_link(object)
119
- link_to(ti(:"button.cancel"), polymorphic_path(object), :class => 'cancel')
122
+ link_to(ti(:"button.cancel"), polymorphic_path(object, :returning => true), :class => 'cancel')
123
+ end
124
+
125
+ # Renders a simple unordered list, which will
126
+ # simply render all passed items or yield them
127
+ # to your block.
128
+ def simple_list(items,ul_options={},&blk)
129
+ content_tag_nested(:ul, items, ul_options) do |item|
130
+ content_tag(:li, block_given? ? yield(item) : f(item))
131
+ end
132
+ end
133
+
134
+ # render a content tag with the collected contents rendered
135
+ # by &block for each item in collection.
136
+ def content_tag_nested(tag, collection, options = {}, &block)
137
+ content_tag(tag, safe_join(collection, &block), options)
120
138
  end
121
139
 
140
+ # Overridden method that takes a block that is executed for each item in array
141
+ # before appending the results.
142
+ def safe_join(array, sep = $,, &block)
143
+ super(block_given? ? array.collect(&block) : array, sep)
144
+ end
122
145
 
123
146
  ######## ACTION LINKS ###################################################### :nodoc:
124
147
 
@@ -136,8 +159,8 @@ module StandardHelper
136
159
  html << ' ' << label if label
137
160
  html
138
161
  end
139
-
140
- # Translates the passed key by looking it up over the controller hierarchy.
162
+
163
+ # Translates the passed key by looking it up over the controller hierarchy.
141
164
  # The key is searched in the following order:
142
165
  # - {controller}.{current_partial}.{key}
143
166
  # - {controller}.{current_action}.{key}
@@ -161,15 +184,15 @@ module StandardHelper
161
184
  current = current.superclass
162
185
  end
163
186
  defaults << :"global.#{key}"
164
-
187
+
165
188
  variables[:default] ||= defaults
166
189
  t(defaults.shift, variables)
167
190
  end
168
-
191
+
169
192
  alias_method :ti, :translate_inheritable
170
193
 
171
194
  # Translates the passed key for an active record association. This helper is used
172
- # for rendering association dependent keys in forms like :no_entry, :none_available or
195
+ # for rendering association dependent keys in forms like :no_entry, :none_available or
173
196
  # :please_select.
174
197
  # The key is looked up in the following order:
175
198
  # - activerecord.associations.models.{model_name}.{association_name}.{key}
@@ -185,19 +208,19 @@ module StandardHelper
185
208
  end
186
209
  t(primary, variables)
187
210
  end
188
-
211
+
189
212
  alias_method :ta, :translate_association
190
-
191
-
213
+
214
+
192
215
  # Returns the css class for the given flash level.
193
216
  def flash_class(level)
194
217
  case level
195
218
  when :notice then 'success'
196
- when :error then 'error'
197
219
  when :alert then 'error'
220
+ else level.to_s
198
221
  end
199
222
  end
200
-
223
+
201
224
  # Adds a class to the given options, even if there are already classes.
202
225
  def add_css_class(options, classes)
203
226
  if options[:class]
@@ -206,7 +229,7 @@ module StandardHelper
206
229
  options[:class] = classes
207
230
  end
208
231
  end
209
-
232
+
210
233
  protected
211
234
 
212
235
  # Helper methods that are not directly called from templates.
@@ -220,7 +243,7 @@ module StandardHelper
220
243
  case column_type(obj, attr)
221
244
  when :time then f(val.to_time)
222
245
  when :date then f(val.to_date)
223
- when :datetime, :timestamp then "#{f(val.to_date)} #{f(val.to_time)}"
246
+ when :datetime, :timestamp then "#{f(val.to_date)} #{f(val.time)}"
224
247
  when :text then val.present? ? simple_format(h(val)) : EMPTY_STRING
225
248
  when :decimal then f(val.to_s.to_f)
226
249
  else f(val)
@@ -240,15 +263,33 @@ module StandardHelper
240
263
  end
241
264
  end
242
265
 
243
- # Formats an active record association
266
+ # Formats an active record belongs_to association
244
267
  def format_assoc(obj, assoc)
245
- if assoc_val = obj.send(assoc.name)
246
- link_to_unless(no_assoc_link?(assoc, assoc_val), assoc_val, assoc_val)
268
+ if val = obj.send(assoc.name)
269
+ assoc_link(assoc, val)
270
+ else
271
+ ta(:no_entry, assoc)
272
+ end
273
+ end
274
+
275
+ # Formats an active record has_and_belongs_to_many or
276
+ # has_many association.
277
+ def format_many_assoc(obj, assoc)
278
+ values = obj.send(assoc.name)
279
+ if values.size == 1
280
+ assoc_link(assoc, values.first)
281
+ elsif values.present?
282
+ simple_list(values) { |val| assoc_link(assoc, val) }
247
283
  else
248
284
  ta(:no_entry, assoc)
249
285
  end
250
286
  end
251
287
 
288
+ # Renders a link to the given association entry.
289
+ def assoc_link(assoc, val)
290
+ link_to_unless(no_assoc_link?(assoc, val), val.to_s, val)
291
+ end
292
+
252
293
  # Returns true if no link should be created when formatting the given association.
253
294
  def no_assoc_link?(assoc, val)
254
295
  !respond_to?("#{val.class.model_name.underscore}_path".to_sym)
@@ -259,12 +300,24 @@ module StandardHelper
259
300
  # is given, the association must be of this type, otherwise, any association
260
301
  # is returned. Returns nil if no association (or not of the given macro) was
261
302
  # found.
262
- def association(obj, attr, macro = nil)
303
+ def association(obj, attr, *macros)
263
304
  if obj.class.respond_to?(:reflect_on_association)
264
- name = attr.to_s =~ /_id$/ ? attr.to_s[0..-4].to_sym : attr
305
+ name = assoc_and_id_attr(attr).first.to_sym
265
306
  assoc = obj.class.reflect_on_association(name)
266
- assoc if assoc && (macro.nil? || assoc.macro == macro)
307
+ assoc if assoc && (macros.blank? || macros.include?(assoc.macro))
308
+ end
309
+ end
310
+
311
+ # Returns the name of the attr and it's corresponding field
312
+ def assoc_and_id_attr(attr)
313
+ attr = attr.to_s
314
+ attr, attr_id = if attr.end_with?('_id')
315
+ [attr[0..-4], attr]
316
+ elsif attr.end_with?('_ids')
317
+ [attr[0..-5].pluralize, attr]
318
+ else
319
+ [attr, "#{attr}_id"]
267
320
  end
268
321
  end
269
322
 
270
- end
323
+ end
@@ -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, :add_css_class, :to => :template
14
+ :captionize, :add_css_class, :content_tag_nested, :to => :template
15
15
 
16
16
  def initialize(entries, template, options = {})
17
17
  @entries = entries
@@ -57,8 +57,8 @@ class StandardTableBuilder
57
57
  def to_html
58
58
  add_css_class options, 'table'
59
59
  content_tag :table, options do
60
- content_tag(:thead, html_header) +
61
- content_tag(:tbody, safe_join(entries) { |e| html_row(e) })
60
+ content_tag(:thead, html_header) +
61
+ content_tag_nested(:tbody, entries) { |e| html_row(e) }
62
62
  end
63
63
  end
64
64
 
@@ -81,24 +81,16 @@ class StandardTableBuilder
81
81
  private
82
82
 
83
83
  def html_header
84
- content_tag :tr do
85
- safe_join(cols) { |c| c.html_header }
86
- end
84
+ content_tag_nested(:tr, cols) { |c| c.html_header }
87
85
  end
88
86
 
89
87
  def html_row(entry)
90
- content_tag :tr do
91
- safe_join(cols) { |c| c.html_cell(entry) }
92
- end
88
+ content_tag_nested(:tr, cols) { |c| c.html_cell(entry) }
93
89
  end
94
90
 
95
91
  def entry_class
96
92
  entries.first.class
97
93
  end
98
-
99
- def safe_join(collection, &block)
100
- collection.collect(&block).join.html_safe
101
- end
102
94
 
103
95
  # Helper class to store column information.
104
96
  class Col < Struct.new(:header, :html_options, :template, :block) #:nodoc:
@@ -1,8 +1,5 @@
1
1
  <% if flash[level].present? %>
2
2
  <div class="alert alert-<%= flash_class(level) %>">
3
- <a class="close" href="#" data-dismiss="alert">&times;</a>
4
- <div>
5
- <%= raw flash[level] %>
6
- </div>
3
+ <%= flash[level] %>
7
4
  </div>
8
5
  <% end %>
@@ -1,4 +1,2 @@
1
1
  - if flash[level].present?
2
- %div{:class => "alert alert-#{flash_class(level)}"}
3
- %a.close{:'data-dismiss' => 'alert'} &times;
4
- %div= raw(flash[level])
2
+ %div{:class => "alert alert-#{flash_class(level)}"}= flash[level]
@@ -1,6 +1,6 @@
1
- <div class="navbar">
2
- <%= link_to 'MyApp', root_path, :class => 'brand' %>
3
- <ul class="nav">
4
- <%= render 'layouts/menu' %>
5
- </ul>
6
- </div>
1
+ <%= link_to 'MyApp', root_path, :class => 'brand' %>
2
+ <ul class="nav">
3
+ <li><%= link_to "Link1", "/path1" %></li>
4
+ <li><%= link_to "Link2", "/path2" %></li>
5
+ <li><%= link_to "Link3", "/path3" %></li>
6
+ </ul>
@@ -1,3 +1,5 @@
1
- .navbar
2
- = link_to 'MyApp', root_path, :class => 'brand'
3
- %ul.nav= render 'layouts/menu'
1
+ = link_to 'MyApp', root_path, :class => 'brand'
2
+ %ul.nav
3
+ %li= link_to "Link1", "/path1"
4
+ %li= link_to "Link2", "/path2"
5
+ %li= link_to "Link3", "/path3"
@@ -12,44 +12,46 @@
12
12
  <![endif]-->
13
13
 
14
14
  <%= stylesheet_link_tag 'application', :media => 'all' %>
15
-
15
+
16
16
  <!-- fav and touch icons -->
17
17
  <link href="images/favicon.ico" rel="shortcut icon">
18
18
  <link href="images/apple-touch-icon.png" rel="apple-touch-icon">
19
19
  <link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon" sizes="72x72">
20
20
  <link href="images/apple-touch-icon-114x114.png" rel="apple-touch-icon" sizes="114x114">
21
-
21
+
22
22
  <%= yield :head %>
23
23
  </head>
24
24
  <body>
25
-
25
+
26
26
 
27
27
  <div class="container">
28
- <%= render 'layouts/nav' %>
29
-
28
+ <div class="navbar">
29
+ <%= render 'layouts/nav' %>
30
+ </div>
31
+
30
32
  <h1><%= @title %></h1>
31
33
 
32
34
  <%= render :partial => 'layouts/flash', :collection => [:notice, :alert], :as => :level %>
33
35
 
34
36
  <div class="actions btn-toolbar">
35
- <div class="pull-left">
36
- <%= yield :tools %>
37
- </div>
38
37
  <div class="pull-right">
39
38
  <%= yield :actions %>
40
39
  </div>
40
+ <div class="pull-left">
41
+ <%= yield :tools %>
42
+ </div>
41
43
  </div>
42
44
 
43
45
  <div id="content">
44
46
  <%= yield %>
45
47
  </div>
46
-
48
+
47
49
  </div>
48
50
 
49
51
  <footer>
50
- <p>&copy; Company <%= Time.now.year %></p>
52
+ <p>&copy; code!z <%= Time.zone.now.year %></p>
51
53
  </footer>
52
-
54
+
53
55
  <!-- Javascript placed at the end of the document so the pages load faster -->
54
56
  <%= javascript_include_tag 'application' %>
55
57
  <%= javascript_tag yield(:javascripts) if content_for?(:javascripts) %>
@@ -5,38 +5,38 @@
5
5
  %meta{:charset => 'utf-8'}
6
6
  %title= strip_tags(@title)
7
7
  = csrf_meta_tag
8
-
8
+
9
9
  <!-- HTML5 shim, for IE6-8 support of HTML elements -->
10
10
  <!--[if lt IE 9]>
11
11
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
12
12
  <![endif]-->
13
-
13
+
14
14
  = stylesheet_link_tag 'application', :media => 'all'
15
-
15
+
16
16
  %link{:href => "images/favicon.ico", :rel => "shortcut icon"}
17
17
  %link{:href => "images/apple-touch-icon.png", :rel => "apple-touch-icon"}
18
18
  %link{:href => "images/apple-touch-icon-72x72.png", :rel => "apple-touch-icon", :sizes => "72x72"}
19
19
  %link{:href => "images/apple-touch-icon-114x114.png", :rel => "apple-touch-icon", :sizes => "114x114"}
20
-
20
+
21
21
  = yield :head
22
-
22
+
23
23
  %body
24
24
  .container
25
- = render 'layouts/nav'
26
-
25
+ .navbar= render 'layouts/nav'
26
+
27
27
  %h1= @title
28
-
28
+
29
29
  = render :partial => 'layouts/flash', :collection => [:notice, :alert], :as => :level
30
-
31
- .actions.btn-toolbar.clearfix
32
- .pull-left=yield :tools
30
+
31
+ .actions.btn-toolbar
33
32
  .pull-right= yield :actions
34
-
33
+ .pull-left= yield :tools
34
+
35
35
  #content= yield
36
-
36
+
37
37
  %footer
38
38
  %p
39
- &copy; MyCompany #{Time.now.year}
40
-
39
+ &copy; code!z #{Time.zone.now.year}
40
+
41
41
  = javascript_include_tag 'application'
42
42
  = javascript_tag yield(:javascripts) if content_for?(:javascripts)
@@ -1,12 +1,12 @@
1
1
  <% if errors.any? %>
2
- <div id='error_explanation' class='alert alert-error'>
3
- <h2>
4
- <%= ti(:"errors.header", :count => errors.count, :model => object.to_s) %>
5
- </h2>
6
- <ul>
7
- <% errors.full_messages.each do |msg| %>
8
- <li><%= msg %></li>
9
- <% end %>
10
- </ul>
11
- </div>
2
+ <div id='error_explanation' class='alert alert-error'>
3
+ <h2>
4
+ <%= ti(:"errors.header", :count => errors.count, :model => object.to_s) %>
5
+ </h2>
6
+ <ul>
7
+ <% errors.full_messages.each do |msg| %>
8
+ <li><%= msg %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
12
  <% end -%>
@@ -1,4 +1,4 @@
1
1
  <div class="labeled">
2
- <label><%= label.presence || raw(StandardHelper::EMPTY_STRING) %></label>
3
- <div class="value"><%= content.presence || raw(StandardHelper::EMPTY_STRING) %></div>
2
+ <label><%= label.presence || raw(StandardHelper::EMPTY_STRING) %></label>
3
+ <div class="value"><%= content.presence || raw(StandardHelper::EMPTY_STRING) %></div>
4
4
  </div>
@@ -1,3 +1,3 @@
1
1
  .labeled
2
- %label= label.presence || raw(StandardHelper::EMPTY_STRING)
3
- .value= content.presence || raw(StandardHelper::EMPTY_STRING)
2
+ %label= label.presence || raw(StandardHelper::EMPTY_STRING)
3
+ .value= content.presence || raw(StandardHelper::EMPTY_STRING)
@@ -0,0 +1 @@
1
+ ActionView::Base.field_error_proc = Proc.new {|html_tag, instance| html_tag }
@@ -61,3 +61,4 @@ en:
61
61
  destroy:
62
62
  flash:
63
63
  success: "%{model} was successfully deleted."
64
+ failure: "%{model} could not be deleted."
@@ -1,7 +1,13 @@
1
1
  # A dummy model used for general testing.
2
2
  class CrudTestModel < ActiveRecord::Base #:nodoc:
3
3
 
4
+ attr_protected nil
5
+
4
6
  belongs_to :companion, :class_name => 'CrudTestModel'
7
+ has_and_belongs_to_many :others, :class_name => 'OtherCrudTestModel'
8
+ has_many :mores, :class_name => 'OtherCrudTestModel', :foreign_key => :more_id
9
+
10
+ before_destroy :protect_if_companion
5
11
 
6
12
  validates :name, :presence => true
7
13
  validates :rating, :inclusion => { :in => 1..10 }
@@ -15,7 +21,28 @@ class CrudTestModel < ActiveRecord::Base #:nodoc:
15
21
  def chatty
16
22
  remarks.size
17
23
  end
18
-
24
+
25
+ private
26
+
27
+ def protect_if_companion
28
+ if companion.present?
29
+ errors.add(:base, 'Cannot destroy model with companion')
30
+ false
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ class OtherCrudTestModel < ActiveRecord::Base #:nodoc:
37
+
38
+ attr_protected nil
39
+
40
+ has_and_belongs_to_many :others, :class_name => 'CrudTestModel'
41
+ belongs_to :more, :foreign_key => :more_id, :class_name => 'CrudTestModel'
42
+
43
+ def to_s
44
+ name
45
+ end
19
46
  end
20
47
 
21
48
  # Controller for the dummy model.
@@ -27,6 +54,7 @@ class CrudTestModelsController < CrudController #:nodoc:
27
54
 
28
55
  before_create :possibly_redirect
29
56
  before_create :handle_name
57
+ before_destroy :handle_name
30
58
 
31
59
  before_render_new :possibly_redirect
32
60
  before_render_new :set_companions
@@ -39,10 +67,22 @@ class CrudTestModelsController < CrudController #:nodoc:
39
67
  # don't use the standard layout as it may require different routes
40
68
  # than just the test route for this controller
41
69
  layout false
42
-
43
- def destroy
44
- super do |success, format|
45
- format.html { redirect_to_index :notice => 'model is gone' } if success
70
+
71
+ def index
72
+ super do |format|
73
+ format.js { render :text => 'index js'}
74
+ end
75
+ end
76
+
77
+ def show
78
+ super do |format|
79
+ format.html { render :text => 'custom html' } if entry.name == 'BBBBB'
80
+ end
81
+ end
82
+
83
+ def create
84
+ super do |format|
85
+ flash[:notice] = 'model got created' if entry.persisted?
46
86
  end
47
87
  end
48
88
 
@@ -60,9 +100,9 @@ class CrudTestModelsController < CrudController #:nodoc:
60
100
 
61
101
  # custom callback
62
102
  def handle_name
63
- if @entry.name == 'illegal'
64
- flash[:error] = "illegal name"
65
- return false
103
+ if entry.name == 'illegal'
104
+ flash[:alert] = "illegal name"
105
+ false
66
106
  end
67
107
  end
68
108
 
@@ -113,11 +153,11 @@ module CrudTestHelper
113
153
  def model_class
114
154
  CrudTestModel
115
155
  end
116
-
156
+
117
157
  def controller_name
118
158
  'crud_test_models'
119
159
  end
120
-
160
+
121
161
  def action_name
122
162
  'index'
123
163
  end
@@ -125,7 +165,7 @@ module CrudTestHelper
125
165
  def params
126
166
  {}
127
167
  end
128
-
168
+
129
169
  def path_args(entry)
130
170
  entry
131
171
  end
@@ -133,11 +173,11 @@ module CrudTestHelper
133
173
  def sortable?(attr)
134
174
  true
135
175
  end
136
-
176
+
137
177
  def h(text)
138
178
  ERB::Util.h(text)
139
179
  end
140
-
180
+
141
181
  protected
142
182
 
143
183
  # Sets up the test database with a crud_test_models table.
@@ -162,6 +202,14 @@ module CrudTestHelper
162
202
  t.timestamps
163
203
  end
164
204
  end
205
+ ActiveRecord::Base.connection.create_table :other_crud_test_models, :force => true do |t|
206
+ t.string :name, :null => false, :limit => 50
207
+ t.integer :more_id
208
+ end
209
+ ActiveRecord::Base.connection.create_table :crud_test_models_other_crud_test_models, :force => true do |t|
210
+ t.belongs_to :crud_test_model
211
+ t.belongs_to :other_crud_test_model
212
+ end
165
213
 
166
214
  CrudTestModel.reset_column_information
167
215
  end
@@ -170,7 +218,7 @@ module CrudTestHelper
170
218
  # Removes the crud_test_models table from the database.
171
219
  def reset_db
172
220
  c = ActiveRecord::Base.connection
173
- [:crud_test_models].each do |table|
221
+ [:crud_test_models, :other_crud_test_models, :crud_test_models_other_crud_test_models].each do |table|
174
222
  if c.table_exists?(table)
175
223
  c.drop_table(table) rescue nil
176
224
  end
@@ -180,6 +228,7 @@ module CrudTestHelper
180
228
  # Creates 6 dummy entries for the crud_test_models table.
181
229
  def create_test_data
182
230
  (1..6).inject(nil) {|prev, i| create(i, prev) }
231
+ (1..6).each {|i| create_other(i) }
183
232
  end
184
233
 
185
234
  # Fixture-style accessor method to get CrudTestModel instances by name
@@ -207,14 +256,20 @@ module CrudTestHelper
207
256
  :income => 10000000 * index + 0.1 * index,
208
257
  :birthdate => "#{1900 + 10 * index}-#{index}-#{index}",
209
258
  # store entire date to avoid time zone issues
210
- :gets_up_at => RUBY_VERSION.include?('1.9.') ?
259
+ :gets_up_at => RUBY_VERSION.include?('1.9.') ?
211
260
  Time.local(2000,1,1,index,index) :
212
- Time.utc(2000,1,1,index,index),
261
+ Time.utc(2000,1,1,index,index),
213
262
  :last_seen => "#{2000 + 10 * index}-#{index}-#{index} 1#{index}:2#{index}",
214
263
  :human => index % 2 == 0,
215
264
  :remarks => "#{c} #{str(index + 1)} #{str(index + 2)}\n" * (index % 3 + 1))
216
265
  end
217
266
 
267
+ def create_other(index)
268
+ c = str(index)
269
+ others = CrudTestModel.all[index..(index+2)]
270
+ OtherCrudTestModel.create!(:name => c, :other_ids => others.collect(&:id), :more_id => others.first.try(:id))
271
+ end
272
+
218
273
  def str(index)
219
274
  (index + 64).chr * 5
220
275
  end
@@ -233,5 +288,5 @@ module CrudTestHelper
233
288
 
234
289
  c.execute("BEGIN") if start_transaction
235
290
  end
236
-
291
+
237
292
  end
@@ -63,7 +63,7 @@ module CustomAssertions
63
63
  end
64
64
  end
65
65
  end
66
-
66
+
67
67
  # The method used to by Test::Unit to format arguments in
68
68
  # #build_message. Prints ActiveRecord objects in a simpler format.
69
69
  # Only works for Ruby 1.9