active_scaffold 3.4.17 → 3.4.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +12 -1
  3. data/README.md +8 -4
  4. data/app/assets/javascripts/jquery/active_scaffold.js +82 -67
  5. data/app/assets/stylesheets/active_scaffold.scss +1 -1
  6. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  7. data/app/assets/stylesheets/blue-theme.css +1 -1
  8. data/app/views/active_scaffold_overrides/_form_association.html.erb +3 -3
  9. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +3 -3
  10. data/app/views/active_scaffold_overrides/_show_columns.html.erb +1 -1
  11. data/lib/active_scaffold.rb +16 -16
  12. data/lib/active_scaffold/actions/common_search.rb +13 -11
  13. data/lib/active_scaffold/actions/core.rb +85 -78
  14. data/lib/active_scaffold/actions/create.rb +29 -28
  15. data/lib/active_scaffold/actions/delete.rb +17 -17
  16. data/lib/active_scaffold/actions/field_search.rb +18 -19
  17. data/lib/active_scaffold/actions/list.rb +30 -22
  18. data/lib/active_scaffold/actions/mark.rb +1 -1
  19. data/lib/active_scaffold/actions/nested.rb +78 -65
  20. data/lib/active_scaffold/actions/search.rb +13 -10
  21. data/lib/active_scaffold/actions/show.rb +10 -6
  22. data/lib/active_scaffold/actions/subform.rb +1 -2
  23. data/lib/active_scaffold/actions/update.rb +39 -31
  24. data/lib/active_scaffold/active_record_permissions.rb +14 -15
  25. data/lib/active_scaffold/attribute_params.rb +42 -43
  26. data/lib/active_scaffold/bridges.rb +22 -12
  27. data/lib/active_scaffold/bridges/ancestry.rb +1 -1
  28. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +6 -6
  29. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  30. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -13
  31. data/lib/active_scaffold/bridges/calendar_date_select.rb +5 -5
  32. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +17 -20
  33. data/lib/active_scaffold/bridges/cancan.rb +1 -1
  34. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +8 -9
  35. data/lib/active_scaffold/bridges/carrierwave.rb +4 -4
  36. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +9 -8
  37. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +11 -10
  38. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +7 -6
  39. data/lib/active_scaffold/bridges/chosen.rb +1 -1
  40. data/lib/active_scaffold/bridges/chosen/helpers.rb +4 -4
  41. data/lib/active_scaffold/bridges/country_helper.rb +1 -1
  42. data/lib/active_scaffold/bridges/country_helper/country_helper_bridge.rb +259 -260
  43. data/lib/active_scaffold/bridges/date_picker.rb +2 -2
  44. data/lib/active_scaffold/bridges/date_picker/ext.rb +9 -11
  45. data/lib/active_scaffold/bridges/date_picker/helper.rb +61 -67
  46. data/lib/active_scaffold/bridges/dragonfly.rb +4 -4
  47. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +9 -8
  48. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +11 -10
  49. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +6 -5
  50. data/lib/active_scaffold/bridges/file_column.rb +5 -5
  51. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +20 -23
  52. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +20 -23
  53. data/lib/active_scaffold/bridges/file_column/form_ui.rb +13 -14
  54. data/lib/active_scaffold/bridges/file_column/list_ui.rb +7 -8
  55. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +18 -22
  56. data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +5 -4
  57. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +2 -10
  58. data/lib/active_scaffold/bridges/paper_trail.rb +7 -5
  59. data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +4 -3
  60. data/lib/active_scaffold/bridges/paperclip.rb +5 -5
  61. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +11 -10
  62. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +6 -5
  63. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +10 -9
  64. data/lib/active_scaffold/bridges/record_select.rb +1 -1
  65. data/lib/active_scaffold/bridges/record_select/helpers.rb +28 -28
  66. data/lib/active_scaffold/bridges/semantic_attributes.rb +1 -1
  67. data/lib/active_scaffold/bridges/semantic_attributes/column.rb +1 -1
  68. data/lib/active_scaffold/bridges/shared/date_bridge.rb +58 -52
  69. data/lib/active_scaffold/bridges/tiny_mce.rb +2 -2
  70. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -3
  71. data/lib/active_scaffold/config/base.rb +9 -10
  72. data/lib/active_scaffold/config/core.rb +24 -29
  73. data/lib/active_scaffold/config/create.rb +0 -1
  74. data/lib/active_scaffold/config/field_search.rb +8 -10
  75. data/lib/active_scaffold/config/form.rb +5 -5
  76. data/lib/active_scaffold/config/list.rb +21 -20
  77. data/lib/active_scaffold/config/mark.rb +3 -3
  78. data/lib/active_scaffold/config/nested.rb +11 -10
  79. data/lib/active_scaffold/config/search.rb +2 -3
  80. data/lib/active_scaffold/config/show.rb +1 -1
  81. data/lib/active_scaffold/config/update.rb +1 -2
  82. data/lib/active_scaffold/configurable.rb +9 -11
  83. data/lib/active_scaffold/constraints.rb +9 -8
  84. data/lib/active_scaffold/core.rb +72 -84
  85. data/lib/active_scaffold/data_structures/action_columns.rb +26 -25
  86. data/lib/active_scaffold/data_structures/action_link.rb +43 -43
  87. data/lib/active_scaffold/data_structures/action_links.rb +17 -15
  88. data/lib/active_scaffold/data_structures/actions.rb +5 -5
  89. data/lib/active_scaffold/data_structures/bridge.rb +6 -3
  90. data/lib/active_scaffold/data_structures/column.rb +110 -89
  91. data/lib/active_scaffold/data_structures/columns.rb +3 -3
  92. data/lib/active_scaffold/data_structures/error_message.rb +4 -6
  93. data/lib/active_scaffold/data_structures/nested_info.rb +43 -48
  94. data/lib/active_scaffold/data_structures/set.rb +7 -8
  95. data/lib/active_scaffold/data_structures/sorting.rb +38 -33
  96. data/lib/active_scaffold/delayed_setup.rb +5 -6
  97. data/lib/active_scaffold/engine.rb +4 -4
  98. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -4
  99. data/lib/active_scaffold/extensions/action_controller_rescueing.rb +1 -1
  100. data/lib/active_scaffold/extensions/action_view_rendering.rb +5 -6
  101. data/lib/active_scaffold/extensions/left_outer_joins.rb +11 -11
  102. data/lib/active_scaffold/extensions/localize.rb +1 -1
  103. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +1 -1
  104. data/lib/active_scaffold/extensions/paginator_extensions.rb +2 -5
  105. data/lib/active_scaffold/extensions/reverse_associations.rb +13 -13
  106. data/lib/active_scaffold/extensions/routing_mapper.rb +9 -9
  107. data/lib/active_scaffold/extensions/unsaved_associated.rb +9 -9
  108. data/lib/active_scaffold/finder.rb +90 -93
  109. data/lib/active_scaffold/helpers/association_helpers.rb +5 -5
  110. data/lib/active_scaffold/helpers/controller_helpers.rb +22 -19
  111. data/lib/active_scaffold/helpers/form_column_helpers.rb +115 -105
  112. data/lib/active_scaffold/helpers/human_condition_helpers.rb +62 -35
  113. data/lib/active_scaffold/helpers/id_helpers.rb +6 -6
  114. data/lib/active_scaffold/helpers/list_column_helpers.rb +89 -94
  115. data/lib/active_scaffold/helpers/pagination_helpers.rb +9 -9
  116. data/lib/active_scaffold/helpers/search_column_helpers.rb +47 -44
  117. data/lib/active_scaffold/helpers/show_column_helpers.rb +2 -2
  118. data/lib/active_scaffold/helpers/view_helpers.rb +86 -91
  119. data/lib/active_scaffold/marked_model.rb +10 -10
  120. data/lib/active_scaffold/paginator.rb +30 -34
  121. data/lib/active_scaffold/responds_to_parent.rb +27 -28
  122. data/lib/active_scaffold/tableless.rb +20 -15
  123. data/lib/active_scaffold/version.rb +1 -1
  124. data/lib/generators/active_scaffold/active_scaffold_generator.rb +8 -8
  125. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +9 -9
  126. data/shoulda_macros/macros.rb +27 -22
  127. data/test/bridges/bridge_test.rb +38 -29
  128. data/test/bridges/date_picker_test.rb +1 -1
  129. data/test/bridges/paper_trail_test.rb +17 -0
  130. data/test/bridges/paperclip_test.rb +3 -2
  131. data/test/bridges/tiny_mce_test.rb +5 -2
  132. data/test/company.rb +25 -30
  133. data/test/config/base_test.rb +1 -1
  134. data/test/config/core_test.rb +9 -9
  135. data/test/config/create_test.rb +14 -8
  136. data/test/config/delete_test.rb +4 -4
  137. data/test/config/field_search_test.rb +6 -6
  138. data/test/config/list_test.rb +16 -16
  139. data/test/config/nested_test.rb +4 -4
  140. data/test/config/search_test.rb +8 -8
  141. data/test/config/show_test.rb +6 -6
  142. data/test/config/subform_test.rb +1 -1
  143. data/test/config/update_test.rb +5 -5
  144. data/test/const_mocker.rb +4 -4
  145. data/test/data_structures/action_columns_test.rb +4 -5
  146. data/test/data_structures/action_link_test.rb +1 -0
  147. data/test/data_structures/action_links_test.rb +5 -5
  148. data/test/data_structures/column_test.rb +9 -9
  149. data/test/data_structures/columns_test.rb +2 -2
  150. data/test/data_structures/error_message_test.rb +4 -5
  151. data/test/data_structures/set_test.rb +1 -2
  152. data/test/data_structures/sorting_test.rb +10 -10
  153. data/test/data_structures/validation_reflection_test.rb +8 -0
  154. data/test/extensions/routing_mapper_test.rb +2 -2
  155. data/test/helpers/list_column_helpers_test.rb +3 -2
  156. data/test/helpers/pagination_helpers_test.rb +5 -4
  157. data/test/helpers/search_column_helpers_test.rb +1 -1
  158. data/test/misc/active_record_permissions_test.rb +63 -50
  159. data/test/misc/attribute_params_test.rb +28 -26
  160. data/test/misc/calculation_test.rb +10 -3
  161. data/test/misc/configurable_test.rb +12 -13
  162. data/test/misc/constraints_test.rb +6 -6
  163. data/test/misc/convert_numbers_format_test.rb +7 -6
  164. data/test/misc/finder_test.rb +17 -12
  165. data/test/misc/lang_test.rb +3 -4
  166. data/test/misc/tableless_test.rb +2 -3
  167. data/test/mock_app/app/controllers/addresses_controller.rb +1 -1
  168. data/test/mock_app/app/controllers/buildings_controller.rb +1 -1
  169. data/test/mock_app/app/controllers/cars_controller.rb +1 -1
  170. data/test/mock_app/app/controllers/contacts_controller.rb +1 -1
  171. data/test/mock_app/app/controllers/people_controller.rb +1 -1
  172. data/test/mock_app/app/models/file_model.rb +2 -2
  173. data/test/mock_app/app/models/person.rb +1 -1
  174. data/test/mock_app/config/application.rb +3 -3
  175. data/test/mock_app/config/boot.rb +1 -1
  176. data/test/mock_app/config/environment.rb +1 -0
  177. data/test/mock_app/config/environments/development.rb +0 -1
  178. data/test/mock_app/config/environments/production.rb +1 -1
  179. data/test/mock_app/db/schema.rb +14 -15
  180. data/test/model_stub.rb +13 -16
  181. data/test/run_all.rb +5 -7
  182. data/test/test_helper.rb +12 -9
  183. metadata +19 -3
@@ -10,10 +10,10 @@ module ActiveScaffold::DataStructures
10
10
  # Whether to enable inplace editing for this column. Currently works for text columns, in the List.
11
11
  attr_reader :inplace_edit
12
12
  def inplace_edit=(value)
13
- self.clear_link if value
13
+ clear_link if value
14
14
  @inplace_edit = value
15
15
  end
16
-
16
+
17
17
  attr_accessor :inplace_edit_update
18
18
 
19
19
  # Whether this column set is collapsed by default in contexts where collapsing is supported
@@ -21,10 +21,10 @@ module ActiveScaffold::DataStructures
21
21
 
22
22
  # Whether to enable add_existing for this column
23
23
  attr_accessor :allow_add_existing
24
-
24
+
25
25
  # What columns load from main table
26
26
  attr_accessor :select_columns
27
-
27
+
28
28
  # Any extra parameters this particular column uses. This is for create/update purposes.
29
29
  def params
30
30
  # lazy initialize
@@ -63,9 +63,9 @@ module ActiveScaffold::DataStructures
63
63
  def required?
64
64
  @required
65
65
  end
66
-
66
+
67
67
  attr_reader :update_columns
68
-
68
+
69
69
  # update dependent columns after value change in form
70
70
  # update_columns = :name
71
71
  # update_columns = [:name, :age]
@@ -92,7 +92,7 @@ module ActiveScaffold::DataStructures
92
92
  end
93
93
 
94
94
  def sort
95
- self.initialize_sort if @sort === true
95
+ initialize_sort if @sort == true
96
96
  @sort
97
97
  end
98
98
 
@@ -112,9 +112,7 @@ module ActiveScaffold::DataStructures
112
112
  self.list_method = nil if @list_ui.nil? && value != @form_ui
113
113
  @form_ui = value
114
114
  end
115
- def form_ui
116
- @form_ui
117
- end
115
+ attr_reader :form_ui
118
116
 
119
117
  def list_ui=(value)
120
118
  self.list_method = nil if value != @list_ui
@@ -141,13 +139,13 @@ module ActiveScaffold::DataStructures
141
139
  @link
142
140
  end
143
141
 
144
- # associate an action_link with this column
142
+ # associate an action_link with this column
145
143
  def set_link(action, options = {})
146
144
  if action.is_a?(ActiveScaffold::DataStructures::ActionLink) || (action.is_a? Proc)
147
145
  @link = action
148
146
  else
149
- options[:label] ||= self.label
150
- options[:position] ||= :after unless options.has_key?(:position)
147
+ options[:label] ||= label
148
+ options[:position] ||= :after unless options.key?(:position)
151
149
  options[:type] ||= :member
152
150
  @link = ActiveScaffold::DataStructures::ActionLink.new(action, options)
153
151
  end
@@ -169,14 +167,14 @@ module ActiveScaffold::DataStructures
169
167
 
170
168
  # get whether to run a calculation on this column
171
169
  def calculation?
172
- !(@calculate == false or @calculate.nil?)
170
+ !(@calculate == false || @calculate.nil?)
173
171
  end
174
172
 
175
173
  # a collection of associations to pre-load when finding the records on a page
176
174
  attr_reader :includes
177
175
  def includes=(value)
178
176
  @includes = case value
179
- when Array then value
177
+ when Array then value
180
178
  else value ? [value] : value # not convert nil to [nil]
181
179
  end
182
180
  end
@@ -188,7 +186,7 @@ module ActiveScaffold::DataStructures
188
186
 
189
187
  def search_joins=(value)
190
188
  @search_joins = case value
191
- when Array then value
189
+ when Array then value
192
190
  else [value] # automatically convert to an array
193
191
  end
194
192
  end
@@ -201,18 +199,21 @@ module ActiveScaffold::DataStructures
201
199
  # search = "CONCAT(a, b)" define your own sql for searching. this should be the "left-side" of a WHERE condition. the operator and value will be supplied by ActiveScaffold.
202
200
  # search = [:a, :b] searches in both fields
203
201
  def search_sql=(value)
204
- @search_sql = if value
205
- (value == true || value.is_a?(Proc)) ? value : Array(value)
206
- else
207
- value
208
- end
202
+ @search_sql =
203
+ if value
204
+ (value == true || value.is_a?(Proc)) ? value : Array(value)
205
+ else
206
+ value
207
+ end
209
208
  end
209
+
210
210
  def search_sql
211
- self.initialize_search_sql if @search_sql === true
211
+ initialize_search_sql if @search_sql == true
212
212
  @search_sql
213
213
  end
214
+
214
215
  def searchable?
215
- !!search_sql
216
+ search_sql.present?
216
217
  end
217
218
 
218
219
  # to modify the default order of columns
@@ -236,17 +237,16 @@ module ActiveScaffold::DataStructures
236
237
  @@show_blank_record = true
237
238
  attr_writer :show_blank_record
238
239
  def show_blank_record?(associated)
239
- if @show_blank_record
240
- return false unless self.association.klass.authorized_for?(:crud_type => :create) and not self.association.options[:readonly]
241
- self.plural_association? or (self.singular_association? and associated.blank?)
242
- end
240
+ return false unless @show_blank_record
241
+ return false unless association.klass.authorized_for?(:crud_type => :create) && !association.options[:readonly]
242
+ self.plural_association? || (self.singular_association? && associated.blank?)
243
243
  end
244
244
 
245
245
  # methods for automatic links in singular association columns
246
246
  cattr_accessor :actions_for_association_links
247
247
  @@actions_for_association_links = [:new, :edit, :show]
248
248
  attr_accessor :actions_for_association_links
249
-
249
+
250
250
  cattr_accessor :association_form_ui
251
251
  @@association_form_ui = nil
252
252
 
@@ -260,24 +260,27 @@ module ActiveScaffold::DataStructures
260
260
  # the association from the ActiveRecord class
261
261
  attr_reader :association
262
262
  def singular_association?
263
- self.association and !self.association.collection?
263
+ association && !association.collection?
264
264
  end
265
+
265
266
  def plural_association?
266
- self.association and self.association.collection?
267
+ association && association.collection?
267
268
  end
269
+
268
270
  def through_association?
269
- self.association and self.association.options[:through]
271
+ association && association.options[:through]
270
272
  end
273
+
271
274
  def polymorphic_association?
272
- self.association and self.association.options[:polymorphic]
275
+ association && association.options[:polymorphic]
273
276
  end
277
+
274
278
  def readonly_association?
275
- if self.association
276
- if self.association.options.has_key? :readonly
277
- self.association.options[:readonly]
278
- else
279
- self.through_association?
280
- end
279
+ return false unless association
280
+ if association.options.key? :readonly
281
+ association.options[:readonly]
282
+ else
283
+ self.through_association?
281
284
  end
282
285
  end
283
286
 
@@ -285,7 +288,7 @@ module ActiveScaffold::DataStructures
285
288
  def virtual?
286
289
  column.nil? && association.nil?
287
290
  end
288
-
291
+
289
292
  attr_writer :number
290
293
  def number?
291
294
  @number
@@ -298,11 +301,11 @@ module ActiveScaffold::DataStructures
298
301
  # this is so that array.delete and array.include?, etc., will work by column name
299
302
  def ==(other) #:nodoc:
300
303
  # another column
301
- if other.respond_to? :name and other.class == self.class
302
- self.name == other.name.to_sym
304
+ if other.respond_to?(:name) && other.class == self.class
305
+ name == other.name.to_sym
303
306
  # a string or symbol
304
307
  elsif other.respond_to? :to_sym
305
- self.name == other.to_sym rescue false # catch "interning empty string"
308
+ name == other.to_sym rescue false # catch "interning empty string"
306
309
  # unknown
307
310
  else
308
311
  self.eql? other
@@ -323,25 +326,8 @@ module ActiveScaffold::DataStructures
323
326
  @show_blank_record = self.class.show_blank_record
324
327
  @send_form_on_update_column = self.class.send_form_on_update_column
325
328
  @actions_for_association_links = self.class.actions_for_association_links.clone if @association
326
- @select_columns = if @association.nil? && @column
327
- [field]
328
- elsif polymorphic_association?
329
- [field, quoted_field(@active_record_class.connection.quote_column_name(@association.foreign_type))]
330
- elsif @association
331
- if self.association.belongs_to?
332
- [field]
333
- else
334
- columns = []
335
- if active_record_class.columns_hash[count_column = "#{@association.name}_count"]
336
- columns << quoted_field(@active_record_class.connection.quote_column_name(count_column))
337
- end
338
- if @association.through_reflection.try(:belongs_to?)
339
- columns << quoted_field(@active_record_class.connection.quote_column_name(@association.through_reflection.foreign_key))
340
- end
341
- columns
342
- end
343
- end
344
-
329
+ @select_columns = default_select_columns
330
+
345
331
  @text = @column.nil? || [:string, :text].include?(@column.type)
346
332
  if @column
347
333
  @form_ui = case @column.type
@@ -356,23 +342,21 @@ module ActiveScaffold::DataStructures
356
342
  end
357
343
  @allow_add_existing = true
358
344
  @form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
359
-
345
+
346
+ if association && !polymorphic_association?
347
+ self.includes = [association.name]
348
+ self.search_joins = includes.clone
349
+ end
350
+
360
351
  # default all the configurable variables
361
352
  self.css_class = ''
362
353
  self.required = active_record_class.validators_on(self.name).any? do |val|
363
- !val.options[:if] && !val.options[:unless] && (ActiveModel::Validations::PresenceValidator === val ||
364
- (ActiveModel::Validations::InclusionValidator === val && !val.options[:allow_nil] && !val.options[:allow_blank] && !(@form_ui == :checkbox && [[true, false], [false, true]].include?(val.send(:delimiter))))
365
- )
354
+ validator_force_required?(val)
366
355
  end
367
356
  self.sort = true
368
357
  self.search_sql = true
369
-
370
- @weight = estimate_weight
371
358
 
372
- if association && !polymorphic_association?
373
- self.includes = [association.name]
374
- self.search_joins = self.includes.clone
375
- end
359
+ @weight = estimate_weight
376
360
  end
377
361
 
378
362
  # just the field (not table.field)
@@ -381,16 +365,16 @@ module ActiveScaffold::DataStructures
381
365
  @field_name ||= column ? @active_record_class.connection.quote_column_name(column.name) : association.foreign_key
382
366
  end
383
367
 
384
- def <=>(other_column)
385
- order_weight = self.weight <=> other_column.weight
386
- order_weight != 0 ? order_weight : self.name.to_s <=> other_column.name.to_s
368
+ def <=>(other)
369
+ order_weight = weight <=> other.weight
370
+ order_weight != 0 ? order_weight : name.to_s <=> other.name.to_s
387
371
  end
388
372
 
389
373
  def number_to_native(value)
390
374
  return value if value.blank? || !value.is_a?(String)
391
375
  native = '.' # native ruby separator
392
376
  format = {:separator => '', :delimiter => ''}.merge! I18n.t('number.format', :default => {})
393
- specific = case self.options[:format]
377
+ specific = case options[:format]
394
378
  when :currency
395
379
  I18n.t('number.currency.format', :default => nil)
396
380
  when :size
@@ -399,10 +383,10 @@ module ActiveScaffold::DataStructures
399
383
  I18n.t('number.percentage.format', :default => nil)
400
384
  end
401
385
  format.merge! specific unless specific.nil?
402
- unless format[:separator].blank? || !value.include?(format[:separator]) && value.include?(native) && (format[:delimiter] != native || value !~ /\.\d{3}$/)
403
- value.gsub(/[^0-9\-#{format[:separator]}]/, '').gsub(format[:separator], native)
404
- else
386
+ if format[:separator].blank? || !value.include?(format[:separator]) && value.include?(native) && (format[:delimiter] != native || value !~ /\.\d{3}$/)
405
387
  value
388
+ else
389
+ value.gsub(/[^0-9\-#{format[:separator]}]/, '').gsub(format[:separator], native)
406
390
  end
407
391
  end
408
392
 
@@ -419,6 +403,42 @@ module ActiveScaffold::DataStructures
419
403
 
420
404
  protected
421
405
 
406
+ def validator_force_required?(val)
407
+ return false if val.options[:if] || val.options[:unless]
408
+ case val
409
+ when ActiveModel::Validations::PresenceValidator
410
+ true
411
+ when ActiveModel::Validations::InclusionValidator
412
+ !val.options[:allow_nil] && !val.options[:allow_blank] &&
413
+ !inclusion_validator_for_checkbox?(val)
414
+ end
415
+ end
416
+
417
+ def inclusion_validator_for_checkbox?(val)
418
+ @form_ui == :checkbox && [[true, false], [false, true]].include?(val.options[:with] || val.options[:within])
419
+ end
420
+
421
+ def default_select_columns
422
+ if association.nil? && column
423
+ [field]
424
+ elsif polymorphic_association?
425
+ [field, quoted_field(@active_record_class.connection.quote_column_name(association.foreign_type))]
426
+ elsif association
427
+ if association.belongs_to?
428
+ [field]
429
+ else
430
+ columns = []
431
+ if active_record_class.columns_hash[count_column = "#{association.name}_count"]
432
+ columns << quoted_field(@active_record_class.connection.quote_column_name(count_column))
433
+ end
434
+ if association.through_reflection.try(:belongs_to?)
435
+ columns << quoted_field(@active_record_class.connection.quote_column_name(association.through_reflection.foreign_key))
436
+ end
437
+ columns
438
+ end
439
+ end
440
+ end
441
+
422
442
  def quoted_field(name)
423
443
  [@active_record_class.quoted_table_name, name].join('.')
424
444
  end
@@ -429,34 +449,35 @@ module ActiveScaffold::DataStructures
429
449
  self.sort = false
430
450
  else
431
451
  if column && !@tableless
432
- self.sort = {:sql => self.field}
452
+ self.sort = {:sql => field}
433
453
  else
434
454
  self.sort = false
435
455
  end
436
456
  end
437
457
  end
438
-
458
+
439
459
  def initialize_search_sql
440
- self.search_sql = unless self.virtual?
441
- if association.nil?
442
- self.field.to_s unless @tableless
443
- elsif !self.polymorphic_association?
444
- [association.klass.quoted_table_name, association.klass.quoted_primary_key].join('.') unless association.klass < ActiveScaffold::Tableless
460
+ self.search_sql =
461
+ unless self.virtual?
462
+ if association.nil?
463
+ field.to_s unless @tableless
464
+ elsif !self.polymorphic_association?
465
+ [association.klass.quoted_table_name, association.klass.quoted_primary_key].join('.') unless association.klass < ActiveScaffold::Tableless
466
+ end
445
467
  end
446
- end
447
468
  end
448
469
 
449
470
  # the table name from the ActiveRecord class
450
471
  attr_reader :table
451
-
472
+
452
473
  def estimate_weight
453
474
  if singular_association?
454
475
  400
455
476
  elsif plural_association?
456
477
  500
457
- elsif [:created_at, :updated_at].include?(self.name)
478
+ elsif [:created_at, :updated_at].include?(name)
458
479
  600
459
- elsif [:name, :label, :title].include?(self.name)
480
+ elsif [:name, :label, :title].include?(name)
460
481
  100
461
482
  elsif required?
462
483
  200
@@ -24,14 +24,14 @@ module ActiveScaffold::DataStructures
24
24
  @_inheritable = []
25
25
  @set = []
26
26
 
27
- self.add *args
27
+ add *args
28
28
  end
29
29
 
30
30
  # the way to add columns to the set. this is primarily useful for virtual columns.
31
31
  # note that this also makes columns inheritable
32
32
  def add(*args)
33
33
  args.flatten! # allow [] as a param
34
- args = args.collect{ |a| a.to_sym }
34
+ args = args.collect(&:to_sym)
35
35
 
36
36
  # make the columns inheritable
37
37
  @_inheritable.concat(args)
@@ -59,7 +59,7 @@ module ActiveScaffold::DataStructures
59
59
  alias_method :[], :find_by_name
60
60
 
61
61
  def each
62
- @set.each {|i| yield i }
62
+ @set.each { |i| yield i }
63
63
  end
64
64
 
65
65
  def _inheritable
@@ -6,19 +6,17 @@ module ActiveScaffold::DataStructures
6
6
  end
7
7
 
8
8
  def public_attributes
9
- { :error => @error }
9
+ {:error => @error}
10
10
  end
11
11
 
12
12
  def to_xml
13
- public_attributes.to_xml(:root => "errors")
13
+ public_attributes.to_xml(:root => 'errors')
14
14
  end
15
15
 
16
- def to_yaml
17
- public_attributes.to_yaml
18
- end
16
+ delegate :to_yaml, :to => :public_attributes
19
17
 
20
18
  def to_s
21
19
  @error
22
20
  end
23
21
  end
24
- end
22
+ end
@@ -1,37 +1,34 @@
1
1
  module ActiveScaffold::DataStructures
2
2
  class NestedInfo
3
3
  def self.get(model, params)
4
- nested_info = {}
5
- begin
6
- unless params[:association].nil?
7
- ActiveScaffold::DataStructures::NestedInfoAssociation.new(model, params)
8
- else
9
- ActiveScaffold::DataStructures::NestedInfoScope.new(model, params)
10
- end
11
- rescue ActiveScaffold::ControllerNotFound
12
- nil
4
+ if params[:association].nil?
5
+ ActiveScaffold::DataStructures::NestedInfoScope.new(model, params)
6
+ else
7
+ ActiveScaffold::DataStructures::NestedInfoAssociation.new(model, params)
13
8
  end
9
+ rescue ActiveScaffold::ControllerNotFound
10
+ nil
14
11
  end
15
-
12
+
16
13
  attr_accessor :association, :child_association, :parent_model, :parent_scaffold, :parent_id, :param_name, :constrained_fields, :scope
17
-
14
+
18
15
  def initialize(model, params)
19
16
  @parent_scaffold = "#{params[:parent_scaffold].to_s.camelize}Controller".constantize
20
17
  @parent_model = @parent_scaffold.active_scaffold_config.model
21
18
  end
22
-
19
+
23
20
  def to_params
24
21
  {:parent_scaffold => parent_scaffold.controller_path}
25
22
  end
26
-
23
+
27
24
  def new_instance?
28
25
  result = @new_instance.nil?
29
26
  @new_instance = false
30
27
  result
31
28
  end
32
-
29
+
33
30
  def habtm?
34
- false
31
+ false
35
32
  end
36
33
 
37
34
  def has_many?
@@ -61,7 +58,7 @@ module ActiveScaffold::DataStructures
61
58
  def through_association?
62
59
  false
63
60
  end
64
-
61
+
65
62
  def readonly?
66
63
  false
67
64
  end
@@ -70,7 +67,7 @@ module ActiveScaffold::DataStructures
70
67
  false
71
68
  end
72
69
  end
73
-
70
+
74
71
  class NestedInfoAssociation < NestedInfo
75
72
  def initialize(model, params)
76
73
  super
@@ -79,88 +76,86 @@ module ActiveScaffold::DataStructures
79
76
  @parent_id = params[@param_name]
80
77
  iterate_model_associations(model)
81
78
  end
82
-
83
- def name
84
- self.association.name
85
- end
86
-
79
+
80
+ delegate :name, :to => :association
81
+
87
82
  def has_many?
88
- association.macro == :has_many
83
+ association.macro == :has_many
89
84
  end
90
-
85
+
91
86
  def habtm?
92
- association.macro == :has_and_belongs_to_many
93
- end
94
-
95
- def belongs_to?
96
- association.belongs_to?
87
+ association.macro == :has_and_belongs_to_many
97
88
  end
98
89
 
90
+ delegate :belongs_to?, :to => :association
91
+
99
92
  def has_one?
100
93
  association.macro == :has_one
101
94
  end
102
-
95
+
103
96
  # A through association with has_one or has_many as source association
104
- # create cannot be called in such through association, unless create columns include through reflection of reverse association
97
+ # create cannot be called in nested through associations, and not-nested through associations
98
+ # unless create columns include through reflection of reverse association
105
99
  # e.g. customer -> networks -> firewall, reverse is firewall -> network -> customer,
106
100
  # firewall can be created if create columns include network
107
101
  def readonly_through_association?(columns)
108
- through_association? && association.source_reflection.macro != :belongs_to && (
102
+ return false unless through_association?
103
+ return true if association.through_reflection.options[:through]
104
+ association.source_reflection.macro != :belongs_to && (
109
105
  !child_association || !columns.include?(child_association.through_reflection.name)
110
106
  )
111
107
  end
112
-
108
+
113
109
  def through_association?
114
110
  association.options[:through]
115
111
  end
116
-
112
+
117
113
  def readonly?
118
114
  association.options[:readonly]
119
115
  end
120
116
 
121
117
  def sorted?
122
- association.options.has_key? :order
118
+ association.options.key? :order
123
119
  end
124
120
 
125
121
  def default_sorting
126
- if association.options[:order] # TODO remove when rails 3 compatibility is removed
122
+ if association.options[:order] # TODO: remove when rails 3 compatibility is removed
127
123
  association.options[:order]
128
124
  elsif association.respond_to?(:scope) # rails 4
129
125
  association.klass.class_eval(&association.scope).values[:order] if association.scope.is_a? Proc
130
126
  end
131
127
  end
132
-
128
+
133
129
  def to_params
134
130
  super.merge(:association => @association.name, :assoc_id => parent_id)
135
131
  end
136
-
132
+
137
133
  protected
138
-
134
+
139
135
  def iterate_model_associations(model)
140
136
  @constrained_fields = []
141
137
  constrained_fields << association.foreign_key.to_sym unless association.belongs_to?
142
- if reverse = association.reverse(model)
143
- @child_association = model.reflect_on_association(reverse)
144
- constrained_fields << @child_association.name unless @child_association == association
145
- end
138
+ return if (reverse = association.reverse(model)).nil?
139
+ @child_association = model.reflect_on_association(reverse)
140
+ constrained_fields << @child_association.name unless @child_association == association
146
141
  end
147
142
  end
148
-
143
+
149
144
  class NestedInfoScope < NestedInfo
150
145
  def initialize(model, params)
151
146
  super
152
147
  @scope = params[:named_scope].to_sym
153
148
  @param_name = parent_model.name.foreign_key.to_sym
154
149
  @parent_id = params[@param_name]
155
- @constrained_fields = []
150
+ @constrained_fields = []
156
151
  end
157
-
152
+
158
153
  def to_params
159
154
  super.merge(:named_scope => @scope)
160
155
  end
161
-
156
+
162
157
  def name
163
- self.scope
158
+ scope
164
159
  end
165
160
  end
166
161
  end