active_scaffold 3.4.43 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +39 -0
  3. data/{LICENSE → LICENSE.md} +1 -1
  4. data/README.md +27 -19
  5. data/app/assets/javascripts/active_scaffold.js.erb +1 -1
  6. data/app/assets/javascripts/jquery/active_scaffold.js +95 -43
  7. data/app/assets/javascripts/jquery/tiny_mce_bridge.js +30 -6
  8. data/app/assets/javascripts/prototype/tiny_mce_bridge.js +11 -1
  9. data/app/assets/stylesheets/active_scaffold_colors.scss +2 -2
  10. data/app/assets/stylesheets/active_scaffold_layout.css +36 -28
  11. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -3
  12. data/app/views/active_scaffold_overrides/_field_search.html.erb +8 -7
  13. data/app/views/active_scaffold_overrides/_form_association.html.erb +9 -9
  14. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +6 -6
  15. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +52 -50
  16. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  17. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
  18. data/app/views/active_scaffold_overrides/_human_conditions.html.erb +3 -1
  19. data/app/views/active_scaffold_overrides/_list_calculations.html.erb +1 -1
  20. data/app/views/active_scaffold_overrides/_list_column_headings.html.erb +2 -0
  21. data/app/views/active_scaffold_overrides/_list_messages.html.erb +5 -3
  22. data/app/views/active_scaffold_overrides/_list_record.html.erb +3 -1
  23. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +9 -9
  24. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -1
  25. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +18 -10
  26. data/app/views/active_scaffold_overrides/_render_field.js.erb +3 -3
  27. data/app/views/active_scaffold_overrides/_search.html.erb +7 -6
  28. data/app/views/active_scaffold_overrides/_show_actions.html.erb +14 -0
  29. data/app/views/active_scaffold_overrides/_show_association.html.erb +1 -1
  30. data/app/views/active_scaffold_overrides/_update_actions.html.erb +6 -2
  31. data/app/views/active_scaffold_overrides/_update_column.js.erb +1 -1
  32. data/app/views/active_scaffold_overrides/_update_form.html.erb +1 -1
  33. data/app/views/active_scaffold_overrides/destroy.js.erb +2 -3
  34. data/app/views/active_scaffold_overrides/edit_associated.js.erb +4 -3
  35. data/app/views/active_scaffold_overrides/on_action_update.js.erb +5 -3
  36. data/app/views/active_scaffold_overrides/on_create.js.erb +4 -4
  37. data/app/views/active_scaffold_overrides/on_update.js.erb +6 -6
  38. data/app/views/active_scaffold_overrides/show.html.erb +6 -0
  39. data/app/views/active_scaffold_overrides/update.html.erb +1 -1
  40. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  41. data/config/brakeman.ignore +26 -0
  42. data/config/brakeman.yml +3 -0
  43. data/config/i18n-tasks.yml +121 -0
  44. data/config/locales/de.yml +81 -70
  45. data/config/locales/en.yml +83 -74
  46. data/config/locales/es.yml +82 -73
  47. data/config/locales/fr.yml +86 -75
  48. data/config/locales/hu.yml +81 -70
  49. data/config/locales/ja.yml +71 -60
  50. data/config/locales/ru.yml +85 -74
  51. data/lib/active_scaffold.rb +3 -0
  52. data/lib/active_scaffold/actions/common_search.rb +11 -7
  53. data/lib/active_scaffold/actions/core.rb +119 -47
  54. data/lib/active_scaffold/actions/create.rb +1 -1
  55. data/lib/active_scaffold/actions/delete.rb +11 -8
  56. data/lib/active_scaffold/actions/field_search.rb +104 -6
  57. data/lib/active_scaffold/actions/list.rb +25 -21
  58. data/lib/active_scaffold/actions/mark.rb +12 -4
  59. data/lib/active_scaffold/actions/nested.rb +26 -26
  60. data/lib/active_scaffold/actions/search.rb +2 -2
  61. data/lib/active_scaffold/actions/show.rb +4 -5
  62. data/lib/active_scaffold/actions/subform.rb +9 -7
  63. data/lib/active_scaffold/actions/update.rb +20 -13
  64. data/lib/active_scaffold/active_record_permissions.rb +24 -5
  65. data/lib/active_scaffold/attribute_params.rb +68 -49
  66. data/lib/active_scaffold/bridges.rb +1 -1
  67. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +15 -19
  68. data/lib/active_scaffold/bridges/bitfields.rb +1 -1
  69. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +10 -14
  70. data/lib/active_scaffold/bridges/calendar_date_select.rb +0 -7
  71. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +19 -22
  72. data/lib/active_scaffold/bridges/cancan.rb +4 -3
  73. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +11 -21
  74. data/lib/active_scaffold/bridges/carrierwave.rb +2 -1
  75. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +2 -6
  76. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +6 -39
  77. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  78. data/lib/active_scaffold/bridges/chosen.rb +4 -1
  79. data/lib/active_scaffold/bridges/chosen/helpers.rb +3 -2
  80. data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +2 -2
  81. data/lib/active_scaffold/bridges/date_picker.rb +3 -0
  82. data/lib/active_scaffold/bridges/date_picker/ext.rb +43 -38
  83. data/lib/active_scaffold/bridges/date_picker/helper.rb +24 -23
  84. data/lib/active_scaffold/bridges/dragonfly.rb +1 -1
  85. data/lib/active_scaffold/bridges/dragonfly/dragonfly_bridge.rb +3 -7
  86. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -25
  87. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +2 -2
  88. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +6 -8
  89. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +1 -1
  90. data/lib/active_scaffold/bridges/file_column/form_ui.rb +0 -2
  91. data/lib/active_scaffold/bridges/file_column/list_ui.rb +2 -1
  92. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +1 -1
  93. data/lib/active_scaffold/bridges/paper_trail/actions.rb +1 -1
  94. data/lib/active_scaffold/bridges/paper_trail/helper.rb +1 -2
  95. data/lib/active_scaffold/bridges/paper_trail/paper_trail_bridge.rb +3 -7
  96. data/lib/active_scaffold/bridges/paperclip.rb +1 -1
  97. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -28
  98. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  99. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +3 -7
  100. data/lib/active_scaffold/bridges/record_select.rb +2 -0
  101. data/lib/active_scaffold/bridges/record_select/helpers.rb +14 -18
  102. data/lib/active_scaffold/bridges/semantic_attributes/column.rb +4 -8
  103. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -20
  104. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +7 -22
  105. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +14 -14
  106. data/lib/active_scaffold/config/base.rb +9 -6
  107. data/lib/active_scaffold/config/core.rb +30 -21
  108. data/lib/active_scaffold/config/create.rb +2 -1
  109. data/lib/active_scaffold/config/delete.rb +2 -2
  110. data/lib/active_scaffold/config/field_search.rb +9 -3
  111. data/lib/active_scaffold/config/form.rb +4 -4
  112. data/lib/active_scaffold/config/list.rb +27 -23
  113. data/lib/active_scaffold/config/nested.rb +4 -4
  114. data/lib/active_scaffold/config/search.rb +6 -6
  115. data/lib/active_scaffold/config/show.rb +11 -1
  116. data/lib/active_scaffold/config/subform.rb +1 -1
  117. data/lib/active_scaffold/config/update.rb +4 -2
  118. data/lib/active_scaffold/constraints.rb +39 -36
  119. data/lib/active_scaffold/core.rb +36 -15
  120. data/lib/active_scaffold/data_structures/action_columns.rb +14 -9
  121. data/lib/active_scaffold/data_structures/action_link.rb +4 -5
  122. data/lib/active_scaffold/data_structures/action_links.rb +5 -4
  123. data/lib/active_scaffold/data_structures/actions.rb +2 -2
  124. data/lib/active_scaffold/data_structures/association.rb +8 -0
  125. data/lib/active_scaffold/data_structures/association/abstract.rb +147 -0
  126. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +42 -0
  127. data/lib/active_scaffold/data_structures/association/active_record.rb +94 -0
  128. data/lib/active_scaffold/data_structures/association/mongoid.rb +45 -0
  129. data/lib/active_scaffold/data_structures/bridge.rb +3 -6
  130. data/lib/active_scaffold/data_structures/column.rb +100 -82
  131. data/lib/active_scaffold/data_structures/columns.rb +21 -3
  132. data/lib/active_scaffold/data_structures/nested_info.rb +22 -37
  133. data/lib/active_scaffold/data_structures/set.rb +4 -4
  134. data/lib/active_scaffold/data_structures/sorting.rb +29 -15
  135. data/lib/active_scaffold/engine.rb +3 -1
  136. data/lib/active_scaffold/extensions/action_controller_rendering.rb +10 -5
  137. data/lib/active_scaffold/extensions/action_view_rendering.rb +65 -59
  138. data/lib/active_scaffold/extensions/left_outer_joins.rb +48 -53
  139. data/lib/active_scaffold/extensions/localize.rb +3 -4
  140. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +7 -11
  141. data/lib/active_scaffold/extensions/paginator_extensions.rb +20 -18
  142. data/lib/active_scaffold/extensions/routing_mapper.rb +104 -40
  143. data/lib/active_scaffold/extensions/to_label.rb +1 -1
  144. data/lib/active_scaffold/extensions/unsaved_associated.rb +4 -13
  145. data/lib/active_scaffold/extensions/unsaved_record.rb +12 -1
  146. data/lib/active_scaffold/finder.rb +200 -134
  147. data/lib/active_scaffold/helpers/action_link_helpers.rb +398 -0
  148. data/lib/active_scaffold/helpers/association_helpers.rb +12 -30
  149. data/lib/active_scaffold/helpers/controller_helpers.rb +74 -24
  150. data/lib/active_scaffold/helpers/form_column_helpers.rb +205 -112
  151. data/lib/active_scaffold/helpers/human_condition_helpers.rb +21 -11
  152. data/lib/active_scaffold/helpers/id_helpers.rb +1 -1
  153. data/lib/active_scaffold/helpers/list_column_helpers.rb +117 -39
  154. data/lib/active_scaffold/helpers/pagination_helpers.rb +11 -14
  155. data/lib/active_scaffold/helpers/search_column_helpers.rb +69 -32
  156. data/lib/active_scaffold/helpers/show_column_helpers.rb +9 -3
  157. data/lib/active_scaffold/helpers/view_helpers.rb +41 -426
  158. data/lib/active_scaffold/orm_checks.rb +109 -0
  159. data/lib/active_scaffold/paginator.rb +1 -1
  160. data/lib/active_scaffold/responds_to_parent.rb +12 -10
  161. data/lib/active_scaffold/tableless.rb +81 -43
  162. data/lib/active_scaffold/version.rb +2 -2
  163. data/lib/generators/active_scaffold/controller_generator.rb +49 -0
  164. data/lib/generators/active_scaffold/install_generator.rb +45 -0
  165. data/lib/generators/active_scaffold/resource_generator.rb +56 -0
  166. data/lib/generators/{active_scaffold_controller/templates → templates}/controller.rb +0 -0
  167. data/lib/generators/{active_scaffold_controller/templates → templates}/helper.rb +0 -0
  168. data/shoulda_macros/macros.rb +3 -3
  169. data/test/active_scaffold_config_mock.rb +33 -0
  170. data/test/bridges/bridge_test.rb +9 -9
  171. data/test/bridges/date_picker_test.rb +3 -1
  172. data/test/bridges/paper_trail_test.rb +2 -3
  173. data/test/bridges/paperclip_test.rb +21 -10
  174. data/test/bridges/tiny_mce_test.rb +20 -21
  175. data/test/class_with_finder.rb +42 -0
  176. data/test/company.rb +6 -4
  177. data/test/config/core_test.rb +1 -1
  178. data/test/config/create_test.rb +1 -1
  179. data/test/config/list_test.rb +3 -3
  180. data/test/config/update_test.rb +3 -3
  181. data/test/data_structures/action_columns_test.rb +3 -3
  182. data/test/data_structures/association_column_test.rb +5 -5
  183. data/test/data_structures/column_test.rb +14 -14
  184. data/test/data_structures/columns_test.rb +2 -2
  185. data/test/data_structures/set_test.rb +2 -2
  186. data/test/data_structures/sorting_test.rb +6 -4
  187. data/test/extensions/active_record_test.rb +1 -1
  188. data/test/extensions/routing_mapper_test.rb +64 -13
  189. data/test/helpers/form_column_helpers_test.rb +6 -6
  190. data/test/helpers/list_column_helpers_test.rb +9 -5
  191. data/test/helpers/pagination_helpers_test.rb +1 -0
  192. data/test/misc/active_record_permissions_test.rb +18 -1
  193. data/test/misc/attribute_params_test.rb +26 -17
  194. data/test/misc/calculation_test.rb +8 -31
  195. data/test/misc/configurable_test.rb +3 -2
  196. data/test/misc/constraints_test.rb +33 -22
  197. data/test/misc/convert_numbers_format_test.rb +28 -10
  198. data/test/misc/finder_test.rb +6 -29
  199. data/test/misc/parse_datetime_test.rb +160 -0
  200. data/test/misc/render_test.rb +1 -1
  201. data/test/misc/tableless_test.rb +24 -0
  202. data/test/mock_app/app/models/building.rb +2 -1
  203. data/test/mock_app/config.ru +1 -1
  204. data/test/mock_app/config/environments/test.rb +1 -1
  205. data/test/mock_app/config/routes.rb +11 -3
  206. data/test/model_stub.rb +11 -6
  207. data/test/run_all.rb +1 -1
  208. data/test/test_helper.rb +19 -4
  209. metadata +42 -23
  210. data/lib/active_scaffold/data_structures/error_message.rb +0 -22
  211. data/lib/active_scaffold/extensions/reverse_associations.rb +0 -119
  212. data/lib/generators/active_scaffold/USAGE +0 -29
  213. data/lib/generators/active_scaffold/active_scaffold_generator.rb +0 -21
  214. data/lib/generators/active_scaffold_controller/USAGE +0 -19
  215. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +0 -29
  216. data/test/data_structures/error_message_test.rb +0 -25
@@ -2,7 +2,15 @@ module ActiveScaffold
2
2
  module Helpers
3
3
  module ControllerHelpers
4
4
  def self.included(controller)
5
- controller.class_eval { helper_method :params_for, :conditions_from_params, :main_path_to_return, :render_parent?, :render_parent_options, :render_parent_action, :nested_singular_association?, :build_associated, :generate_temporary_id, :generated_id }
5
+ if controller.respond_to? :helper_method
6
+ controller.class_eval do
7
+ helper_method :params_for, :conditions_from_params, :render_parent?,
8
+ :main_path_to_return, :render_parent_options,
9
+ :render_parent_action, :nested_singular_association?,
10
+ :main_form_controller, :build_associated,
11
+ :generate_temporary_id, :generated_id
12
+ end
13
+ end
6
14
  end
7
15
 
8
16
  include ActiveScaffold::Helpers::IdHelpers
@@ -19,7 +27,7 @@ module ActiveScaffold
19
27
 
20
28
  # These params should not propagate:
21
29
  # :adapter and :position are one-use rendering arguments.
22
- # :sort, :sort_direction, and :page are arguments that stored in the session.
30
+ # :sort, :sort_direction, and :page are arguments that stored in the session, if store_user_settings is enabled
23
31
  # and wow. no we don't want to propagate :record.
24
32
  # :commit is a special rails variable for form buttons
25
33
  # :_method is a special rails variable to simulate put, patch and delete actions.
@@ -28,16 +36,52 @@ module ActiveScaffold
28
36
  # :iframe is used to simulate ajax forms loading form in iframe.
29
37
  # :associated_id used in add_existing
30
38
  # :authenticity_token is sent on some ajax requests
31
- BLACKLIST_PARAMS = [:adapter, :position, :sort, :sort_direction, :page, :record, :commit, :_method, :dont_close, :auto_pagination, :iframe, :associated_id, :authenticity_token].freeze
39
+ # :_added is sent on checkbox-list with update_columns
40
+ # :_removed is sent on checkbox-list with update_columns
41
+ # :_popstate sent when loading previous page from history, after using history.pushState
42
+ # :_ jQuery param added for GET requests with cache disabled
43
+ BLACKLIST_PARAMS = %i[adapter position sort sort_direction page record commit _method dont_close auto_pagination
44
+ iframe associated_id authenticity_token _added _removed _popstate _].freeze
32
45
 
33
46
  def params_for(options = {})
34
47
  unless @params_for
35
48
  @params_for = {}
36
- params.except(*BLACKLIST_PARAMS).each { |key, value| @params_for[key.to_sym] = value.duplicable? ? value.clone : value }
49
+ params.except(*BLACKLIST_PARAMS).each do |key, value|
50
+ @params_for[key.to_sym] = copy_param(value)
51
+ end
37
52
  @params_for[:controller] = '/' + @params_for[:controller].to_s unless @params_for[:controller].to_s.first(1) == '/' # for namespaced controllers
38
53
  @params_for.delete(:id) if @params_for[:id].nil?
39
54
  end
40
- @params_for.merge(options)
55
+
56
+ url_options = @params_for.merge(options)
57
+ if !active_scaffold_config.store_user_settings && controller_requested(url_options[:controller]) == controller_path
58
+ url_options[:search] ||= copy_param search_params if respond_to?(:search_params, true) && search_params.present?
59
+ url_options[:page] ||= params[:page]
60
+ if active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.user.user_sorting?
61
+ column, direction = active_scaffold_config.list.user.sorting.first
62
+ url_options[:sort] ||= column.name
63
+ url_options[:sort_direction] ||= direction
64
+ end
65
+ end
66
+ url_options
67
+ end
68
+
69
+ def controller_requested(controller)
70
+ if controller.to_s.first(1) == '/'
71
+ controller[1..-1]
72
+ else
73
+ path = controller_path.split('/')[0..-2]
74
+ path << controller
75
+ path.join('/')
76
+ end
77
+ end
78
+
79
+ def copy_param(value)
80
+ if controller_params? value
81
+ params_hash value
82
+ else
83
+ value.duplicable? ? value.clone : value
84
+ end
41
85
  end
42
86
 
43
87
  # Parameters to generate url to the main page (override if the ActiveScaffold is used as a component on another controllers page)
@@ -45,7 +89,7 @@ module ActiveScaffold
45
89
  if params[:return_to]
46
90
  params[:return_to]
47
91
  else
48
- exclude_parameters = [:utf8, :associated_id]
92
+ exclude_parameters = %i[utf8 associated_id]
49
93
  parameters = {}
50
94
  if params[:parent_scaffold] && nested? && nested.singular_association?
51
95
  parameters[:controller] = params[:parent_scaffold]
@@ -67,6 +111,10 @@ module ActiveScaffold
67
111
  nested? && (nested.belongs_to? || nested.has_one?)
68
112
  end
69
113
 
114
+ def main_form_controller
115
+ parent_controller_name.constantize if params[:parent_controller]
116
+ end
117
+
70
118
  def render_parent?
71
119
  nested_singular_association? || params[:parent_sti]
72
120
  end
@@ -74,24 +122,21 @@ module ActiveScaffold
74
122
  def render_parent_options
75
123
  if nested_singular_association?
76
124
  {:controller => nested.parent_scaffold.controller_path, :action => :index, :id => nested.parent_id}
77
- elsif params[:parent_sti]
78
- options = params_for(:controller => params[:parent_sti], :action => render_parent_action, :parent_sti => nil)
79
- options.merge(:action => :index, :id => @record.to_param) if render_parent_action == :row
125
+ elsif parent_sti_controller
126
+ options = params_for(:controller => parent_sti_controller.controller_path, :action => render_parent_action, :parent_sti => nil)
127
+ options.merge!(:action => :index, :id => @record.to_param) if render_parent_action == :row
128
+ options
80
129
  end
81
130
  end
82
131
 
83
132
  def render_parent_action
84
133
  if @parent_action.nil?
85
- begin
86
- @parent_action = :row
87
- if params[:parent_sti]
88
- parent_controller = "#{params[:parent_sti].to_s.camelize}Controller".constantize
89
- @parent_action = :index if action_name == 'create' && parent_controller.active_scaffold_config.actions.include?(:create) && parent_controller.active_scaffold_config.create.refresh_list == true
90
- @parent_action = :index if action_name == 'update' && parent_controller.active_scaffold_config.actions.include?(:update) && parent_controller.active_scaffold_config.update.refresh_list == true
91
- @parent_action = :index if action_name == 'destroy' && parent_controller.active_scaffold_config.actions.include?(:delete) && parent_controller.active_scaffold_config.delete.refresh_list == true
92
- end
93
- rescue ActiveScaffold::ControllerNotFound => ex
94
- logger.warn "#{ex.message} for parent_sti #{params[:parent_sti]}"
134
+ @parent_action = :row
135
+ if parent_sti_controller
136
+ parent_sti_config = parent_sti_controller.active_scaffold_config
137
+ @parent_action = :index if action_name == 'create' && parent_sti_config.actions.include?(:create) && parent_sti_config.create.refresh_list == true
138
+ @parent_action = :index if action_name == 'update' && parent_sti_config.actions.include?(:update) && parent_sti_config.update.refresh_list == true
139
+ @parent_action = :index if action_name == 'destroy' && parent_sti_config.actions.include?(:delete) && parent_sti_config.delete.refresh_list == true
95
140
  end
96
141
  end
97
142
  @parent_action
@@ -99,12 +144,17 @@ module ActiveScaffold
99
144
 
100
145
  # build an associated record for association
101
146
  def build_associated(association, parent_record)
102
- if association.options[:through]
147
+ if association.through? && association.through_reflection.collection?
103
148
  # build full chain, only check create_associated on initial parent_record
104
- parent_record = build_associated(association.through_reflection, parent_record)
105
- build_associated(association.source_reflection, parent_record).tap do |record|
106
- save_record_to_association(record, association.source_reflection.reverse, parent_record) # set inverse
149
+ parent_record = build_associated(association.class.new(association.through_reflection), parent_record)
150
+ source_assoc = association.class.new(association.source_reflection)
151
+ build_associated(source_assoc, parent_record).tap do |record|
152
+ save_record_to_association(record, source_assoc.reverse_association, parent_record) # set inverse
107
153
  end
154
+ elsif association.through? # through belongs_to/has_one
155
+ parent_record = parent_record.send(association.through_reflection.name)
156
+ source_assoc = association.class.new(association.source_reflection)
157
+ build_associated(source_assoc, parent_record)
108
158
  elsif association.collection?
109
159
  parent_record.send(association.name).build
110
160
  elsif association.belongs_to? || parent_record.new_record? || parent_record.send(association.name).nil?
@@ -113,7 +163,7 @@ module ActiveScaffold
113
163
  parent_record.send("build_#{association.name}")
114
164
  else
115
165
  association.klass.new.tap do |record|
116
- save_record_to_association(record, association.reverse, parent_record) # set inverse
166
+ save_record_to_association(record, association.reverse_association, parent_record) # set inverse
117
167
  end
118
168
  end
119
169
  end
@@ -12,8 +12,6 @@ module ActiveScaffold
12
12
 
13
13
  def active_scaffold_render_input(column, options)
14
14
  record = options[:object]
15
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
16
- record ||= @record # TODO: Remove when relying on @record is removed
17
15
 
18
16
  # first, check if the dev has created an override for this specific field
19
17
  if (method = override_form_field(column))
@@ -42,15 +40,14 @@ module ActiveScaffold
42
40
  # final ultimate fallback: use rails' generic input method
43
41
  else
44
42
  # for textual fields we pass different options
45
- text_types = [:text, :string, :integer, :float, :decimal, :date, :time, :datetime]
43
+ text_types = %i[text string integer float decimal]
46
44
  options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
47
45
  if column.column.type == :string && options[:maxlength].blank?
48
46
  options[:maxlength] = column.column.limit
49
47
  options[:size] ||= options[:maxlength].to_i > 30 ? 30 : options[:maxlength]
50
48
  end
51
- options[:include_blank] = true if column.column.null && [:date, :datetime, :time].include?(column.column.type)
52
49
  options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
53
- text_field(:record, column.name, options.merge(column.options))
50
+ text_field(:record, column.name, options.merge(column.options).except(:format))
54
51
  end
55
52
  end
56
53
  end
@@ -60,8 +57,6 @@ module ActiveScaffold
60
57
  end
61
58
 
62
59
  def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil)
63
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, call with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
64
- record ||= @record # TODO: Remove when relying on @record is removed
65
60
  if add_class
66
61
  col_class = []
67
62
  col_class << 'required' if column.required?
@@ -120,22 +115,24 @@ module ActiveScaffold
120
115
  def current_form_columns(record, scope, subform_controller = nil)
121
116
  if scope
122
117
  subform_controller.active_scaffold_config.subform.columns.names
123
- elsif [:new, :create, :edit, :update, :render_field].include? action_name.to_sym
118
+ elsif %i[new create edit update render_field].include? action_name.to_sym
119
+ # disable update_columns for inplace_edit (GET render_field)
120
+ return if action_name == 'render_field' && request.get?
124
121
  active_scaffold_config.send(record.new_record? ? :create : :update).columns.names
125
122
  end
126
123
  end
127
124
 
128
125
  def update_columns_options(column, scope, options, force = false)
129
126
  record = options[:object]
130
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
131
- record ||= @record # TODO: Remove when relying on @record is removed
132
127
  subform_controller = controller.class.active_scaffold_controller_for(record.class) if scope
133
128
  form_columns = @main_columns.try(:names) if scope.nil? || subform_controller == controller.class
134
129
  form_columns ||= current_form_columns(record, scope, subform_controller)
135
130
  if force || (form_columns && column.update_columns && (column.update_columns & form_columns).present?)
136
131
  url_params = params_for(:action => 'render_field', :column => column.name, :id => record.to_param)
137
- url_params = url_params.except(:parent_scaffold, :association, nested.param_name) if nested? && scope
138
- url_params[:eid] = params[:eid] if params[:eid]
132
+ if nested? && scope
133
+ url_params[:nested] = url_params.slice(:parent_scaffold, :association, nested.param_name)
134
+ url_params = url_params.except(:parent_scaffold, :association, nested.param_name)
135
+ end
139
136
  if scope
140
137
  url_params[:parent_controller] ||= url_params[:controller].gsub(/^\//, '')
141
138
  url_params[:controller] = subform_controller.controller_path
@@ -144,7 +141,7 @@ module ActiveScaffold
144
141
  end
145
142
 
146
143
  options[:class] = "#{options[:class]} update_form".strip
147
- options['data-update_url'] = url_for(url_params.merge(:_added => nil, :_removed => nil))
144
+ options['data-update_url'] = url_for(url_params)
148
145
  options['data-update_send_form'] = column.send_form_on_update_column
149
146
  options['data-update_send_form_selector'] = column.options[:send_form_selector] if column.options[:send_form_selector]
150
147
  end
@@ -156,8 +153,8 @@ module ActiveScaffold
156
153
  end
157
154
 
158
155
  def render_column(column, record, renders_as, scope = nil, only_value = false, col_class = nil)
159
- if override_form_field_partial?(column)
160
- render :partial => override_form_field_partial(column), :locals => {:column => column, :only_value => only_value, :scope => scope, :col_class => col_class, :record => record}
156
+ if partial = override_form_field_partial(column)
157
+ render :partial => partial, :locals => {:column => column, :only_value => only_value, :scope => scope, :col_class => col_class, :record => record}
161
158
  elsif renders_as == :field || override_form_field?(column)
162
159
  form_attribute(column, record, scope, only_value, col_class)
163
160
  elsif renders_as == :subform
@@ -171,13 +168,17 @@ module ActiveScaffold
171
168
  column_options = active_scaffold_input_options(column, scope, :object => record)
172
169
  attributes = field_attributes(column, record)
173
170
  attributes[:class] = "#{attributes[:class]} #{col_class}" if col_class.present?
174
- field =
175
- if only_value
176
- content_tag(:span, get_column_value(record, column), column_options.except(:name, :object)) <<
177
- hidden_field(:record, column.association ? column.association.foreign_key : column.name, column_options)
178
- else
179
- active_scaffold_input_for column, scope, column_options
171
+ if only_value
172
+ field = content_tag(:span, get_column_value(record, column), column_options.except(:name, :object))
173
+ if column.association.nil? || column.association.belongs_to?
174
+ # hidden field probably not needed, but leaving it just in case
175
+ # but it isn't working for assocations which are not belongs_to
176
+ method = column.association ? column.association.foreign_key : column.name
177
+ field << hidden_field(:record, method, column_options)
180
178
  end
179
+ else
180
+ field = active_scaffold_input_for column, scope, column_options
181
+ end
181
182
 
182
183
  content_tag :dl, attributes do
183
184
  %(<dt>#{label_tag label_for(column, column_options), column.label}</dt><dd>#{field}
@@ -188,7 +189,7 @@ module ActiveScaffold
188
189
  end
189
190
 
190
191
  def label_for(column, options)
191
- options[:id] unless column.form_ui == :select && column.plural_association?
192
+ options[:id] unless column.form_ui == :select && column.association.try(:collection?)
192
193
  end
193
194
 
194
195
  def subform_label(column, hidden)
@@ -196,33 +197,60 @@ module ActiveScaffold
196
197
  end
197
198
 
198
199
  def form_hidden_attribute(column, record, scope = nil)
199
- %(<dl style="display: none;"><dt></dt><dd>
200
- #{hidden_field :record, column.name, active_scaffold_input_options(column, scope).merge(:object => record)}
201
- </dd></dl>).html_safe
200
+ content_tag :dl, style: 'display: none' do
201
+ content_tag(:dt, '') <<
202
+ content_tag(:dd, form_hidden_field(column, record, scope))
203
+ end
204
+ end
205
+
206
+ def form_hidden_field(column, record, scope)
207
+ options = active_scaffold_input_options(column, scope)
208
+ if column.association.try(:collection?)
209
+ associated = record.send(column.name)
210
+ if associated.blank?
211
+ hidden_field_tag options[:name], '', options
212
+ else
213
+ options[:name] += '[]'
214
+ fields = associated.map do |r|
215
+ hidden_field_tag options[:name], r.id, options.merge(id: options[:id] + "_#{r.id}")
216
+ end
217
+ safe_join fields, ''
218
+ end
219
+ else
220
+ hidden_field :record, column.name, options.merge(object: record)
221
+ end
202
222
  end
203
223
 
204
224
  # Should this column be displayed in the subform?
205
- def in_subform?(column, parent_record)
225
+ def in_subform?(column, parent_record, parent_column)
206
226
  return true unless column.association
207
227
 
208
- # Polymorphic associations can't appear because they *might* be the reverse association, and because you generally don't assign an association from the polymorphic side ... I think.
209
- return false if column.polymorphic_association?
228
+ if column.association.reverse.nil?
229
+ # Polymorphic associations can't appear because they *might* be the reverse association
230
+ return false if column.association.polymorphic?
210
231
 
211
- # A column shouldn't be in the subform if it's the reverse association to the parent
212
- return false if column.association.inverse_for?(parent_record.class)
213
-
214
- true
232
+ # A column shouldn't be in the subform if it's the reverse association to the parent
233
+ !column.association.inverse_for?(parent_record.class)
234
+ elsif column.association.reverse == parent_column.name
235
+ if column.association.polymorphic?
236
+ column.association.name != parent_column.association.as
237
+ else
238
+ !column.association.inverse_for?(parent_record.class)
239
+ end
240
+ else
241
+ true
242
+ end
215
243
  end
216
244
 
217
245
  def column_show_add_existing(column, record = nil)
218
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, call with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
219
- record ||= @record # TODO: Remove when relying on @record is removed
220
- (column.allow_add_existing && options_for_association_count(column.association, record) > 0)
246
+ column.allow_add_existing && options_for_association_count(column.association, record) > 0
221
247
  end
222
248
 
223
249
  def column_show_add_new(column, associated, record)
224
- value = (column.plural_association? && !column.readonly_association?) || column.singular_association?
225
- value &&= false unless column.association.klass.authorized_for?(:crud_type => :create)
250
+ assoc = column.association
251
+ value = assoc.singular?
252
+ value ||= assoc.collection? && !assoc.readonly? && (!assoc.through? || !assoc.through_reflection.collection?)
253
+ value &&= false unless assoc.klass.authorized_for?(:crud_type => :create)
226
254
  value
227
255
  end
228
256
 
@@ -245,21 +273,25 @@ module ActiveScaffold
245
273
  options
246
274
  end
247
275
 
248
- def active_scaffold_input_singular_association(column, html_options)
276
+ def active_scaffold_select_name_with_multiple(options)
277
+ if options[:multiple] && !options[:name].to_s.ends_with?('[]')
278
+ options[:name] = "#{options[:name]}[]"
279
+ end
280
+ end
281
+
282
+ def active_scaffold_input_singular_association(column, html_options, options = {})
249
283
  record = html_options.delete(:object)
250
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in html_options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
251
- record ||= @record # TODO: Remove when relying on @record is removed
252
284
  associated = record.send(column.association.name)
253
285
 
254
286
  select_options = sorted_association_options_find(column.association, nil, record)
255
287
  select_options.unshift(associated) unless associated.nil? || select_options.include?(associated)
256
288
 
257
289
  method = column.name
258
- options = {:selected => associated.try(:id), :include_blank => as_(:_select_), :object => record}
290
+ options.merge! :selected => associated.try(:id), :include_blank => as_(:_select_), :object => record
259
291
 
260
292
  html_options.merge!(column.options[:html_options] || {})
261
293
  options.merge!(column.options)
262
- html_options[:name] = "#{html_options[:name]}[]" if html_options[:multiple] == true && !html_options[:name].to_s.ends_with?('[]')
294
+ active_scaffold_select_name_with_multiple html_options
263
295
  active_scaffold_translate_select_options(options)
264
296
 
265
297
  html =
@@ -272,6 +304,39 @@ module ActiveScaffold
272
304
  html
273
305
  end
274
306
 
307
+ def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, &block)
308
+ options = active_scaffold_input_text_options(options.merge(column.options))
309
+ if content
310
+ active_scaffold_file_with_content(column, content, options, remove_file_prefix, controls_class, &block)
311
+ else
312
+ file_field(:record, column.name, options)
313
+ end
314
+ end
315
+
316
+ def active_scaffold_file_with_content(column, content, options, remove_file_prefix, controls_class)
317
+ required = options.delete(:required)
318
+ case ActiveScaffold.js_framework
319
+ when :jquery
320
+ js_remove_file_code = "jQuery(this).prev().val('true'); jQuery(this).parent().hide().next().show()#{".find('input').attr('required', 'required')" if required}; return false;"
321
+ js_dont_remove_file_code = "jQuery(this).parents('div.#{controls_class}').find('input.remove_file').val('false'); return false;"
322
+ when :prototype
323
+ js_remove_file_code = "$(this).previous().value='true'; $(this).up().hide().next().show()#{".down().writeAttribute('required', 'required')" if required}; return false;"
324
+ js_dont_remove_file_code = "jQuery(this).parents('div.#{controls_class}').find('input.remove_file').val('false'); return false;"
325
+ end
326
+
327
+ object_name, method = options[:name].split(/\[(#{column.name})\]/)
328
+ method.sub!(/#{column.name}/, "#{remove_file_prefix}\\0")
329
+ fields = block_given? ? yield : ''
330
+ input = file_field(:record, column.name, options.merge(:onchange => js_dont_remove_file_code))
331
+ content_tag(:div, class: controls_class) do
332
+ content_tag(:div) do
333
+ safe_join [content, ' | ', fields,
334
+ hidden_field(object_name, method, :value => 'false', class: 'remove_file'),
335
+ content_tag(:a, as_(:remove_file), :href => '#', :onclick => js_remove_file_code)]
336
+ end << content_tag(:div, input, :style => 'display: none')
337
+ end
338
+ end
339
+
275
340
  def active_scaffold_refresh_link(column, html_options, record)
276
341
  link_options = {:object => record}
277
342
  if html_options['data-update_url']
@@ -286,16 +351,12 @@ module ActiveScaffold
286
351
  end
287
352
 
288
353
  def active_scaffold_plural_association_options(column, record = nil)
289
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, call with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
290
- record ||= @record # TODO: Remove when relying on @record is removed
291
354
  associated_options = record.send(column.association.name)
292
355
  [associated_options, associated_options | sorted_association_options_find(column.association, nil, record)]
293
356
  end
294
357
 
295
358
  def active_scaffold_input_plural_association(column, options)
296
359
  record = options.delete(:object)
297
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
298
- record ||= @record # TODO: Remove when relying on @record is removed
299
360
  associated_options, select_options = active_scaffold_plural_association_options(column, record)
300
361
 
301
362
  html =
@@ -339,31 +400,45 @@ module ActiveScaffold
339
400
  column.options[:options]
340
401
  end
341
402
 
342
- def active_scaffold_input_enum(column, html_options)
403
+ def active_scaffold_input_enum(column, html_options, options = {})
343
404
  record = html_options.delete(:object)
344
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in html_options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
345
- record ||= @record # TODO: Remove when relying on @record is removed
346
- options = {:selected => record.send(column.name), :object => record}
405
+ options[:selected] = record.send(column.name)
406
+ options[:object] = record
347
407
  options_for_select = active_scaffold_enum_options(column, record).collect do |text, value|
348
408
  active_scaffold_translated_option(column, text, value)
349
409
  end
350
410
  html_options.merge!(column.options[:html_options] || {})
351
411
  options.merge!(column.options)
352
- html_options[:name] = "#{html_options[:name]}[]" if html_options[:multiple] == true && !html_options[:name].to_s.ends_with?('[]')
412
+ active_scaffold_select_name_with_multiple html_options
353
413
  active_scaffold_translate_select_options(options)
354
414
  select(:record, column.name, options_for_select, options, html_options)
355
415
  end
356
416
 
357
417
  def active_scaffold_input_select(column, html_options)
358
- if column.singular_association?
418
+ if column.association.try :singular?
359
419
  active_scaffold_input_singular_association(column, html_options)
360
- elsif column.plural_association?
420
+ elsif column.association.try :collection?
361
421
  active_scaffold_input_plural_association(column, html_options)
362
422
  else
363
423
  active_scaffold_input_enum(column, html_options)
364
424
  end
365
425
  end
366
426
 
427
+ def active_scaffold_radio_option(option, selected, column, radio_options)
428
+ if column.association
429
+ label_method = column.options[:label_method] || :to_label
430
+ text, value = [option.send(label_method), option.id]
431
+ checked = {:checked => selected == value}
432
+ else
433
+ text, value = active_scaffold_translated_option(column, *option)
434
+ end
435
+
436
+ id_key = radio_options[:"data-id"] ? :"data-id" : :id
437
+ radio_options = radio_options.merge(id_key => radio_options[id_key] + '-' + value.to_s.parameterize)
438
+ radio_options.merge!(checked) if checked
439
+ content_tag(:label, radio_button(:record, column.name, value, radio_options) + text)
440
+ end
441
+
367
442
  def active_scaffold_input_radio(column, html_options)
368
443
  record = html_options[:object]
369
444
  html_options.merge!(column.options[:html_options] || {})
@@ -373,21 +448,12 @@ module ActiveScaffold
373
448
  else
374
449
  active_scaffold_enum_options(column, record)
375
450
  end
376
- id_key = html_options[:"data-id"] ? :"data-id" : :id
377
- label_method = column.options[:label_method] || :to_label if column.association
378
451
 
379
- options.each_with_object('') do |(text, value), html|
380
- if column.association
381
- text, value = [text.send(label_method), text.id]
382
- checked = {:checked => html_options[:object].send(column.association.name).try(:id) == value}
383
- else
384
- text, value = active_scaffold_translated_option(column, text, value)
385
- end
386
-
387
- radio_options = html_options.merge(id_key => html_options[id_key] + '-' + value.to_s.parameterize)
388
- radio_options.merge!(checked) if checked
389
- html << content_tag(:label, radio_button(:record, column.name, value, radio_options) + text)
390
- end.html_safe
452
+ selected = record.send(column.association.name).try(:id) if column.association
453
+ radios = options.map do |option|
454
+ active_scaffold_radio_option(option, selected, column, html_options)
455
+ end
456
+ safe_join radios
391
457
  end
392
458
 
393
459
  def active_scaffold_input_checkbox(column, options)
@@ -395,8 +461,7 @@ module ActiveScaffold
395
461
  end
396
462
 
397
463
  def active_scaffold_input_password(column, options)
398
- options = active_scaffold_input_text_options(options)
399
- password_field :record, column.name, options.merge(column.options)
464
+ active_scaffold_text_input :password_field, column, options
400
465
  end
401
466
 
402
467
  def active_scaffold_input_textarea(column, options)
@@ -404,8 +469,7 @@ module ActiveScaffold
404
469
  end
405
470
 
406
471
  def active_scaffold_input_virtual(column, options)
407
- options = active_scaffold_input_text_options(options)
408
- text_field :record, column.name, options.merge(column.options)
472
+ active_scaffold_text_input :text_field, column, options
409
473
  end
410
474
 
411
475
  # Some fields from HTML5 (primarily for using in-browser validation)
@@ -413,34 +477,54 @@ module ActiveScaffold
413
477
 
414
478
  # A text box, that accepts only valid email address (in-browser validation)
415
479
  def active_scaffold_input_email(column, options)
416
- options = active_scaffold_input_text_options(options)
417
- email_field :record, column.name, options.merge(column.options)
480
+ active_scaffold_text_input :email_field, column, options
418
481
  end
419
482
 
420
483
  # A text box, that accepts only valid URI (in-browser validation)
421
484
  def active_scaffold_input_url(column, options)
422
- options = active_scaffold_input_text_options(options)
423
- url_field :record, column.name, options.merge(column.options)
485
+ active_scaffold_text_input :url_field, column, options
424
486
  end
425
487
 
426
488
  # A text box, that accepts only valid phone-number (in-browser validation)
427
489
  def active_scaffold_input_telephone(column, options)
428
- options = active_scaffold_input_text_options(options)
429
- telephone_field :record, column.name, options.merge(column.options)
490
+ active_scaffold_text_input :telephone_field, column, options, :format
430
491
  end
431
492
 
432
493
  # A spinbox control for number values (in-browser validation)
433
494
  def active_scaffold_input_number(column, options)
434
- options = numerical_constraints_for_column(column, options)
435
- options = active_scaffold_input_text_options(options)
436
- number_field :record, column.name, options.merge(column.options)
495
+ active_scaffold_number_input :number_field, column, options, :format
437
496
  end
438
497
 
439
498
  # A slider control for number values (in-browser validation)
440
499
  def active_scaffold_input_range(column, options)
500
+ active_scaffold_number_input :range_field, column, options, :format
501
+ end
502
+
503
+ # A slider control for number values (in-browser validation)
504
+ def active_scaffold_number_input(method, column, options, remove_options = nil)
441
505
  options = numerical_constraints_for_column(column, options)
506
+ active_scaffold_text_input method, column, options, remove_options
507
+ end
508
+
509
+ def active_scaffold_text_input(method, column, options, remove_options = nil)
442
510
  options = active_scaffold_input_text_options(options)
443
- range_field :record, column.name, options.merge(column.options)
511
+ options = options.merge(column.options)
512
+ options = options.except(*remove_options) if remove_options.present?
513
+ send method, :record, column.name, options
514
+ end
515
+
516
+ # A color picker
517
+ def active_scaffold_input_color(column, options)
518
+ options = active_scaffold_input_text_options(options)
519
+ if column.column.try(:null)
520
+ no_color = options[:object].send(column.name).nil?
521
+ method = no_color ? :hidden_field : :color_field
522
+ html = content_tag(:label, check_box_tag('disable', '1', no_color, id: nil, name: nil, class: 'no-color') << " #{as_ column.options[:no_color] || :no_color}")
523
+ else
524
+ method = :color_field
525
+ html = ''.html_safe
526
+ end
527
+ html << send(method, :record, column.name, options.merge(column.options).except(:format, :no_color))
444
528
  end
445
529
 
446
530
  #
@@ -449,8 +533,6 @@ module ActiveScaffold
449
533
 
450
534
  def active_scaffold_input_boolean(column, options)
451
535
  record = options.delete(:object)
452
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
453
- record ||= @record # TODO: Remove when relying on @record is removed
454
536
  select_options = []
455
537
  select_options << [as_(:_select_), nil] if !column.virtual? && column.column.null
456
538
  select_options << [as_(:true), true]
@@ -459,51 +541,65 @@ module ActiveScaffold
459
541
  select_tag(options[:name], options_for_select(select_options, record.send(column.name)), options)
460
542
  end
461
543
 
462
- def onsubmit
544
+ def active_scaffold_input_date(column, options)
545
+ active_scaffold_text_input :date_field, column, options
546
+ end
547
+
548
+ def active_scaffold_input_time(column, options)
549
+ active_scaffold_text_input :time_field, column, options
550
+ end
551
+
552
+ def active_scaffold_input_datetime(column, options)
553
+ active_scaffold_text_input :datetime_local_field, column, options
554
+ end
555
+
556
+ def active_scaffold_input_month(column, options)
557
+ active_scaffold_text_input :month_field, column, options
558
+ end
559
+
560
+ def active_scaffold_input_week(column, options)
561
+ active_scaffold_text_input :week_field, column, options
463
562
  end
464
563
 
465
564
  ##
466
565
  ## Form column override signatures
467
566
  ##
468
567
 
469
- # add functionality for overriding subform partials from association class path
470
- def override_subform_partial?(column, subform_partial)
471
- template_exists?(override_subform_partial(column, subform_partial), true)
568
+ def partial_for_model(model, partial)
569
+ controller = active_scaffold_controller_for(model)
570
+ while controller.uses_active_scaffold?
571
+ path = File.join(controller.controller_path, partial)
572
+ return path if template_exists?(path, true)
573
+ controller = controller.superclass
574
+ end
575
+ nil
472
576
  end
473
577
 
578
+ # add functionality for overriding subform partials from association class path
474
579
  def override_subform_partial(column, subform_partial)
475
- File.join(active_scaffold_controller_for(column.association.klass).controller_path, subform_partial) if column_renders_as(column) == :subform
476
- end
477
-
478
- def override_form_field_partial?(column)
479
- template_exists?(override_form_field_partial(column), true)
580
+ partial_for_model(column.association.klass, subform_partial) if column_renders_as(column) == :subform
480
581
  end
481
582
 
482
583
  # the naming convention for overriding form fields with helpers
483
584
  def override_form_field_partial(column)
484
- path = active_scaffold_controller_for(column.active_record_class).controller_path
485
- File.join(path, "#{clean_column_name(column.name)}_form_column")
585
+ partial_for_model(column.active_record_class, "#{clean_column_name(column.name)}_form_column")
486
586
  end
487
587
 
488
588
  def override_form_field(column)
489
589
  override_helper column, 'form_column'
490
590
  end
491
- alias_method :override_form_field?, :override_form_field
591
+ alias override_form_field? override_form_field
492
592
 
493
593
  # the naming convention for overriding form input types with helpers
494
594
  def override_input(form_ui)
495
595
  method = "active_scaffold_input_#{form_ui}"
496
596
  method if respond_to? method
497
597
  end
498
- alias_method :override_input?, :override_input
598
+ alias override_input? override_input
499
599
 
500
600
  def subform_partial_for_column(column)
501
601
  subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
502
- if override_subform_partial?(column, subform_partial)
503
- override_subform_partial(column, subform_partial)
504
- else
505
- subform_partial
506
- end
602
+ override_subform_partial(column, subform_partial) || subform_partial
507
603
  end
508
604
 
509
605
  ##
@@ -512,19 +608,18 @@ module ActiveScaffold
512
608
 
513
609
  def column_renders_as(column)
514
610
  if column.respond_to? :each
515
- return :subsection
611
+ :subsection
516
612
  elsif column.active_record_class.locking_column.to_s == column.name.to_s || column.form_ui == :hidden
517
- return :hidden
613
+ :hidden
518
614
  elsif column.association.nil? || column.form_ui || !active_scaffold_config_for(column.association.klass).actions.include?(:subform) || override_form_field?(column)
519
- return :field
615
+ :field
520
616
  else
521
- return :subform
617
+ :subform
522
618
  end
523
619
  end
524
620
 
525
621
  def column_scope(column, scope = nil, record = nil)
526
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, call with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
527
- if column.plural_association?
622
+ if column.association.try(:collection?)
528
623
  "#{scope}[#{column.name}][#{record.id || generate_temporary_id(record)}]"
529
624
  else
530
625
  "#{scope}[#{column.name}]"
@@ -533,11 +628,9 @@ module ActiveScaffold
533
628
 
534
629
  def active_scaffold_add_existing_input(options)
535
630
  record = options.delete(:object)
536
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include :object in options with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
537
- record ||= @record # TODO: Remove when relying on @record is removed
538
631
  if !ActiveScaffold.js_framework.nil? && controller.respond_to?(:record_select_config, true)
539
632
  remote_controller = active_scaffold_controller_for(record_select_config.model).controller_path
540
- options.merge!(:controller => remote_controller)
633
+ options[:controller] = remote_controller
541
634
  options.merge!(active_scaffold_input_text_options)
542
635
  record_select_field(options[:name], record, options)
543
636
  else
@@ -596,8 +689,8 @@ module ActiveScaffold
596
689
  numerical_constraints[:step] ||= "0.#{'0' * (column.column.scale - 1)}1" if column.column && column.column.scale.to_i > 0
597
690
  elsif options[:min] && options[:min].respond_to?(:even?) && (only_odd_valid || only_even_valid)
598
691
  numerical_constraints[:step] = 2
599
- numerical_constraints[:min] += 1 if only_odd_valid && !options[:min].odd?
600
- numerical_constraints[:min] += 1 if only_even_valid && !options[:min].even?
692
+ numerical_constraints[:min] += 1 if only_odd_valid && options[:min].even?
693
+ numerical_constraints[:min] += 1 if only_even_valid && options[:min].odd?
601
694
  end
602
695
  numerical_constraints[:step] ||= 'any' unless only_integer
603
696
  end