active_scaffold 3.5.2 → 3.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +66 -0
  3. data/README.md +17 -7
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +63 -6
  6. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  7. data/app/assets/stylesheets/active_scaffold_layout.css +52 -29
  8. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -2
  9. data/app/views/active_scaffold_overrides/_form.html.erb +1 -1
  10. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  11. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +6 -6
  12. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  13. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
  14. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  16. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  17. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  18. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  19. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  20. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  21. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  22. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  23. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  24. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  25. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  26. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  27. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  28. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  29. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  30. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  31. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  32. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  33. data/config/locales/de.yml +2 -1
  34. data/config/locales/en.yml +1 -0
  35. data/config/locales/es.yml +1 -0
  36. data/config/locales/fr.yml +2 -1
  37. data/config/locales/hu.yml +1 -0
  38. data/config/locales/ja.yml +1 -0
  39. data/config/locales/ru.yml +1 -0
  40. data/lib/active_scaffold.rb +19 -16
  41. data/lib/active_scaffold/actions/common_search.rb +11 -8
  42. data/lib/active_scaffold/actions/core.rb +89 -71
  43. data/lib/active_scaffold/actions/create.rb +28 -28
  44. data/lib/active_scaffold/actions/delete.rb +3 -3
  45. data/lib/active_scaffold/actions/field_search.rb +53 -43
  46. data/lib/active_scaffold/actions/list.rb +111 -27
  47. data/lib/active_scaffold/actions/nested.rb +65 -48
  48. data/lib/active_scaffold/actions/search.rb +1 -1
  49. data/lib/active_scaffold/actions/show.rb +4 -4
  50. data/lib/active_scaffold/actions/subform.rb +12 -17
  51. data/lib/active_scaffold/actions/update.rb +96 -77
  52. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  53. data/lib/active_scaffold/attribute_params.rb +104 -86
  54. data/lib/active_scaffold/bridges.rb +8 -8
  55. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  56. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +33 -0
  57. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  58. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  59. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  60. data/lib/active_scaffold/bridges/bitfields.rb +1 -0
  61. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  62. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  63. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -12
  64. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  65. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  66. data/lib/active_scaffold/bridges/chosen/helpers.rb +11 -9
  67. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  68. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  69. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  70. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  71. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  72. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  73. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  74. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  75. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  76. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  77. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  78. data/lib/active_scaffold/bridges/record_select/helpers.rb +12 -16
  79. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  80. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  81. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  82. data/lib/active_scaffold/config/base.rb +133 -41
  83. data/lib/active_scaffold/config/core.rb +146 -18
  84. data/lib/active_scaffold/config/delete.rb +14 -1
  85. data/lib/active_scaffold/config/field_search.rb +7 -1
  86. data/lib/active_scaffold/config/form.rb +10 -1
  87. data/lib/active_scaffold/config/list.rb +39 -13
  88. data/lib/active_scaffold/config/mark.rb +4 -2
  89. data/lib/active_scaffold/config/nested.rb +16 -17
  90. data/lib/active_scaffold/config/search.rb +9 -0
  91. data/lib/active_scaffold/config/show.rb +4 -0
  92. data/lib/active_scaffold/config/update.rb +4 -0
  93. data/lib/active_scaffold/configurable.rb +14 -7
  94. data/lib/active_scaffold/constraints.rb +22 -20
  95. data/lib/active_scaffold/core.rb +68 -29
  96. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  97. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  98. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  99. data/lib/active_scaffold/data_structures/association/abstract.rb +41 -15
  100. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  101. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  102. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  103. data/lib/active_scaffold/data_structures/column.rb +75 -66
  104. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  105. data/lib/active_scaffold/data_structures/nested_info.rb +21 -19
  106. data/lib/active_scaffold/data_structures/set.rb +8 -0
  107. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  108. data/lib/active_scaffold/delayed_setup.rb +16 -5
  109. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  110. data/lib/active_scaffold/extensions/action_view_rendering.rb +34 -14
  111. data/lib/active_scaffold/extensions/cow_proxy.rb +91 -0
  112. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  113. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  114. data/lib/active_scaffold/extensions/localize.rb +3 -1
  115. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  116. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  117. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  118. data/lib/active_scaffold/finder.rb +104 -73
  119. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  120. data/lib/active_scaffold/helpers/association_helpers.rb +21 -19
  121. data/lib/active_scaffold/helpers/controller_helpers.rb +23 -10
  122. data/lib/active_scaffold/helpers/form_column_helpers.rb +157 -121
  123. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  124. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  125. data/lib/active_scaffold/helpers/list_column_helpers.rb +82 -53
  126. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  127. data/lib/active_scaffold/helpers/search_column_helpers.rb +29 -34
  128. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  129. data/lib/active_scaffold/helpers/view_helpers.rb +38 -35
  130. data/lib/active_scaffold/marked_model.rb +2 -2
  131. data/lib/active_scaffold/orm_checks.rb +3 -7
  132. data/lib/active_scaffold/paginator.rb +7 -7
  133. data/lib/active_scaffold/registry.rb +33 -0
  134. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  135. data/lib/active_scaffold/tableless.rb +67 -65
  136. data/lib/active_scaffold/version.rb +2 -2
  137. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  138. data/lib/generators/active_scaffold/install_generator.rb +1 -1
  139. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  140. data/shoulda_macros/macros.rb +3 -1
  141. data/test/bridges/date_picker_test.rb +1 -2
  142. data/test/bridges/paperclip_test.rb +6 -6
  143. data/test/class_with_finder.rb +2 -2
  144. data/test/company.rb +4 -4
  145. data/test/config/create_test.rb +4 -2
  146. data/test/config/nested_test.rb +1 -1
  147. data/test/config/show_test.rb +1 -1
  148. data/test/config/update_test.rb +7 -6
  149. data/test/data_structures/action_columns_test.rb +2 -2
  150. data/test/data_structures/action_links_test.rb +1 -1
  151. data/test/data_structures/column_test.rb +3 -6
  152. data/test/data_structures/columns_test.rb +2 -2
  153. data/test/data_structures/sorting_test.rb +7 -0
  154. data/test/extensions/active_record_test.rb +4 -4
  155. data/test/extensions/routing_mapper_test.rb +2 -2
  156. data/test/helpers/list_column_helpers_test.rb +3 -1
  157. data/test/misc/active_record_permissions_test.rb +3 -11
  158. data/test/misc/attribute_params_test.rb +12 -8
  159. data/test/misc/calculation_test.rb +1 -1
  160. data/test/misc/configurable_test.rb +10 -10
  161. data/test/misc/constraints_test.rb +2 -2
  162. data/test/misc/convert_numbers_format_test.rb +7 -3
  163. data/test/misc/lang_test.rb +1 -1
  164. data/test/misc/parse_datetime_test.rb +3 -4
  165. data/test/misc/tableless_test.rb +6 -0
  166. data/test/mock_app/Rakefile +1 -1
  167. data/test/mock_app/app/assets/config/manifest.js +0 -0
  168. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  169. data/test/mock_app/app/controllers/people_controller.rb +3 -1
  170. data/test/mock_app/config/application.rb +2 -1
  171. data/test/mock_app/config/boot.rb +1 -1
  172. data/test/mock_app/config/environment.rb +2 -2
  173. data/test/mock_app/config/routes.rb +4 -1
  174. data/test/mock_app/db/schema.rb +2 -0
  175. data/test/performance/list_cars_performance_test.rb +34 -0
  176. data/test/performance/list_people_performance_test.rb +31 -0
  177. data/test/performance_test_help.rb +3 -0
  178. data/test/test_helper.rb +10 -2
  179. metadata +56 -15
  180. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  181. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -7
@@ -1,13 +1,12 @@
1
1
  module ActiveScaffold::Actions
2
2
  module CommonSearch
3
3
  def self.included(base)
4
- unless base < InstanceMethods
5
- base.send :include, InstanceMethods
6
- base.before_action :search_authorized_filter, :only => :show_search
7
- base.before_action :store_search_params_into_session, :only => [:index]
8
- base.before_action :do_search, :only => [:index]
9
- base.helper_method :search_params
10
- end
4
+ return if base < InstanceMethods
5
+ base.send :include, InstanceMethods
6
+ base.before_action :search_authorized_filter, :only => :show_search
7
+ base.before_action :store_search_params_into_session, :only => [:index]
8
+ base.before_action :do_search, :only => [:index]
9
+ base.helper_method :search_params
11
10
  end
12
11
 
13
12
  module InstanceMethods
@@ -34,7 +33,11 @@ module ActiveScaffold::Actions
34
33
 
35
34
  def store_search_params_into_session
36
35
  if active_scaffold_config.store_user_settings
37
- active_scaffold_session_storage['search'] = permitted_search_params if params[:search]
36
+ if params[:search].present?
37
+ active_scaffold_session_storage['search'] = permitted_search_params
38
+ elsif params.key? :search
39
+ active_scaffold_session_storage.delete 'search'
40
+ end
38
41
  else
39
42
  @search_params = permitted_search_params
40
43
  end
@@ -3,13 +3,13 @@ module ActiveScaffold::Actions
3
3
  def self.included(base)
4
4
  base.class_eval do
5
5
  before_action :set_vary_accept_header
6
- before_action :handle_user_settings
7
6
  before_action :check_input_device
8
7
  before_action :register_constraints_with_action_columns, :unless => :nested?
9
8
  after_action :clear_flashes
10
- after_action :clear_storage
9
+ around_action :clear_storage
11
10
  rescue_from ActiveScaffold::RecordNotAllowed, ActiveScaffold::ActionNotAllowed, :with => :deny_access
12
11
  end
12
+ base.helper_method :active_scaffold_config
13
13
  base.helper_method :successful?
14
14
  base.helper_method :nested?
15
15
  base.helper_method :grouped_search?
@@ -72,7 +72,7 @@ module ActiveScaffold::Actions
72
72
  else
73
73
  updated_record_with_column(@column, params.delete(:value), @scope)
74
74
  end
75
- set_parent(@record) if main_form_controller && @scope
75
+ setup_parent(@record) if main_form_controller && @scope
76
76
  after_render_field(@record, @column)
77
77
  end
78
78
 
@@ -104,16 +104,16 @@ module ActiveScaffold::Actions
104
104
  end
105
105
 
106
106
  def subform_child_association
107
- params[:child_association].presence || (@scope.split(']').first.sub(/^\[/, '').presence if @scope)
107
+ params[:child_association].presence || @scope&.split(']')&.first&.sub(/^\[/, '').presence
108
108
  end
109
109
 
110
110
  def parent_controller_name
111
111
  "#{params[:parent_controller].camelize}Controller"
112
112
  end
113
113
 
114
- def set_parent(record)
114
+ def setup_parent(record)
115
115
  cfg = main_form_controller.active_scaffold_config
116
- association = cfg.columns[subform_child_association].try(:association).try(:reverse_association)
116
+ association = cfg.columns[subform_child_association]&.association&.reverse_association
117
117
  return if association.nil?
118
118
 
119
119
  parent_model = cfg.model
@@ -129,8 +129,8 @@ module ActiveScaffold::Actions
129
129
  end
130
130
 
131
131
  if params[:nested] # form in nested scaffold, set nested parent_record to parent
132
- nested = ActiveScaffold::DataStructures::NestedInfo.get(parent.class, params.delete(:nested))
133
- if nested.child_association
132
+ nested = ActiveScaffold::DataStructures::NestedInfo.get(parent.class, params[:nested])
133
+ if nested&.child_association && !nested.child_association.polymorphic?
134
134
  apply_constraints_to_record(parent, constraints: {nested.child_association.name => nested.parent_id})
135
135
  end
136
136
  end
@@ -179,14 +179,12 @@ module ActiveScaffold::Actions
179
179
  # ex: accepts? :html, :xml
180
180
  def accepts?(*types)
181
181
  request.accepts.compact.each do |priority|
182
- if priority == Mime::ALL
183
- # Because IE always sends */* in the accepts header and we assume
184
- # that if you really wanted XML or something else you would say so
185
- # explicitly, we will assume */* to only ask for :html
186
- return types.include?(:html)
187
- elsif types.include?(priority.to_sym)
188
- return true
189
- end
182
+ # Because IE always sends */* in the accepts header and we assume
183
+ # that if you really wanted XML or something else you would say so
184
+ # explicitly, we will assume */* to only ask for :html
185
+ return types.include?(:html) if priority == Mime::ALL
186
+
187
+ return true if types.include?(priority.to_sym)
190
188
  end
191
189
  false
192
190
  end
@@ -204,6 +202,18 @@ module ActiveScaffold::Actions
204
202
  @response_object ||= successful? ? (@record || @records) : @record.errors
205
203
  end
206
204
 
205
+ def response_to_api(format, columns_names, options = {})
206
+ render(
207
+ options.reverse_merge(
208
+ format => response_object,
209
+ :only => columns_names + [active_scaffold_config.model.primary_key],
210
+ :include => association_columns(columns_names),
211
+ :methods => virtual_columns(columns_names),
212
+ :status => response_status
213
+ )
214
+ )
215
+ end
216
+
207
217
  # Success is the existence of one or more model objects. Most actions
208
218
  # circumvent this method by setting @success directly.
209
219
  def successful?
@@ -234,24 +244,32 @@ module ActiveScaffold::Actions
234
244
  # Builds search conditions by search params for column names. This allows urls like "contacts/list?company_id=5".
235
245
  def conditions_from_params
236
246
  @conditions_from_params ||= begin
237
- conditions = {}
247
+ conditions = [{}]
238
248
  params.except(:controller, :action, :page, :sort, :sort_direction, :format, :id).each do |key, value|
239
- column = active_scaffold_config._columns_hash[key.to_s]
249
+ distinct = true if key =~ /!$/
250
+ column = active_scaffold_config._columns_hash[key.to_s[0..(distinct ? -2 : -1)]]
240
251
  next unless column
241
- key = key.to_sym
252
+ key = column.name.to_sym
242
253
  not_string = %i[string text].exclude?(column.type)
243
254
  next if active_scaffold_constraints[key]
244
255
  next if nested? && nested.param_name == key
245
256
 
246
- range = %i[date datetime].include?(column.type) && value.is_a?(String) && value.scan('..').size == 1
257
+ range = %i[date datetime integer decimal float bigint].include?(column.type) && value.is_a?(String) && value.scan('..').size == 1
247
258
  value = value.split('..') if range
248
- conditions[key] =
259
+ value =
249
260
  if value.is_a?(Array)
250
261
  value.map { |v| v == '' && not_string ? nil : ActiveScaffold::Core.column_type_cast(v, column) }
262
+ elsif value == '' && (not_string || column.null)
263
+ ActiveScaffold::Core.column_type_cast(column.default, column)
251
264
  else
252
- value == '' && not_string ? nil : ActiveScaffold::Core.column_type_cast(value, column)
265
+ ActiveScaffold::Core.column_type_cast(value, column)
253
266
  end
254
- conditions[key] = Range.new(*conditions[key]) if range
267
+ value = Range.new(*value) if range
268
+ if distinct
269
+ conditions << active_scaffold_config.model.arel_table[key].not_eq(value)
270
+ else
271
+ conditions[0][key] = value
272
+ end
255
273
  end
256
274
  conditions
257
275
  end
@@ -259,39 +277,36 @@ module ActiveScaffold::Actions
259
277
 
260
278
  def new_model
261
279
  relation = beginning_of_chain
262
- config = active_scaffold_config_for(relation.klass) if nested? && nested.plural_association?
263
- if config && config._columns_hash[column = relation.klass.inheritance_column]
264
- model_name = params.delete(column) # in new action inheritance_column must be in params
265
- model_name ||= params[:record].delete(column) if params[:record].present? # in create action must be inside record key
266
- model_name = model_name.camelize if model_name
267
- model_name ||= active_scaffold_config.model.name
268
- build_options = {column.to_sym => model_name} if model_name
269
- end
280
+ build_options = sti_nested_build_options(relation.klass) if nested? && nested.plural_association?
270
281
  relation.respond_to?(:build) ? relation.build(build_options || {}) : relation.new
271
282
  end
272
283
 
284
+ def sti_nested_build_options(klass)
285
+ config = active_scaffold_config_for(klass)
286
+ return unless config
287
+ column = klass.inheritance_column
288
+ return unless column && config._columns_hash[column]
289
+
290
+ model_name = params.delete(column) # in new action inheritance_column must be in params
291
+ model_name ||= params[:record]&.delete(column) # in create action must be inside record key
292
+ model_name = model_name.camelize if model_name
293
+ model_name ||= active_scaffold_config.model.name
294
+ {column.to_sym => model_name} if model_name
295
+ end
296
+
273
297
  def get_row(crud_type_or_security_options = :read)
274
298
  klass = beginning_of_chain
275
299
  klass = klass.preload(active_scaffold_preload) unless active_scaffold_config.mongoid?
276
300
  @record = find_if_allowed(params[:id], crud_type_or_security_options, klass)
277
301
  end
278
302
 
279
- def active_scaffold_session_storage_key(id = nil)
280
- id ||= params[:eid] || "#{params[:controller]}#{"_#{nested_parent_id}" if nested?}"
281
- "as:#{id}"
282
- end
283
-
284
- def active_scaffold_session_storage(id = nil)
285
- session_index = active_scaffold_session_storage_key(id)
286
- session[session_index] ||= {}
287
- session[session_index]
288
- end
289
-
290
303
  def active_scaffold_embedded_params
291
304
  params[:embedded] || {}
292
305
  end
293
306
 
294
307
  def clear_storage
308
+ yield if block_given?
309
+ ensure
295
310
  session_index = active_scaffold_session_storage_key
296
311
  session.delete(session_index) if session[session_index].blank?
297
312
  end
@@ -300,25 +315,14 @@ module ActiveScaffold::Actions
300
315
  response.headers['Vary'] = 'Accept'
301
316
  end
302
317
 
303
- # at some point we need to pass the session and params into config. we'll just take care of that before any particular action occurs by passing those hashes off to the UserSettings class of each action.
304
- def handle_user_settings
305
- storage = active_scaffold_config.store_user_settings ? active_scaffold_session_storage : {}
306
- active_scaffold_config.actions.each do |action_name|
307
- conf_instance = active_scaffold_config.send(action_name) rescue next
308
- next if conf_instance.class::UserSettings == ActiveScaffold::Config::Base::UserSettings # if it hasn't been extended, skip it
309
- conf_instance.user = conf_instance.class::UserSettings.new(conf_instance, storage, params)
310
- end
311
- end
312
-
313
318
  def check_input_device
314
- if session[:input_device_type].nil?
315
- if request.env['HTTP_USER_AGENT'] && request.env['HTTP_USER_AGENT'][/(iPhone|iPod|iPad)/i]
316
- session[:input_device_type] = 'TOUCH'
317
- session[:hover_supported] = false
318
- else
319
- session[:input_device_type] = 'MOUSE'
320
- session[:hover_supported] = true
321
- end
319
+ return unless session[:input_device_type].nil?
320
+ if request.env['HTTP_USER_AGENT'] =~ /(iPhone|iPod|iPad)/i
321
+ session[:input_device_type] = 'TOUCH'
322
+ session[:hover_supported] = false
323
+ else
324
+ session[:input_device_type] = 'MOUSE'
325
+ session[:hover_supported] = true
322
326
  end
323
327
  end
324
328
 
@@ -340,7 +344,7 @@ module ActiveScaffold::Actions
340
344
 
341
345
  def params_hash(value)
342
346
  if controller_params?(value)
343
- Rails.version < '4.2' ? value.clone.permit! : value.to_unsafe_h.with_indifferent_access
347
+ value.to_unsafe_h.with_indifferent_access
344
348
  else
345
349
  value
346
350
  end
@@ -361,7 +365,7 @@ module ActiveScaffold::Actions
361
365
  else
362
366
  @action_link = active_scaffold_config.action_links[action_name]
363
367
  if params[:id]
364
- crud_type_or_security_options ||= {:crud_type => (request.post? || request.put?) ? :update : :delete, :action => action_name}
368
+ crud_type_or_security_options ||= {:crud_type => request.post? || request.put? ? :update : :delete, :action => action_name}
365
369
  get_row(crud_type_or_security_options)
366
370
  if @record.nil?
367
371
  self.successful = false
@@ -381,20 +385,24 @@ module ActiveScaffold::Actions
381
385
  render :action => 'action_confirmation', :locals => {:record => @record, :link => link}
382
386
  end
383
387
 
388
+ def action_update_respond_on_iframe
389
+ responds_to_parent { action_update_respond_to_js }
390
+ end
391
+
384
392
  def action_update_respond_to_html
385
393
  redirect_to :action => 'index'
386
394
  end
387
395
 
388
396
  def action_update_respond_to_js
389
- render(:action => 'on_action_update')
397
+ render :action => 'on_action_update', :formats => [:js], :layout => false
390
398
  end
391
399
 
392
400
  def action_update_respond_to_xml
393
- render :xml => successful? ? '' : response_object, :only => list_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(list_columns_names), :methods => virtual_columns(list_columns_names), :status => response_status
401
+ response_to_api(:xml, list_columns_names)
394
402
  end
395
403
 
396
404
  def action_update_respond_to_json
397
- render :json => successful? ? '' : response_object, :only => list_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(list_columns_names), :methods => virtual_columns(list_columns_names), :status => response_status
405
+ response_to_api(:json, list_columns_names)
398
406
  end
399
407
 
400
408
  def objects_for_etag
@@ -420,11 +428,13 @@ module ActiveScaffold::Actions
420
428
  end
421
429
 
422
430
  def virtual_columns(columns)
423
- columns.reject { |col| active_scaffold_config.model.columns_hash[col.to_s] || active_scaffold_config.columns[col].try(:association) }
431
+ columns.reject do |col|
432
+ active_scaffold_config._columns_hash[col.to_s] || active_scaffold_config.columns[col]&.association
433
+ end
424
434
  end
425
435
 
426
436
  def association_columns(columns)
427
- columns.select { |col| active_scaffold_config.columns[col].try(:association) }
437
+ columns.select { |col| active_scaffold_config.columns[col]&.association }
428
438
  end
429
439
 
430
440
  private
@@ -434,14 +444,22 @@ module ActiveScaffold::Actions
434
444
  respond_to do |type|
435
445
  action_formats.each do |format|
436
446
  type.send(format) do
437
- if respond_to?(method_name = "#{action}_respond_to_#{format}", true)
438
- send(method_name)
439
- end
447
+ method_name = respond_method_for(action, format)
448
+ send(method_name) if method_name
440
449
  end
441
450
  end
442
451
  end
443
452
  end
444
453
 
454
+ def respond_method_for(action, format)
455
+ if format == :html && params[:iframe] == 'true'
456
+ method_name = "#{action}_respond_on_iframe"
457
+ return method_name if respond_to?(method_name, true)
458
+ end
459
+ method_name = "#{action}_respond_to_#{format}"
460
+ method_name if respond_to?(method_name, true)
461
+ end
462
+
445
463
  def action_formats
446
464
  @action_formats ||=
447
465
  if respond_to? "#{action_name}_formats", true
@@ -457,7 +475,7 @@ module ActiveScaffold::Actions
457
475
  klass = klass.superclass
458
476
  controller = self.class.active_scaffold_controller_for(klass)
459
477
  cfg = controller.active_scaffold_config if controller.uses_active_scaffold?
460
- next unless cfg && cfg.add_sti_create_links?
478
+ next unless cfg&.add_sti_create_links?
461
479
  return controller if cfg.sti_children.map(&:to_s).include? self.class.active_scaffold_config.model.name.underscore
462
480
  end
463
481
  rescue ActiveScaffold::ControllerNotFound => ex
@@ -32,51 +32,51 @@ module ActiveScaffold::Actions
32
32
  render(:partial => 'create_form')
33
33
  end
34
34
 
35
+ def create_respond_on_iframe
36
+ do_refresh_list if successful? && active_scaffold_config.create.refresh_list && !render_parent?
37
+ responds_to_parent do
38
+ render :action => 'on_create', :formats => [:js], :layout => false
39
+ end
40
+ end
41
+
35
42
  def create_respond_to_html
36
- if params[:iframe] == 'true' # was this an iframe post ?
37
- do_refresh_list if successful? && active_scaffold_config.create.refresh_list && !render_parent?
38
- responds_to_parent do
39
- render :action => 'on_create', :formats => [:js], :layout => false
40
- end
41
- else
42
- if successful?
43
- flash[:info] = as_(:created_model, :model => ERB::Util.h(@record.to_label))
44
- if (action = active_scaffold_config.create.action_after_create)
45
- redirect_to params_for(:action => action, :id => @record.to_param)
46
- elsif params[:dont_close]
47
- redirect_to params_for(:action => 'new')
48
- else
49
- return_to_main
50
- end
43
+ if successful?
44
+ flash[:info] = as_(:created_model, :model => ERB::Util.h(@record.to_label))
45
+ if (action = active_scaffold_config.create.action_after_create)
46
+ redirect_to params_for(:action => action, :id => @record.to_param)
47
+ elsif params[:dont_close]
48
+ redirect_to params_for(:action => 'new')
51
49
  else
52
- if active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.always_show_create
53
- list
54
- else
55
- render(:action => 'create')
56
- end
50
+ return_to_main
57
51
  end
52
+ elsif active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.always_show_create
53
+ list
54
+ else
55
+ render(:action => 'create')
58
56
  end
59
57
  end
60
58
 
61
59
  def create_respond_to_js
62
- do_refresh_list if successful? && active_scaffold_config.create.refresh_list && !render_parent?
63
- if successful? && params[:dont_close] && !render_parent?
64
- @saved_record = @record
65
- do_new
60
+ if successful? && !render_parent?
61
+ do_refresh_list if active_scaffold_config.create.refresh_list
62
+ if params[:dont_close]
63
+ @saved_record = @record
64
+ do_new
65
+ end
66
66
  end
67
67
  render :action => 'on_create'
68
68
  end
69
69
 
70
70
  def create_respond_to_xml
71
- render :xml => response_object, :only => create_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(create_columns_names), :methods => virtual_columns(create_columns_names), :status => response_status, :location => response_location
71
+ response_to_api(:xml, create_columns_names, location: response_location)
72
72
  end
73
73
 
74
74
  def create_respond_to_json
75
- render :json => response_object, :only => create_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(create_columns_names), :methods => virtual_columns(create_columns_names), :status => response_status, :location => response_location
75
+ response_to_api(:json, create_columns_names, location: response_location)
76
76
  end
77
77
 
78
78
  def create_columns_names
79
- active_scaffold_config.create.columns.names
79
+ active_scaffold_config.create.columns.visible_columns_names
80
80
  end
81
81
 
82
82
  # A simple method to find and prepare an example new record for the form
@@ -136,7 +136,7 @@ module ActiveScaffold::Actions
136
136
  private
137
137
 
138
138
  def create_authorized_filter
139
- link = active_scaffold_config.create.link || active_scaffold_config.create.class.link
139
+ link = active_scaffold_config.create.link || self.class.active_scaffold_config.create.class.link
140
140
  raise ActiveScaffold::ActionNotAllowed unless send(link.security_method)
141
141
  end
142
142
 
@@ -24,11 +24,11 @@ module ActiveScaffold::Actions
24
24
  end
25
25
 
26
26
  def destroy_respond_to_xml
27
- render :xml => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
27
+ render :xml => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
28
28
  end
29
29
 
30
30
  def destroy_respond_to_json
31
- render :json => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
31
+ render :json => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
32
32
  end
33
33
 
34
34
  def destroy_find_record
@@ -65,7 +65,7 @@ module ActiveScaffold::Actions
65
65
  private
66
66
 
67
67
  def delete_authorized_filter
68
- link = active_scaffold_config.delete.link || active_scaffold_config.delete.class.link
68
+ link = active_scaffold_config.delete.link || self.class.active_scaffold_config.delete.class.link
69
69
  raise ActiveScaffold::ActionNotAllowed unless Array(send(link.security_method))[0]
70
70
  end
71
71