active_scaffold 3.5.4 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +72 -0
  3. data/README.md +20 -8
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +98 -7
  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.html.erb +2 -1
  11. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  12. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +9 -7
  13. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +4 -4
  14. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  16. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  17. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  18. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  19. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  20. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  21. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  22. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  23. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  24. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  25. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  26. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  27. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  28. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
  29. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  30. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  31. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  32. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  33. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  34. data/app/views/active_scaffold_overrides/update_column.js.erb +2 -2
  35. data/config/locales/de.yml +2 -1
  36. data/config/locales/en.yml +1 -0
  37. data/config/locales/es.yml +1 -0
  38. data/config/locales/fr.yml +2 -1
  39. data/config/locales/hu.yml +1 -0
  40. data/config/locales/ja.yml +1 -0
  41. data/config/locales/ru.yml +1 -0
  42. data/lib/active_scaffold.rb +19 -16
  43. data/lib/active_scaffold/actions/common_search.rb +11 -8
  44. data/lib/active_scaffold/actions/core.rb +91 -70
  45. data/lib/active_scaffold/actions/create.rb +28 -28
  46. data/lib/active_scaffold/actions/delete.rb +3 -3
  47. data/lib/active_scaffold/actions/field_search.rb +53 -43
  48. data/lib/active_scaffold/actions/list.rb +111 -27
  49. data/lib/active_scaffold/actions/nested.rb +65 -48
  50. data/lib/active_scaffold/actions/search.rb +1 -1
  51. data/lib/active_scaffold/actions/show.rb +4 -4
  52. data/lib/active_scaffold/actions/subform.rb +23 -22
  53. data/lib/active_scaffold/actions/update.rb +96 -77
  54. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  55. data/lib/active_scaffold/attribute_params.rb +102 -94
  56. data/lib/active_scaffold/bridges.rb +8 -8
  57. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  58. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +34 -0
  59. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  60. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  61. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  62. data/lib/active_scaffold/bridges/bitfields.rb +2 -1
  63. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  64. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +19 -0
  65. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  66. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -12
  67. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  68. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  69. data/lib/active_scaffold/bridges/chosen/helpers.rb +7 -6
  70. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  71. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  72. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  73. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  74. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  75. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  76. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  77. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  78. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  79. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  80. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  81. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  82. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -17
  83. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  84. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  85. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  86. data/lib/active_scaffold/config/base.rb +133 -41
  87. data/lib/active_scaffold/config/core.rb +146 -18
  88. data/lib/active_scaffold/config/delete.rb +14 -1
  89. data/lib/active_scaffold/config/field_search.rb +7 -1
  90. data/lib/active_scaffold/config/form.rb +10 -1
  91. data/lib/active_scaffold/config/list.rb +39 -13
  92. data/lib/active_scaffold/config/mark.rb +4 -2
  93. data/lib/active_scaffold/config/nested.rb +16 -17
  94. data/lib/active_scaffold/config/search.rb +9 -0
  95. data/lib/active_scaffold/config/show.rb +4 -0
  96. data/lib/active_scaffold/config/update.rb +4 -0
  97. data/lib/active_scaffold/configurable.rb +14 -7
  98. data/lib/active_scaffold/constraints.rb +22 -20
  99. data/lib/active_scaffold/core.rb +67 -28
  100. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  101. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  102. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  103. data/lib/active_scaffold/data_structures/association/abstract.rb +38 -15
  104. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  105. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  106. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  107. data/lib/active_scaffold/data_structures/column.rb +75 -66
  108. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  109. data/lib/active_scaffold/data_structures/nested_info.rb +33 -19
  110. data/lib/active_scaffold/data_structures/set.rb +8 -0
  111. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  112. data/lib/active_scaffold/delayed_setup.rb +16 -5
  113. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  114. data/lib/active_scaffold/extensions/action_view_rendering.rb +93 -32
  115. data/lib/active_scaffold/extensions/cow_proxy.rb +95 -0
  116. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  117. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  118. data/lib/active_scaffold/extensions/localize.rb +3 -1
  119. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  120. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  121. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  122. data/lib/active_scaffold/finder.rb +110 -77
  123. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  124. data/lib/active_scaffold/helpers/association_helpers.rb +18 -16
  125. data/lib/active_scaffold/helpers/controller_helpers.rb +34 -10
  126. data/lib/active_scaffold/helpers/form_column_helpers.rb +196 -124
  127. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  128. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  129. data/lib/active_scaffold/helpers/list_column_helpers.rb +90 -57
  130. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  131. data/lib/active_scaffold/helpers/search_column_helpers.rb +29 -34
  132. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  133. data/lib/active_scaffold/helpers/view_helpers.rb +39 -36
  134. data/lib/active_scaffold/marked_model.rb +2 -2
  135. data/lib/active_scaffold/orm_checks.rb +3 -7
  136. data/lib/active_scaffold/paginator.rb +7 -7
  137. data/lib/active_scaffold/registry.rb +33 -0
  138. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  139. data/lib/active_scaffold/tableless.rb +82 -66
  140. data/lib/active_scaffold/version.rb +2 -2
  141. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  142. data/lib/generators/active_scaffold/install_generator.rb +52 -4
  143. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  144. data/shoulda_macros/macros.rb +3 -1
  145. data/test/bridges/date_picker_test.rb +1 -2
  146. data/test/bridges/paperclip_test.rb +6 -6
  147. data/test/class_with_finder.rb +2 -2
  148. data/test/company.rb +4 -4
  149. data/test/config/create_test.rb +4 -2
  150. data/test/config/nested_test.rb +1 -1
  151. data/test/config/show_test.rb +1 -1
  152. data/test/config/update_test.rb +7 -6
  153. data/test/data_structures/action_columns_test.rb +2 -2
  154. data/test/data_structures/action_links_test.rb +1 -1
  155. data/test/data_structures/column_test.rb +3 -6
  156. data/test/data_structures/columns_test.rb +2 -2
  157. data/test/data_structures/sorting_test.rb +7 -0
  158. data/test/extensions/action_view_rendering_test.rb +20 -0
  159. data/test/extensions/active_record_test.rb +4 -4
  160. data/test/extensions/routing_mapper_test.rb +2 -2
  161. data/test/helpers/list_column_helpers_test.rb +3 -1
  162. data/test/misc/active_record_permissions_test.rb +3 -11
  163. data/test/misc/attribute_params_test.rb +12 -8
  164. data/test/misc/calculation_test.rb +1 -1
  165. data/test/misc/configurable_test.rb +10 -10
  166. data/test/misc/constraints_test.rb +2 -2
  167. data/test/misc/convert_numbers_format_test.rb +7 -3
  168. data/test/misc/lang_test.rb +1 -1
  169. data/test/misc/parse_datetime_test.rb +3 -4
  170. data/test/misc/tableless_test.rb +14 -0
  171. data/test/mock_app/Rakefile +1 -1
  172. data/test/mock_app/app/assets/config/manifest.js +0 -0
  173. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  174. data/test/mock_app/app/controllers/people_controller.rb +5 -1
  175. data/test/mock_app/app/controllers/roles_controller.rb +4 -0
  176. data/test/mock_app/app/views/active_scaffold_overrides/_form.html.erb +2 -0
  177. data/test/mock_app/app/views/active_scaffold_overrides/list.html.erb +2 -0
  178. data/test/mock_app/app/views/people/_first_name_form_column.html.erb +2 -0
  179. data/test/mock_app/app/views/people/_form.html.erb +2 -0
  180. data/test/mock_app/app/views/people/list.html.erb +2 -0
  181. data/test/mock_app/config/application.rb +2 -1
  182. data/test/mock_app/config/boot.rb +1 -1
  183. data/test/mock_app/config/environment.rb +2 -2
  184. data/test/mock_app/config/routes.rb +4 -1
  185. data/test/mock_app/db/schema.rb +2 -0
  186. data/test/performance/list_cars_performance_test.rb +34 -0
  187. data/test/performance/list_people_performance_test.rb +31 -0
  188. data/test/performance_test_help.rb +3 -0
  189. data/test/test_helper.rb +12 -4
  190. metadata +69 -18
  191. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  192. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -7
@@ -1,5 +1,7 @@
1
1
  module ActiveScaffold::Actions
2
- # The Nested module basically handles automatically linking controllers together. It does this by creating column links with the right parameters, and by providing any supporting systems (like a /:controller/nested action for returning associated scaffolds).
2
+ # The Nested module basically handles automatically linking controllers together.
3
+ # It does this by creating column links with the right parameters, and by providing
4
+ # any supporting systems (like a /:controller/nested action for returning associated scaffolds).
3
5
  module Nested
4
6
  def self.included(base)
5
7
  super
@@ -27,17 +29,17 @@ module ActiveScaffold::Actions
27
29
  def set_nested
28
30
  @nested = nil
29
31
  return unless params[:parent_scaffold] && (params[:association] || params[:named_scope])
30
- @nested = ActiveScaffold::DataStructures::NestedInfo.get(active_scaffold_config.model, params)
31
- register_constraints_with_action_columns(@nested.constrained_fields) unless @nested.nil?
32
+ @nested = ActiveScaffold::DataStructures::NestedInfo.get(self.class.active_scaffold_config.model, params)
32
33
  end
33
34
 
34
35
  def configure_nested
35
36
  return unless nested?
37
+ register_constraints_with_action_columns(nested.constrained_fields)
38
+ return unless active_scaffold_config.actions.include? :list
36
39
  active_scaffold_config.list.user.label = nested_label
37
- unless active_scaffold_config.nested.ignore_order_from_association
38
- chain = beginning_of_chain
39
- active_scaffold_config.list.user.nested_default_sorting = nested_default_sorting(chain) if nested.sorted?(chain)
40
- end
40
+ return if active_scaffold_config.nested.ignore_order_from_association
41
+ chain = beginning_of_chain
42
+ active_scaffold_config.list.user.nested_default_sorting = nested_default_sorting(chain) if nested.sorted?(chain)
41
43
  end
42
44
 
43
45
  def nested_label
@@ -57,41 +59,39 @@ module ActiveScaffold::Actions
57
59
  end
58
60
 
59
61
  def include_habtm_actions
60
- if nested? && nested.habtm?
62
+ if nested&.habtm?
61
63
  # Production mode is ok with adding a link everytime the scaffold is nested - we are not ok with that.
62
- active_scaffold_config.action_links.add('new_existing', :label => :add_existing, :type => :collection, :security_method => :add_existing_authorized?) unless active_scaffold_config.action_links['new_existing']
63
- if active_scaffold_config.nested.shallow_delete
64
- active_scaffold_config.action_links.add('destroy_existing', :label => :remove, :type => :member, :confirm => :are_you_sure_to_delete, :method => :delete, :position => false, :security_method => :delete_existing_authorized?) unless active_scaffold_config.action_links['destroy_existing']
65
- if active_scaffold_config.actions.include?(:delete)
66
- active_scaffold_config.action_links.delete('destroy') if active_scaffold_config.action_links['destroy']
67
- end
68
- end
69
- else
70
- # Production mode is caching this link into a non nested scaffold
71
- active_scaffold_config.action_links.delete('new_existing') if active_scaffold_config.action_links['new_existing']
72
-
73
- if active_scaffold_config.nested.shallow_delete
74
- active_scaffold_config.action_links.delete('destroy_existing') if active_scaffold_config.action_links['destroy_existing']
75
- if active_scaffold_config.actions.include?(:delete) && active_scaffold_config.delete.link
76
- active_scaffold_config.action_links.add(active_scaffold_config.delete.link) unless active_scaffold_config.action_links['destroy']
77
- end
64
+ unless active_scaffold_config.action_links['new_existing']
65
+ active_scaffold_config.action_links.add('new_existing', :label => :add_existing, :type => :collection, :security_method => :add_existing_authorized?)
78
66
  end
67
+ add_shallow_links if active_scaffold_config.nested.shallow_delete
68
+ elsif !ActiveScaffold.threadsafe
69
+ # Production mode is caching this link into a non nested scaffold, when threadsafe is disabled
70
+ active_scaffold_config.action_links.delete('new_existing')
71
+ restore_shallow_links if active_scaffold_config.nested.shallow_delete
79
72
  end
80
73
  end
81
74
 
75
+ def add_shallow_links
76
+ unless active_scaffold_config.action_links['destroy_existing']
77
+ link_options = {:label => :remove, :type => :member, :confirm => :are_you_sure_to_delete, :method => :delete, :position => false, :security_method => :delete_existing_authorized?}
78
+ active_scaffold_config.action_links.add('destroy_existing', link_options)
79
+ end
80
+ active_scaffold_config.action_links.delete('destroy') if active_scaffold_config.actions.include?(:delete)
81
+ end
82
+
83
+ def restore_shallow_links
84
+ if active_scaffold_config.actions.include?(:delete) && active_scaffold_config.delete.link
85
+ link = active_scaffold_config.delete.link
86
+ active_scaffold_config.action_links.add(link) unless active_scaffold_config.action_links[link.action]
87
+ end
88
+ active_scaffold_config.action_links.delete('destroy_existing')
89
+ end
90
+
82
91
  def beginning_of_chain
83
- if nested? && nested.association
84
- if nested.association.collection?
85
- nested_parent_record.send(nested.association.name)
86
- elsif nested.association.through? # has_one :through
87
- active_scaffold_config.model.where(active_scaffold_config.model.primary_key => nested_parent_record.send(nested.association.name).try(:id))
88
- elsif nested.association.has_one?
89
- active_scaffold_config.model.where(nested.child_association.foreign_key => nested_parent_record.send(nested.association.association_primary_key))
90
- elsif nested.association.belongs_to?
91
- nested_belongs_to_chain
92
- else # never should get here
93
- active_scaffold_config.model
94
- end
92
+ # only if nested is related to current controller, e.g. not when adding record in subform inside subform
93
+ if nested? && nested.match_model?(active_scaffold_config.model)
94
+ nested_chain_with_association
95
95
  elsif nested? && nested.scope
96
96
  nested_parent_record.send(nested.scope)
97
97
  else
@@ -99,23 +99,40 @@ module ActiveScaffold::Actions
99
99
  end
100
100
  end
101
101
 
102
- def nested_belongs_to_chain
103
- primary_key = active_scaffold_config.mongoid? ? '_id' : active_scaffold_config.model.primary_key
104
- active_scaffold_config.model.where(primary_key => nested_parent_record.send(nested.association.name))
102
+ def nested_chain_with_association
103
+ if nested.association.collection?
104
+ nested_parent_record.send(nested.association.name)
105
+ elsif nested.association.through? # has_one :through
106
+ active_scaffold_config.model.where(active_scaffold_config.model.primary_key => nested_parent_record.send(nested.association.name)&.id)
107
+ elsif nested.association.has_one?
108
+ active_scaffold_config.model.where(nested.child_association.name => nested_parent_record)
109
+ elsif nested.association.belongs_to?
110
+ primary_key = active_scaffold_config.mongoid? ? '_id' : active_scaffold_config.model.primary_key
111
+ active_scaffold_config.model.where(primary_key => nested_parent_record.send(nested.association.name))
112
+ else # never should get here
113
+ raise 'missing condition for nested beginning_of_chain'
114
+ end
105
115
  end
106
116
 
107
117
  def nested_parent_record(crud = :read)
108
118
  @nested_parent_record ||= find_if_allowed(nested.parent_id, crud, nested.parent_model)
109
119
  end
110
120
 
121
+ def create_association_with_parent?
122
+ # has_many is done by beginning_of_chain and rails if direct association, not in through associations
123
+ return false if nested.has_many? && !nested.association.through?
124
+ nested.child_association && nested_parent_record
125
+ end
126
+
111
127
  def create_association_with_parent(record)
112
- # has_many is done by beginning_of_chain and rails
113
- return unless (nested.belongs_to? || nested.has_one? || nested.habtm?) && nested.child_association
114
- return if (parent = nested_parent_record).nil?
128
+ return unless create_association_with_parent?
115
129
  if nested.child_association.singular?
116
- record.send("#{nested.child_association.name}=", parent)
130
+ record.send("#{nested.child_association.name}=", nested_parent_record)
131
+ elsif nested.association.through_singular? && nested.child_association.through_singular?
132
+ through = nested_parent_record.send(nested.association.through_reflection.name)
133
+ record.send("#{nested.child_association.through_reflection.name}=", through)
117
134
  else
118
- record.send(nested.child_association.name) << parent
135
+ record.send(nested.child_association.name) << nested_parent_record
119
136
  end
120
137
  end
121
138
 
@@ -181,11 +198,11 @@ module ActiveScaffold::Actions::Nested
181
198
  end
182
199
 
183
200
  def add_existing_respond_to_xml
184
- render :xml => response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
201
+ render :xml => response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
185
202
  end
186
203
 
187
204
  def add_existing_respond_to_json
188
- render :json => response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
205
+ render :json => response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
189
206
  end
190
207
 
191
208
  def destroy_existing_respond_to_html
@@ -198,11 +215,11 @@ module ActiveScaffold::Actions::Nested
198
215
  end
199
216
 
200
217
  def destroy_existing_respond_to_xml
201
- render :xml => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
218
+ render :xml => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
202
219
  end
203
220
 
204
221
  def destroy_existing_respond_to_json
205
- render :json => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.names, :status => response_status
222
+ render :json => successful? ? '' : response_object, :only => active_scaffold_config.list.columns.visible_columns_names, :status => response_status
206
223
  end
207
224
 
208
225
  def add_existing_authorized?(record = nil)
@@ -19,7 +19,7 @@ module ActiveScaffold::Actions
19
19
  def do_search
20
20
  if search_params.is_a?(String) && search_params.present?
21
21
  query = search_params.to_s.strip
22
- columns = active_scaffold_config.search.columns
22
+ columns = active_scaffold_config.search.columns.visible_columns
23
23
  text_search = active_scaffold_config.search.text_search
24
24
  query = query.split(active_scaffold_config.search.split_terms) if active_scaffold_config.search.split_terms
25
25
  search_conditions = self.class.conditions_for_columns(query, columns, text_search)
@@ -19,11 +19,11 @@ module ActiveScaffold::Actions
19
19
  protected
20
20
 
21
21
  def show_respond_to_json
22
- render :json => response_object, :only => show_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(show_columns_names), :methods => virtual_columns(show_columns_names), :status => response_status
22
+ response_to_api(:json, show_columns_names)
23
23
  end
24
24
 
25
25
  def show_respond_to_xml
26
- render :xml => response_object, :only => show_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(show_columns_names), :methods => virtual_columns(show_columns_names), :status => response_status
26
+ response_to_api(:xml, show_columns_names)
27
27
  end
28
28
 
29
29
  def show_respond_to_js
@@ -35,7 +35,7 @@ module ActiveScaffold::Actions
35
35
  end
36
36
 
37
37
  def show_columns_names
38
- active_scaffold_config.show.columns.names
38
+ active_scaffold_config.show.columns.visible_columns_names
39
39
  end
40
40
 
41
41
  # A simple method to retrieve and prepare a record for showing.
@@ -58,7 +58,7 @@ module ActiveScaffold::Actions
58
58
  private
59
59
 
60
60
  def show_authorized_filter
61
- link = active_scaffold_config.show.link || active_scaffold_config.show.class.link
61
+ link = active_scaffold_config.show.link || self.class.active_scaffold_config.show.class.link
62
62
  raise ActiveScaffold::ActionNotAllowed unless Array(send(link.security_method))[0]
63
63
  end
64
64
 
@@ -2,37 +2,38 @@ module ActiveScaffold::Actions
2
2
  module Subform
3
3
  def edit_associated
4
4
  do_edit_associated
5
- render :action => 'edit_associated', :formats => [:js], :readonly => @column.association.readonly?
5
+ respond_to do |format|
6
+ format.js { render :action => 'edit_associated', :formats => [:js], :readonly => @column.association.readonly? }
7
+ end
6
8
  end
7
9
 
8
10
  protected
9
11
 
10
- def do_edit_associated
11
- @parent_record = params[:id].nil? ? new_model : find_if_allowed(params[:id], :update)
12
- if @parent_record.new_record?
13
- apply_constraints_to_record @parent_record
14
- create_association_with_parent @parent_record if nested?
12
+ def new_parent_record
13
+ parent_record = new_model
14
+ # don't apply if scope, subform inside subform, because constraints won't apply to parent_record
15
+ apply_constraints_to_record parent_record unless @scope
16
+ if nested? && nested.match_model?(active_scaffold_config.model)
17
+ create_association_with_parent parent_record
15
18
  end
19
+ parent_record
20
+ end
16
21
 
17
- generate_temporary_id(@parent_record, params[:generated_id]) if @parent_record.new_record? && params[:generated_id]
22
+ def do_edit_associated
23
+ @scope = params[:scope]
24
+ @parent_record = params[:id].nil? ? new_parent_record : find_if_allowed(params[:id], :update)
25
+
26
+ cache_generated_id(@parent_record, params[:generated_id]) if @parent_record.new_record?
18
27
  @column = active_scaffold_config.columns[params[:child_association]]
19
28
 
20
- # NOTE: we don't check whether the user is allowed to update this record, because if not, we'll still let them associate the record. we'll just refuse to do more than associate, is all.
21
- if params[:associated_id]
22
- @record = @column.association.klass.find(params[:associated_id])
23
- if (reverse = @column.association.reverse_association)
24
- if reverse.collection?
25
- @record.send(reverse.name) << @parent_record
26
- elsif @column.association.belongs_to?
27
- @parent_record.send("#{@column.name}=", @record)
28
- else
29
- @record.send("#{reverse.name}=", @parent_record)
30
- end
31
- end
32
- else
33
- @record = build_associated(@column.association, @parent_record)
29
+ @record = find_associated_record if params[:associated_id]
30
+ @record ||= build_associated(@column.association, @parent_record)
31
+ end
32
+
33
+ def find_associated_record
34
+ @column.association.klass.find(params[:associated_id]).tap do |record|
35
+ save_record_to_association(record, @column.association.reverse_association, @parent_record, @column.association)
34
36
  end
35
- @scope = params[:scope]
36
37
  end
37
38
  end
38
39
  end
@@ -35,54 +35,63 @@ module ActiveScaffold::Actions
35
35
  render(:partial => 'update_form')
36
36
  end
37
37
 
38
+ def update_respond_on_iframe
39
+ do_refresh_list if successful? && active_scaffold_config.update.refresh_list && !render_parent?
40
+ responds_to_parent do
41
+ render :action => 'on_update', :formats => [:js], :layout => false
42
+ end
43
+ end
44
+
38
45
  def update_respond_to_html
39
- if params[:iframe] == 'true' # was this an iframe post ?
40
- do_refresh_list if successful? && active_scaffold_config.update.refresh_list && !render_parent?
41
- responds_to_parent do
42
- render :action => 'on_update', :formats => [:js], :layout => false
43
- end
44
- else # just a regular post
45
- if successful?
46
- message = as_(:updated_model, :model => ERB::Util.h(@record.to_label))
47
- if params[:dont_close]
48
- flash.now[:info] = message
49
- render(:action => 'update')
50
- else
51
- flash[:info] = message
52
- return_to_main
53
- end
54
- else
46
+ if successful? # just a regular post
47
+ message = as_(:updated_model, :model => ERB::Util.h(@record.to_label))
48
+ if params[:dont_close]
49
+ flash.now[:info] = message
55
50
  render(:action => 'update')
51
+ else
52
+ flash[:info] = message
53
+ return_to_main
56
54
  end
55
+ else
56
+ render(:action => 'update')
57
57
  end
58
58
  end
59
59
 
60
+ def record_to_refresh_on_update
61
+ if update_refresh_list?
62
+ do_refresh_list
63
+ else
64
+ reload_record_on_update
65
+ end
66
+ end
67
+
68
+ def reload_record_on_update
69
+ @updated_record = @record
70
+ # get_row so associations are cached like in list action
71
+ # if record doesn't fullfil current conditions remove it from list
72
+ @record = get_row
73
+ rescue ActiveRecord::RecordNotFound
74
+ nil
75
+ end
76
+
60
77
  def update_respond_to_js
61
78
  if successful?
62
- if !render_parent? && active_scaffold_config.actions.include?(:list)
63
- if update_refresh_list?
64
- do_refresh_list
65
- else
66
- @updated_record = @record
67
- # get_row so associations are cached like in list action
68
- @record = get_row rescue nil # if record doesn't fullfil current conditions remove it from list
69
- end
70
- end
79
+ record_to_refresh_on_update if !render_parent? && active_scaffold_config.actions.include?(:list)
71
80
  flash.now[:info] = as_(:updated_model, :model => ERB::Util.h((@updated_record || @record).to_label)) if active_scaffold_config.update.persistent
72
81
  end
73
82
  render :action => 'on_update'
74
83
  end
75
84
 
76
85
  def update_respond_to_xml
77
- render :xml => response_object, :only => update_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(update_columns_names), :methods => virtual_columns(update_columns_names), :status => response_status
86
+ response_to_api(:xml, update_columns_names)
78
87
  end
79
88
 
80
89
  def update_respond_to_json
81
- render :json => response_object, :only => update_columns_names + [active_scaffold_config.model.primary_key], :include => association_columns(update_columns_names), :methods => virtual_columns(update_columns_names), :status => response_status
90
+ response_to_api(:json, update_columns_names)
82
91
  end
83
92
 
84
93
  def update_columns_names
85
- active_scaffold_config.update.columns.names
94
+ active_scaffold_config.update.columns.visible_columns_names
86
95
  end
87
96
 
88
97
  # A simple method to find and prepare a record for editing
@@ -91,45 +100,47 @@ module ActiveScaffold::Actions
91
100
  @record = find_if_allowed(params[:id], :update)
92
101
  end
93
102
 
94
- # A complex method to update a record. The complexity comes from the support for subforms, and saving associated records.
103
+ # A complex method to update a record. The complexity comes from the support for subforms,
104
+ # and saving associated records.
95
105
  # If you want to customize this algorithm, consider using the +before_update_save+ callback
96
106
  def do_update
97
107
  do_edit
98
108
  update_save
99
109
  end
100
110
 
101
- def update_save(options = {})
102
- attributes = options[:attributes] || params[:record]
103
- begin
104
- active_scaffold_config.model.transaction do
105
- @record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes) unless options[:no_record_param_update]
106
- before_update_save(@record)
107
- # errors to @record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
108
- self.successful = [@record.keeping_errors { @record.valid? }, @record.associated_valid?].all? # this syntax avoids a short-circuit
109
- if successful?
110
- @record.save! && @record.save_associated!
111
- after_update_save(@record)
112
- else
113
- # some associations such as habtm are saved before saved is called on parent object
114
- # we have to revert these changes if validation fails
115
- raise ActiveRecord::Rollback, "don't save habtm associations unless record is valid"
116
- end
111
+ def update_save(attributes: params[:record], no_record_param_update: false)
112
+ active_scaffold_config.model.transaction do
113
+ unless no_record_param_update
114
+ @record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes)
117
115
  end
118
- rescue ActiveRecord::StaleObjectError
119
- @record.errors.add(:base, as_(:version_inconsistency))
120
- self.successful = false
121
- rescue ActiveRecord::RecordNotSaved => exception
122
- logger.warn do
123
- "\n\n#{exception.class} (#{exception.message}):\n " +
124
- Rails.backtrace_cleaner.clean(exception.backtrace).join("\n ") +
125
- "\n\n"
116
+ before_update_save(@record)
117
+ # errors to @record can be added by update_record_from_params when association fails
118
+ # to set and ActiveRecord::RecordNotSaved is raised
119
+ # this syntax avoids a short-circuit, so we run validations on record and associations
120
+ self.successful = [@record.keeping_errors { @record.valid? }, @record.associated_valid?].all?
121
+
122
+ unless successful?
123
+ # some associations such as habtm are saved before saved is called on parent object
124
+ # we have to revert these changes if validation fails
125
+ raise ActiveRecord::Rollback, "don't save habtm associations unless record is valid"
126
126
  end
127
- @record.errors.add(:base, as_(:record_not_saved)) if @record.errors.empty?
128
- self.successful = false
129
- rescue ActiveRecord::ActiveRecordError => ex
130
- flash[:error] = ex.message
131
- self.successful = false
127
+ @record.save! && @record.save_associated!
128
+ after_update_save(@record)
132
129
  end
130
+ rescue ActiveRecord::StaleObjectError
131
+ @record.errors.add(:base, as_(:version_inconsistency))
132
+ self.successful = false
133
+ rescue ActiveRecord::RecordNotSaved => exception
134
+ logger.warn do
135
+ "\n\n#{exception.class} (#{exception.message}):\n " +
136
+ Rails.backtrace_cleaner.clean(exception.backtrace).join("\n ") +
137
+ "\n\n"
138
+ end
139
+ @record.errors.add(:base, as_(:record_not_saved)) if @record.errors.empty?
140
+ self.successful = false
141
+ rescue ActiveRecord::ActiveRecordError => ex
142
+ flash[:error] = ex.message
143
+ self.successful = false
133
144
  end
134
145
 
135
146
  def do_update_column
@@ -139,25 +150,10 @@ module ActiveScaffold::Actions
139
150
  params.delete(:original_html)
140
151
  params.delete(:original_value)
141
152
  @column = active_scaffold_config.columns[column]
142
- @record = value_record = find_if_allowed(params[:id], :read)
143
- return unless @record.authorized_for?(:crud_type => :update, :column => column)
144
- if @column.delegated_association
145
- value_record = @record.send(@column.delegated_association.name)
146
- value_record ||= @record.association(@column.delegated_association.name).build
147
- return unless value_record.authorized_for?(:crud_type => :update, :column => column)
148
- end
149
-
150
- value ||=
151
- unless @column.column.nil? || @column.column.null
152
- default_val = @column.column.default
153
- default_val = ActiveScaffold::Core.column_type_cast default_val, @column.column if Rails.version >= '4.2.0'
154
- default_val == true ? false : default_val
155
- end
156
- unless @column.nil?
157
- value = column_value_from_param_value(value_record, @column, value)
158
- value = [] if value.nil? && @column.form_ui && @column.association.try(:collection?)
159
- end
153
+ value_record = record_for_update_column
154
+ return unless value_record
160
155
 
156
+ value = value_for_update_column(value, @column, value_record)
161
157
  value_record.send("#{@column.name}=", value)
162
158
  before_update_save(@record)
163
159
  self.successful = value_record.save
@@ -174,6 +170,29 @@ module ActiveScaffold::Actions
174
170
  after_update_save(@record)
175
171
  end
176
172
 
173
+ def record_for_update_column
174
+ @record = find_if_allowed(params[:id], :read)
175
+ return unless @record.authorized_for?(:crud_type => :update, :column => @column.name)
176
+
177
+ if @column.delegated_association
178
+ value_record = @record.send(@column.delegated_association.name)
179
+ value_record ||= @record.association(@column.delegated_association.name).build
180
+ value_record if value_record.authorized_for?(:crud_type => :update, :column => @column.name)
181
+ else
182
+ @record
183
+ end
184
+ end
185
+
186
+ def value_for_update_column(param_value, column, record)
187
+ unless param_value
188
+ param_value = ActiveScaffold::Core.column_type_cast @column.default_for_empty_value, @column.column
189
+ param_value = false if param_value == true
190
+ end
191
+ value = column_value_from_param_value(record, @column, param_value)
192
+ value = [] if value.nil? && @column.form_ui && @column.association&.collection?
193
+ value
194
+ end
195
+
177
196
  # override this method if you want to inject data in the record (or its associated objects) before the save
178
197
  def before_update_save(record); end
179
198
 
@@ -198,7 +217,7 @@ module ActiveScaffold::Actions
198
217
  private
199
218
 
200
219
  def update_authorized_filter
201
- link = active_scaffold_config.update.link || active_scaffold_config.update.class.link
220
+ link = active_scaffold_config.update.link || self.class.active_scaffold_config.update.class.link
202
221
  raise ActiveScaffold::ActionNotAllowed unless Array(send(link.security_method))[0]
203
222
  end
204
223