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
@@ -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