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
@@ -0,0 +1,398 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ # All extra helpers that should be included in the View.
4
+ # Also a dumping ground for uncategorized helpers.
5
+ module ActionLinkHelpers
6
+ # params which mustn't be copying to nested links
7
+ NESTED_PARAMS = %i[eid embedded association parent_scaffold].freeze
8
+
9
+ def skip_action_link?(link, *args)
10
+ !link.ignore_method.nil? && controller.respond_to?(link.ignore_method, true) && controller.send(link.ignore_method, *args)
11
+ end
12
+
13
+ def action_link_authorized?(link, *args)
14
+ auth, reason =
15
+ if link.security_method_set? || controller.respond_to?(link.security_method, true)
16
+ controller.send(link.security_method, *args)
17
+ else
18
+ args.empty? ? true : args.first.authorized_for?(:crud_type => link.crud_type, :action => link.action, :reason => true)
19
+ end
20
+ [auth, reason]
21
+ end
22
+
23
+ def display_dynamic_action_group(action_link, links, record_or_ul_options = nil, ul_options = nil)
24
+ ul_options = record_or_ul_options if ul_options.nil? && record_or_ul_options.is_a?(Hash)
25
+ record = record_or_ul_options unless record_or_ul_options.is_a?(Hash)
26
+ html = content_tag :ul, ul_options do
27
+ safe_join links.map { |link| content_tag :li, link }
28
+ end
29
+ raw "ActiveScaffold.display_dynamic_action_group('#{get_action_link_id action_link, record}', '#{escape_javascript html}');"
30
+ end
31
+
32
+ def display_action_links(action_links, record, options, &block)
33
+ options[:level_0_tag] ||= nil
34
+ options[:options_level_0_tag] ||= nil
35
+ options[:level] ||= 0
36
+ options[:first_action] = true
37
+ output = ActiveSupport::SafeBuffer.new
38
+
39
+ action_links.each(:reverse => options.delete(:reverse), :groups => true) do |link|
40
+ if link.is_a? ActiveScaffold::DataStructures::ActionLinks
41
+ unless link.empty?
42
+ options[:level] += 1
43
+ content = display_action_links(link, record, options, &block)
44
+ options[:level] -= 1
45
+ if content.present?
46
+ output << display_action_link(link, content, record, options)
47
+ options[:first_action] = false
48
+ end
49
+ end
50
+ elsif !skip_action_link?(link, *Array(options[:for]))
51
+ authorized, reason = action_link_authorized?(link, *Array(options[:for]))
52
+ next if !authorized && options[:skip_unauthorized]
53
+ output << display_action_link(link, nil, record, options.merge(:authorized => authorized, :not_authorized_reason => reason))
54
+ options[:first_action] = false
55
+ end
56
+ end
57
+ output
58
+ end
59
+
60
+ def display_action_link(link, content, record, options)
61
+ if content
62
+ html_classes = hover_via_click? ? 'hover_click ' : ''
63
+ if (options[:level]).zero?
64
+ html_classes << 'action_group'
65
+ group_tag = :div
66
+ else
67
+ html_classes << 'top' if options[:first_action]
68
+ group_tag = :li
69
+ end
70
+ content = content_tag(group_tag, :class => (html_classes if html_classes.present?), :onclick => ('' if hover_via_click?)) do
71
+ content_tag(:div, as_(link.label), :class => link.name.to_s.downcase) << content_tag(:ul, content)
72
+ end
73
+ else
74
+ content = render_action_link(link, record, options)
75
+ content = content_tag(:li, content, :class => ('top' if options[:first_action])) unless (options[:level]).zero?
76
+ end
77
+ content = content_tag(options[:level_0_tag], content, options[:options_level_0_tag]) if (options[:level]).zero? && options[:level_0_tag]
78
+ content
79
+ end
80
+
81
+ def render_action_link(link, record = nil, options = {})
82
+ if link.action.nil? || link.column.try(:association).try(:polymorphic?)
83
+ link = action_link_to_inline_form(link, record) if link.column.try(:association)
84
+ options[:authorized] = false if link.action.nil? || link.controller.nil?
85
+ options.delete :link if link.crud_type == :create
86
+ end
87
+ if link.action.nil? || (link.type == :member && options.key?(:authorized) && !options[:authorized])
88
+ action_link_html(link, nil, {:link => action_link_text(link, options), :class => "disabled #{link.action}#{" #{link.html_options[:class]}" if link.html_options[:class].present?}", :title => options[:not_authorized_reason]}, record)
89
+ else
90
+ url = action_link_url(link, record)
91
+ html_options = action_link_html_options(link, record, options)
92
+ action_link_html(link, url, html_options, record)
93
+ end
94
+ end
95
+
96
+ # setup the action link to inline form
97
+ def action_link_to_inline_form(link, record)
98
+ link = link.clone
99
+ associated = record.send(link.column.association.name)
100
+ if link.column.association.try(:polymorphic?)
101
+ link.controller = controller_path_for_activerecord(associated.class)
102
+ return link if link.controller.nil?
103
+ end
104
+ link = configure_column_link(link, record, associated) if link.action.nil?
105
+ link
106
+ end
107
+
108
+ def configure_column_link(link, record, associated, actions = nil)
109
+ actions ||= link.column.actions_for_association_links
110
+ if column_empty?(associated) # if association is empty, we only can link to create form
111
+ if actions.include?(:new)
112
+ link.action = 'new'
113
+ link.crud_type = :create
114
+ link.label ||= as_(:create_new)
115
+ end
116
+ elsif actions.include?(:edit)
117
+ link.action = 'edit'
118
+ link.crud_type = :update
119
+ elsif actions.include?(:show)
120
+ link.action = 'show'
121
+ link.crud_type = :read
122
+ elsif actions.include?(:list)
123
+ link.action = 'index'
124
+ link.crud_type = :read
125
+ end
126
+
127
+ unless column_link_authorized?(link, link.column, record, associated)[0]
128
+ link.action = nil
129
+ # if action is edit and is not authorized, fallback to show if it's enabled
130
+ if link.crud_type == :update && actions.include?(:show)
131
+ link = configure_column_link(link, record, associated, [:show])
132
+ end
133
+ end
134
+ link
135
+ end
136
+
137
+ def column_link_authorized?(link, column, record, associated)
138
+ if column.association
139
+ associated_for_authorized =
140
+ if column.association.collection? || (associated.respond_to?(:blank?) && associated.blank?)
141
+ column.association.klass
142
+ else
143
+ associated
144
+ end
145
+ authorized, reason = associated_for_authorized.authorized_for?(:crud_type => link.crud_type, :reason => true)
146
+ if link.crud_type == :create && authorized
147
+ authorized, reason = record.authorized_for?(:crud_type => :update, :column => column.name, :reason => true)
148
+ end
149
+ [authorized, reason]
150
+ else
151
+ action_link_authorized?(link, record)
152
+ end
153
+ end
154
+
155
+ def sti_record?(record)
156
+ return unless active_scaffold_config.active_record?
157
+ model = active_scaffold_config.model
158
+ record && model.columns_hash.include?(model.inheritance_column) &&
159
+ record[model.inheritance_column].present? && !record.instance_of?(model)
160
+ end
161
+
162
+ def cache_action_link_url?(link, record)
163
+ active_scaffold_config.cache_action_link_urls && link.type == :member && !link.dynamic_parameters.is_a?(Proc) && !sti_record?(record)
164
+ end
165
+
166
+ def cached_action_link_url(link, record)
167
+ @action_links_urls ||= {}
168
+ @action_links_urls[link.name_to_cache] || begin
169
+ url_options = cached_action_link_url_options(link, record)
170
+ if cache_action_link_url?(link, record)
171
+ @action_links_urls[link.name_to_cache] = url_for(url_options)
172
+ else
173
+ url_options.merge! eid: nil, embedded: nil if link.nested_link?
174
+ url_for(params_for(url_options))
175
+ end
176
+ end
177
+ end
178
+
179
+ def replace_id_params_in_action_link_url(link, record, url)
180
+ url = record ? url.sub('--ID--', record.to_param.to_s) : url.clone
181
+ if link.column.try(:association).try(:singular?)
182
+ child_id = record.send(link.column.association.name).try(:to_param)
183
+ if child_id.present?
184
+ url.sub!('--CHILD_ID--', child_id)
185
+ else
186
+ url.sub!(/\w+=--CHILD_ID--&?/, '')
187
+ url.sub!(/\?$/, '')
188
+ end
189
+ elsif nested?
190
+ url.sub!('--CHILD_ID--', params[nested.param_name].to_s)
191
+ end
192
+ url
193
+ end
194
+
195
+ def add_query_string_to_cached_url(link, url)
196
+ query_string, non_nested_query_string = query_string_for_action_links(link)
197
+ nested_params = (!link.nested_link? && non_nested_query_string)
198
+ if query_string || nested_params
199
+ url << (url.include?('?') ? '&' : '?')
200
+ url << query_string if query_string
201
+ url << non_nested_query_string if nested_params
202
+ end
203
+ url
204
+ end
205
+
206
+ def action_link_url(link, record)
207
+ url = replace_id_params_in_action_link_url(link, record, cached_action_link_url(link, record))
208
+ url = add_query_string_to_cached_url(link, url) if @action_links_urls[link.name_to_cache]
209
+ url
210
+ end
211
+
212
+ def query_string_for_action_links(link)
213
+ if defined?(@query_string) && link.parameters.none? { |k, _| @query_string_params.include? k }
214
+ return [@query_string, @non_nested_query_string]
215
+ end
216
+ keep = true
217
+ @query_string_params ||= Set.new
218
+ query_string_options = {}
219
+ non_nested_query_string_options = {}
220
+
221
+ params_for.except(:controller, :action, :id).each do |key, value|
222
+ @query_string_params << key
223
+ if link.parameters.include? key
224
+ keep = false
225
+ next
226
+ end
227
+ if NESTED_PARAMS.include?(key) || conditions_from_params.include?(key) || (nested? && nested.param_name == key)
228
+ non_nested_query_string_options[key] = value
229
+ else
230
+ query_string_options[key] = value
231
+ end
232
+ end
233
+
234
+ query_string = query_string_options.to_query if query_string_options.present?
235
+ if non_nested_query_string_options.present?
236
+ non_nested_query_string = "#{'&' if query_string}#{non_nested_query_string_options.to_query}"
237
+ end
238
+ if keep
239
+ @query_string = query_string
240
+ @non_nested_query_string = non_nested_query_string
241
+ end
242
+ [query_string, non_nested_query_string]
243
+ end
244
+
245
+ def cache_action_link_url_options?(link, record)
246
+ active_scaffold_config.cache_action_link_urls && (link.type == :collection || !link.dynamic_parameters.is_a?(Proc)) && !sti_record?(record)
247
+ end
248
+
249
+ def cached_action_link_url_options(link, record)
250
+ @action_links_url_options ||= {}
251
+ @action_links_url_options[link.name_to_cache] || begin
252
+ options = action_link_url_options(link, record)
253
+ if cache_action_link_url_options?(link, record)
254
+ @action_links_url_options[link.name_to_cache] = options
255
+ end
256
+ options
257
+ end
258
+ end
259
+
260
+ def action_link_url_options(link, record)
261
+ url_options = {:action => link.action}
262
+ url_options[:id] = '--ID--' unless record.nil?
263
+ url_options[:controller] = link.controller.to_s if link.controller
264
+ url_options.merge! link.parameters if link.parameters
265
+ if link.dynamic_parameters.is_a?(Proc)
266
+ if record.nil?
267
+ url_options.merge! instance_exec(&link.dynamic_parameters)
268
+ else
269
+ url_options.merge! instance_exec(record, &link.dynamic_parameters)
270
+ end
271
+ end
272
+ if link.nested_link?
273
+ url_options_for_nested_link(link.column, record, link, url_options)
274
+ elsif nested?
275
+ url_options[nested.param_name] = '--CHILD_ID--'
276
+ end
277
+ url_options_for_sti_link(link.column, record, link, url_options) unless record.nil? || active_scaffold_config.sti_children.nil?
278
+ url_options[:_method] = link.method if !link.confirm? && link.inline? && link.method != :get
279
+ url_options
280
+ end
281
+
282
+ def action_link_text(link, options)
283
+ text = image_tag(link.image[:name], :size => link.image[:size], :alt => options[:link] || link.label, :title => options[:link] || link.label) if link.image
284
+ text || options[:link]
285
+ end
286
+
287
+ def replaced_action_link_url_options(link, record)
288
+ url = cached_action_link_url_options(link, record)
289
+ url[:controller] ||= params[:controller]
290
+ missing_options, url_options = url.partition { |_, v| v.nil? }
291
+ replacements = {}
292
+ replacements['--ID--'] = record.id.to_s if record
293
+ if link.column.try(:association).try(:singular?)
294
+ replacements['--CHILD_ID--'] = record.send(link.column.association.name).try(:id).to_s
295
+ elsif nested?
296
+ replacements['--CHILD_ID--'] = params[nested.param_name].to_s
297
+ end
298
+ url_options.collect! do |k, v|
299
+ [k.to_s, replacements[v] || v]
300
+ end
301
+ [missing_options, url_options]
302
+ end
303
+
304
+ def action_link_selected?(link, record)
305
+ missing_options, url_options = replaced_action_link_url_options(link, record)
306
+ safe_params = (Rails.version < '4.2' ? params.to_h : params.to_unsafe_h)
307
+ (url_options - safe_params.to_a).blank? && missing_options.all? { |k, _| params[k].nil? }
308
+ end
309
+
310
+ def action_link_html_options(link, record, options)
311
+ link_id = get_action_link_id(link, record)
312
+ html_options = link.html_options.merge(:class => [link.html_options[:class], link.action.to_s].compact.join(' '))
313
+ html_options[:link] = action_link_text(link, options)
314
+
315
+ # Needs to be in html_options to as the adding _method to the url is no longer supported by Rails
316
+ html_options[:method] = link.method if link.method != :get
317
+
318
+ html_options[:data] ||= {}
319
+ html_options[:data][:confirm] = link.confirm(h(record.try(:to_label))) if link.confirm?
320
+ if !options[:page] && !options[:popup] && (options[:inline] || link.inline?)
321
+ html_options[:class] << ' as_action'
322
+ html_options[:data][:position] = link.position if link.position
323
+ html_options[:data][:action] = link.action
324
+ html_options[:data][:cancel_refresh] = true if link.refresh_on_close
325
+ html_options[:data][:keep_open] = true if link.keep_open?
326
+ html_options[:remote] = true
327
+ end
328
+
329
+ if link.toggle
330
+ html_options[:class] << ' toggle'
331
+ html_options[:class] << ' active' if action_link_selected?(link, record)
332
+ end
333
+
334
+ html_options[:target] = '_blank' if !options[:page] && !options[:inline] && (options[:popup] || link.popup?)
335
+ html_options[:id] = link_id
336
+ if link.dhtml_confirm?
337
+ unless link.inline?
338
+ html_options[:class] << ' as_action'
339
+ html_options[:page_link] = 'true'
340
+ end
341
+ html_options[:dhtml_confirm] = link.dhtml_confirm.value
342
+ html_options[:onclick] = link.dhtml_confirm.onclick_function(controller, link_id)
343
+ end
344
+ html_options
345
+ end
346
+
347
+ def get_action_link_id(link, record = nil, column = nil)
348
+ column ||= link.column
349
+ if column.try(:association) && record
350
+ id = if column.association.collection?
351
+ "#{column.association.name}-#{record.id}"
352
+ elsif record.send(column.association.name).present?
353
+ "#{column.association.name}-#{record.send(column.association.name).id}-#{record.id}"
354
+ else
355
+ "#{column.association.name}-#{record.id}"
356
+ end
357
+ end
358
+ id ||= record.try(:id) || (nested? ? nested_parent_id : '')
359
+ action_id = "#{id_from_controller("#{link.controller}-") if params[:parent_controller] || (link.controller && link.controller != controller.controller_path)}#{link.action}"
360
+ action_link_id(action_id, id)
361
+ end
362
+
363
+ def action_link_html(link, url, html_options, record)
364
+ label = html_options.delete(:link)
365
+ label ||= link.label
366
+ if url.nil?
367
+ content_tag(:a, label, html_options)
368
+ else
369
+ link_to(label, url, html_options)
370
+ end
371
+ end
372
+
373
+ def url_options_for_nested_link(column, record, link, url_options)
374
+ if column.try(:association)
375
+ url_options[:parent_scaffold] = controller_path
376
+ url_options[column.model.name.foreign_key.to_sym] = url_options.delete(:id)
377
+ url_options[:id] = if column.association.singular? && url_options[:action].to_sym != :index
378
+ '--CHILD_ID--'
379
+ end
380
+ elsif link.parameters && link.parameters[:named_scope]
381
+ url_options[:parent_scaffold] = controller_path
382
+ url_options[active_scaffold_config.model.name.foreign_key.to_sym] = url_options.delete(:id)
383
+ end
384
+ end
385
+
386
+ def url_options_for_sti_link(column, record, link, url_options)
387
+ # need to find out controller of current record type and set parameters
388
+ # it's quite difficult to detect an sti link
389
+ # if link.column.nil? we are sure that it isn't a singular association inline autolink
390
+ # however that will not work if a sti parent is a singular association inline autolink
391
+ return unless link.column.nil?
392
+ return if (sti_controller_path = controller_path_for_activerecord(record.class)).nil?
393
+ url_options[:controller] = sti_controller_path
394
+ url_options[:parent_sti] = controller_path
395
+ end
396
+ end
397
+ end
398
+ end
@@ -5,7 +5,7 @@ module ActiveScaffold
5
5
  def cache_association_options(association, conditions, klass, cache = true)
6
6
  if active_scaffold_config.cache_association_options && cache
7
7
  @_associations_cache ||= Hash.new { |h, k| h[k] = {} }
8
- key = [association.name, association.active_record.name, klass.name].join('/')
8
+ key = [association.name, association.inverse_klass.name, klass.name].join('/')
9
9
  @_associations_cache[key][conditions] ||= yield
10
10
  else
11
11
  yield
@@ -14,10 +14,8 @@ module ActiveScaffold
14
14
 
15
15
  # Provides a way to honor the :conditions on an association while searching the association's klass
16
16
  def association_options_find(association, conditions = nil, klass = nil, record = nil)
17
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, call with record.', caller if record.nil? # TODO: Remove when relying on @record is removed
18
- record ||= @record # TODO: Remove when relying on @record is removed
19
- if klass.nil? && association.options[:polymorphic]
20
- class_name = record.send(association.foreign_type)
17
+ if klass.nil? && association.polymorphic?
18
+ class_name = record.send(association.foreign_type) if association.belongs_to?
21
19
  if class_name.present?
22
20
  klass = class_name.constantize
23
21
  else
@@ -29,18 +27,10 @@ module ActiveScaffold
29
27
  klass ||= association.klass
30
28
  end
31
29
 
32
- if conditions.nil?
33
- if method(:options_for_association_conditions).arity.abs == 2
34
- conditions = options_for_association_conditions(association, record)
35
- else
36
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include record in your options_for_association_conditions overrided method.', caller if record.nil? # TODO: Remove when relying on @record is removed
37
- conditions = options_for_association_conditions(association)
38
- end
39
- end
30
+ conditions ||= options_for_association_conditions(association, record)
40
31
  cache_association_options(association, conditions, klass, cache) do
41
32
  klass = association_klass_scoped(association, klass, record)
42
- relation = klass.where(conditions).where(association.options[:conditions])
43
- relation = relation.includes(association.options[:include]) if association.options[:include]
33
+ relation = klass.where(conditions)
44
34
  column = column_for_association(association, record)
45
35
  if column && column.try(:sort) && column.sort[:sql]
46
36
  if column.includes
@@ -60,6 +50,7 @@ module ActiveScaffold
60
50
 
61
51
  def association_klass_scoped(association, klass, record)
62
52
  if nested? && nested.through_association? && nested.child_association.try(:through_reflection) == association
53
+ # only ActiveRecord associations
63
54
  if nested.association.through_reflection.collection?
64
55
  nested_parent_record.send(nested.association.through_reflection.name)
65
56
  else
@@ -82,16 +73,11 @@ module ActiveScaffold
82
73
  end
83
74
 
84
75
  def association_options_count(association, conditions = nil)
85
- association.klass.where(conditions).where(association.options[:conditions]).count
76
+ association.klass.where(conditions).count
86
77
  end
87
78
 
88
79
  def options_for_association_count(association, record)
89
- if method(:options_for_association_conditions).arity.abs == 2
90
- conditions = options_for_association_conditions(association, record)
91
- else
92
- ActiveSupport::Deprecation.warn 'Relying on @record is deprecated, include record in your options_for_association_conditions overrided method.', caller if record.nil? # TODO: Remove when relying on @record is removed
93
- conditions = options_for_association_conditions(association)
94
- end
80
+ conditions = options_for_association_conditions(association, record)
95
81
  association_options_count(association, conditions)
96
82
  end
97
83
 
@@ -99,14 +85,10 @@ module ActiveScaffold
99
85
  # Should work in both the subform and form_ui=>:select modes.
100
86
  # Check association.name to specialize the conditions per-column.
101
87
  def options_for_association_conditions(association, record = nil)
102
- return nil if association.options[:through]
103
- case association.macro
104
- when :has_one, :has_many
105
- # Find only orphaned objects
106
- {association.foreign_key => nil}
107
- when :belongs_to, :has_and_belongs_to_many
108
- # Find all
109
- nil
88
+ return nil if association.through?
89
+ if association.has_one? || association.has_many?
90
+ # Find only orphaned objects
91
+ {association.foreign_key => nil}
110
92
  end
111
93
  end
112
94