active_scaffold 3.4.43 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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