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
@@ -3,18 +3,20 @@ module ActiveScaffold
3
3
  # Helpers that assist with the rendering of a List Column
4
4
  module ShowColumnHelpers
5
5
  def show_column_value(record, column)
6
+ value_record = column.delegated_association ? record.send(column.delegated_association.name) : record
7
+ return get_column_value(record, column) unless value_record
6
8
  # check for an override helper
7
9
  if (method = show_column_override(column))
8
10
  # we only pass the record as the argument. we previously also passed the formatted_value,
9
11
  # but mike perham pointed out that prohibited the usage of overrides to improve on the
10
12
  # performance of our default formatting. see issue #138.
11
- send(method, record, column)
13
+ send(method, value_record, column)
12
14
  # second, check if the dev has specified a valid list_ui for this column
13
15
  elsif column.show_ui && (method = override_show_column_ui(column.show_ui))
14
- send(method, record, column)
16
+ send(method, value_record, column)
15
17
  else
16
18
  if column.column && (method = override_show_column_ui(column.column.type))
17
- send(method, record, column)
19
+ send(method, value_record, column)
18
20
  else
19
21
  get_column_value(record, column)
20
22
  end
@@ -56,6 +58,10 @@ module ActiveScaffold
56
58
  method = "active_scaffold_show_#{show_ui}"
57
59
  method if respond_to? method
58
60
  end
61
+
62
+ def display_link_in_show?(link, position)
63
+ position == :header
64
+ end
59
65
  end
60
66
  end
61
67
  end
@@ -3,8 +3,8 @@ module ActiveScaffold
3
3
  # All extra helpers that should be included in the View.
4
4
  # Also a dumping ground for uncategorized helpers.
5
5
  module ViewHelpers
6
- NESTED_PARAMS = [:eid, :association, :parent_scaffold]
7
6
  include ActiveScaffold::Helpers::IdHelpers
7
+ include ActiveScaffold::Helpers::ActionLinkHelpers
8
8
  include ActiveScaffold::Helpers::AssociationHelpers
9
9
  include ActiveScaffold::Helpers::PaginationHelpers
10
10
  include ActiveScaffold::Helpers::ListColumnHelpers
@@ -44,16 +44,9 @@ module ActiveScaffold
44
44
  # This is the template finder logic, keep it updated with however we find stuff in rails
45
45
  # currently this very similar to the logic in ActionBase::Base.render for options file
46
46
  def template_exists?(template_name, partial = false)
47
- lookup_context.exists? template_name, '', partial
48
- end
49
-
50
- # Turns [[label, value]] into <option> tags
51
- # Takes optional parameter of :include_blank
52
- def option_tags_for(select_options, options = {})
53
- select_options.insert(0, [as_(:_select_), nil]) if options[:include_blank]
54
- select_options.collect do |option|
55
- label, value = option[0], option[1]
56
- value.nil? ? '<option value='">#{label}</option>" : "<option value=\"#{value}\">#{label}</option>"
47
+ restore_view_paths, lookup_context.view_paths = lookup_context.view_paths, @_view_paths if @_view_paths
48
+ lookup_context.exists?(template_name, '', partial).tap do
49
+ lookup_context.view_paths = restore_view_paths if @_view_paths
57
50
  end
58
51
  end
59
52
 
@@ -61,9 +54,10 @@ module ActiveScaffold
61
54
  options[:target] = action_iframe_id(url_for_options)
62
55
  options[:multipart] ||= true
63
56
  options[:class] = "#{options[:class]} as_remote_upload".strip
64
- output = ''
57
+ output = []
65
58
  output << form_tag(url_for_options, options)
66
- (output << "<iframe id='#{action_iframe_id(url_for_options)}' name='#{action_iframe_id(url_for_options)}' style='display:none'></iframe>").html_safe
59
+ output << content_tag(:iframe, '', id: action_iframe_id(url_for_options), name: action_iframe_id(url_for_options), style: 'display:none')
60
+ safe_join output
67
61
  end
68
62
 
69
63
  # a general-use loading indicator (the "stuff is happening, please wait" feedback)
@@ -81,389 +75,6 @@ module ActiveScaffold
81
75
  link_to options[:default_visible] ? options[:hide_label] : options[:show_label], '#', :data => {:show => options[:show_label], :hide => options[:hide_label], :toggable => id}, :style => 'display: none;', :class => 'as-js-button visibility-toggle'
82
76
  end
83
77
 
84
- def skip_action_link?(link, *args)
85
- !link.ignore_method.nil? && controller.respond_to?(link.ignore_method, true) && controller.send(link.ignore_method, *args)
86
- end
87
-
88
- def action_link_authorized?(link, *args)
89
- if link.security_method_set? || controller.respond_to?(link.security_method, true)
90
- controller.send(link.security_method, *args)
91
- else
92
- args.empty? ? true : args.first.authorized_for?(:crud_type => link.crud_type, :action => link.action)
93
- end
94
- end
95
-
96
- def display_dynamic_action_group(action_link, links, record_or_ul_options = nil, ul_options = nil)
97
- ul_options = record_or_ul_options if ul_options.nil? && record_or_ul_options.is_a?(Hash)
98
- record = record_or_ul_options unless record_or_ul_options.is_a?(Hash)
99
- html = content_tag :ul, ul_options do
100
- links.map { |link| content_tag :li, link }.join('').html_safe
101
- end
102
- raw "ActiveScaffold.display_dynamic_action_group('#{get_action_link_id action_link, record}', '#{escape_javascript html}');"
103
- end
104
-
105
- def display_action_links(action_links, record, options, &block)
106
- options[:level_0_tag] ||= nil
107
- options[:options_level_0_tag] ||= nil
108
- options[:level] ||= 0
109
- options[:first_action] = true
110
- output = ActiveSupport::SafeBuffer.new
111
-
112
- action_links.each(:reverse => options.delete(:reverse), :groups => true) do |link|
113
- if link.is_a? ActiveScaffold::DataStructures::ActionLinks
114
- unless link.empty?
115
- options[:level] += 1
116
- content = display_action_links(link, record, options, &block)
117
- options[:level] -= 1
118
- if content.present?
119
- output << display_action_link(link, content, record, options)
120
- options[:first_action] = false
121
- end
122
- end
123
- elsif !skip_action_link?(link, *Array(options[:for]))
124
- authorized = action_link_authorized?(link, *Array(options[:for]))
125
- next if !authorized && options[:skip_unauthorized]
126
- output << display_action_link(link, nil, record, options.merge(:authorized => authorized))
127
- options[:first_action] = false
128
- end
129
- end
130
- output
131
- end
132
-
133
- def display_action_link(link, content, record, options)
134
- if content
135
- html_classes = hover_via_click? ? 'hover_click ' : ''
136
- if options[:level] == 0
137
- html_classes << 'action_group'
138
- group_tag = :div
139
- else
140
- html_classes << 'top' if options[:first_action]
141
- group_tag = :li
142
- end
143
- content = content_tag(group_tag, :class => (html_classes if html_classes.present?), :onclick => ('' if hover_via_click?)) do
144
- content_tag(:div, as_(link.label), :class => link.name.to_s.downcase) << content_tag(:ul, content)
145
- end
146
- else
147
- content = render_action_link(link, record, options)
148
- content = content_tag(:li, content, :class => ('top' if options[:first_action])) unless options[:level] == 0
149
- end
150
- content = content_tag(options[:level_0_tag], content, options[:options_level_0_tag]) if options[:level] == 0 && options[:level_0_tag]
151
- content
152
- end
153
-
154
- def render_action_link(link, record = nil, options = {})
155
- if link.action.nil? || link.column.try(:polymorphic_association?)
156
- link = action_link_to_inline_form(link, record) if link.column.try(:association)
157
- options[:authorized] = false if link.action.nil? || link.controller.nil?
158
- options.delete :link if link.crud_type == :create
159
- end
160
- if link.action.nil? || (link.type == :member && options.key?(:authorized) && !options[:authorized])
161
- action_link_html(link, nil, {:link => action_link_text(link, options), :class => "disabled #{link.action}#{" #{link.html_options[:class]}" unless link.html_options[:class].blank?}"}, record)
162
- else
163
- url = action_link_url(link, record)
164
- html_options = action_link_html_options(link, record, options)
165
- action_link_html(link, url, html_options, record)
166
- end
167
- end
168
-
169
- # setup the action link to inline form
170
- def action_link_to_inline_form(link, record)
171
- link = link.clone
172
- associated = record.send(link.column.association.name)
173
- if link.column.polymorphic_association?
174
- link.controller = controller_path_for_activerecord(associated.class)
175
- return link if link.controller.nil?
176
- end
177
- link = configure_column_link(link, record, associated) if link.action.nil?
178
- link
179
- end
180
-
181
- def configure_column_link(link, record, associated, actions = nil)
182
- actions ||= link.column.actions_for_association_links
183
- if column_empty?(associated) # if association is empty, we only can link to create form
184
- if actions.include?(:new)
185
- link.action = 'new'
186
- link.crud_type = :create
187
- link.label ||= as_(:create_new)
188
- end
189
- elsif actions.include?(:edit)
190
- link.action = 'edit'
191
- link.crud_type = :update
192
- elsif actions.include?(:show)
193
- link.action = 'show'
194
- link.crud_type = :read
195
- elsif actions.include?(:list)
196
- link.action = 'index'
197
- link.crud_type = :read
198
- end
199
-
200
- unless column_link_authorized?(link, link.column, record, associated)
201
- link.action = nil
202
- # if action is edit and is not authorized, fallback to show if it's enabled
203
- if link.crud_type == :update && actions.include?(:show)
204
- link = configure_column_link(link, record, associated, [:show])
205
- end
206
- end
207
- link
208
- end
209
-
210
- def column_link_authorized?(link, column, record, associated)
211
- if column.association
212
- associated_for_authorized =
213
- if column.plural_association? || (associated.respond_to?(:blank?) && associated.blank?)
214
- column.association.klass
215
- else
216
- associated
217
- end
218
- authorized = associated_for_authorized.authorized_for?(:crud_type => link.crud_type)
219
- authorized &&= record.authorized_for?(:crud_type => :update, :column => column.name) if link.crud_type == :create
220
- authorized
221
- else
222
- action_link_authorized?(link, record)
223
- end
224
- end
225
-
226
- def is_sti_record?(record)
227
- model = active_scaffold_config.model
228
- record && model.columns_hash.include?(model.inheritance_column) &&
229
- record[model.inheritance_column].present? && !record.instance_of?(model)
230
- end
231
-
232
- def cache_action_link_url?(link, record)
233
- active_scaffold_config.cache_action_link_urls && link.type == :member && !link.dynamic_parameters.is_a?(Proc) && !is_sti_record?(record)
234
- end
235
-
236
- def cached_action_link_url(link, record)
237
- @action_links_urls ||= {}
238
- @action_links_urls[link.name_to_cache] || begin
239
- url_options = cached_action_link_url_options(link, record)
240
- if cache_action_link_url?(link, record)
241
- @action_links_urls[link.name_to_cache] = url_for(url_options)
242
- else
243
- url_for(params_for(url_options))
244
- end
245
- end
246
- end
247
-
248
- def replace_id_params_in_action_link_url(link, record, url)
249
- url = record ? url.sub('--ID--', record.to_param.to_s) : url.clone
250
- if link.column.try(:singular_association?)
251
- child_id = record.send(link.column.association.name).try(:to_param)
252
- if child_id.present?
253
- url.sub!('--CHILD_ID--', child_id)
254
- else
255
- url.sub!(/\w+=--CHILD_ID--&?/, '')
256
- url.sub!(/\?$/, '')
257
- end
258
- elsif nested?
259
- url.sub!('--CHILD_ID--', params[nested.param_name].to_s)
260
- end
261
- url
262
- end
263
-
264
- def add_query_string_to_cached_url(link, url)
265
- query_string, non_nested_query_string = query_string_for_action_links(link)
266
- nested_params = (!link.nested_link? && non_nested_query_string)
267
- if query_string || nested_params
268
- url << (url.include?('?') ? '&' : '?')
269
- url << query_string if query_string
270
- url << non_nested_query_string if nested_params
271
- end
272
- url
273
- end
274
-
275
- def action_link_url(link, record)
276
- url = replace_id_params_in_action_link_url(link, record, cached_action_link_url(link, record))
277
- url = add_query_string_to_cached_url(link, url) if @action_links_urls[link.name_to_cache]
278
- url
279
- end
280
-
281
- def query_string_for_action_links(link)
282
- if defined?(@query_string) && link.parameters.none? { |k, _| @query_string_params.include? k }
283
- return [@query_string, @non_nested_query_string]
284
- end
285
- keep = true
286
- @query_string_params ||= Set.new
287
- query_string_options = {}
288
- non_nested_query_string_options = {}
289
-
290
- params_for.except(:controller, :action, :id).each do |key, value|
291
- @query_string_params << key
292
- if link.parameters.include? key
293
- keep = false
294
- next
295
- end
296
- if NESTED_PARAMS.include?(key) || conditions_from_params.include?(key) || (nested? && nested.param_name == key)
297
- non_nested_query_string_options[key] = value
298
- else
299
- query_string_options[key] = value
300
- end
301
- end
302
-
303
- query_string = query_string_options.to_query if query_string_options.present?
304
- if non_nested_query_string_options.present?
305
- non_nested_query_string = "#{'&' if query_string}#{non_nested_query_string_options.to_query}"
306
- end
307
- if keep
308
- @query_string = query_string
309
- @non_nested_query_string = non_nested_query_string
310
- end
311
- [query_string, non_nested_query_string]
312
- end
313
-
314
- def cache_action_link_url_options?(link, record)
315
- active_scaffold_config.cache_action_link_urls && (link.type == :collection || !link.dynamic_parameters.is_a?(Proc)) && !is_sti_record?(record)
316
- end
317
-
318
- def cached_action_link_url_options(link, record)
319
- @action_links_url_options ||= {}
320
- @action_links_url_options[link.name_to_cache] || begin
321
- options = action_link_url_options(link, record)
322
- if cache_action_link_url_options?(link, record)
323
- @action_links_url_options[link.name_to_cache] = options
324
- end
325
- options
326
- end
327
- end
328
-
329
- def action_link_url_options(link, record)
330
- url_options = {:action => link.action}
331
- url_options[:id] = '--ID--' unless record.nil?
332
- url_options[:controller] = link.controller.to_s if link.controller
333
- url_options.merge! link.parameters if link.parameters
334
- if link.dynamic_parameters.is_a?(Proc)
335
- if record.nil?
336
- url_options.merge! instance_exec &link.dynamic_parameters
337
- else
338
- url_options.merge! instance_exec record, &link.dynamic_parameters
339
- end
340
- end
341
- if link.nested_link?
342
- url_options_for_nested_link(link.column, record, link, url_options)
343
- elsif nested?
344
- url_options[nested.param_name] = '--CHILD_ID--'
345
- end
346
- url_options_for_sti_link(link.column, record, link, url_options) unless record.nil? || active_scaffold_config.sti_children.nil?
347
- url_options[:_method] = link.method if !link.confirm? && link.inline? && link.method != :get
348
- url_options
349
- end
350
-
351
- def action_link_text(link, options)
352
- text = image_tag(link.image[:name], :size => link.image[:size], :alt => options[:link] || link.label, :title => options[:link] || link.label) if link.image
353
- text || options[:link]
354
- end
355
-
356
- def replaced_action_link_url_options(link, record)
357
- url = cached_action_link_url_options(link, record)
358
- url[:controller] ||= params[:controller]
359
- missing_options, url_options = url.partition { |_, v| v.nil? }
360
- replacements = {}
361
- replacements['--ID--'] = record.id.to_s if record
362
- if link.column.try(:singular_association?)
363
- replacements['--CHILD_ID--'] = record.send(link.column.association.name).try(:id).to_s
364
- elsif nested?
365
- replacements['--CHILD_ID--'] = params[nested.param_name].to_s
366
- end
367
- url_options.collect! do |k, v|
368
- [k.to_s, replacements[v] || v]
369
- end
370
- [missing_options, url_options]
371
- end
372
-
373
- def action_link_selected?(link, record)
374
- missing_options, url_options = replaced_action_link_url_options(link, record)
375
- (url_options - params.to_a).blank? && missing_options.all? { |k, _| params[k].nil? }
376
- end
377
-
378
- def action_link_html_options(link, record, options)
379
- link_id = get_action_link_id(link, record)
380
- html_options = link.html_options.merge(:class => [link.html_options[:class], link.action.to_s].compact.join(' '))
381
- html_options[:link] = action_link_text(link, options)
382
-
383
- # Needs to be in html_options to as the adding _method to the url is no longer supported by Rails
384
- html_options[:method] = link.method if link.method != :get
385
-
386
- html_options[:data] ||= {}
387
- html_options[:data][:confirm] = link.confirm(h(record.try(:to_label))) if link.confirm?
388
- if link.inline?
389
- html_options[:class] << ' as_action'
390
- html_options[:data][:position] = link.position if link.position
391
- html_options[:data][:action] = link.action
392
- html_options[:data][:cancel_refresh] = true if link.refresh_on_close
393
- html_options[:data][:keep_open] = true if link.keep_open?
394
- end
395
-
396
- if link.toggle
397
- html_options[:class] << ' toggle'
398
- html_options[:class] << ' active' if action_link_selected?(link, record)
399
- end
400
-
401
- html_options[:target] = '_blank' if link.popup?
402
- html_options[:id] = link_id
403
- html_options[:remote] = true unless link.page? || link.popup?
404
- if link.dhtml_confirm?
405
- unless link.inline?
406
- html_options[:class] << ' as_action'
407
- html_options[:page_link] = 'true'
408
- end
409
- html_options[:dhtml_confirm] = link.dhtml_confirm.value
410
- html_options[:onclick] = link.dhtml_confirm.onclick_function(controller, link_id)
411
- end
412
- html_options
413
- end
414
-
415
- def get_action_link_id(link, record = nil, column = nil)
416
- column ||= link.column
417
- if column && column.plural_association?
418
- id = "#{column.association.name}-#{record.id}"
419
- elsif column && column.singular_association?
420
- if record.try(column.association.name.to_sym).present?
421
- id = "#{column.association.name}-#{record.send(column.association.name).id}-#{record.id}"
422
- else
423
- id = "#{column.association.name}-#{record.id}" unless record.nil?
424
- end
425
- end
426
- id ||= record.try(:id) || (nested? ? nested_parent_id : '')
427
- action_id = "#{id_from_controller("#{link.controller}-") if params[:parent_controller] || (link.controller && link.controller != controller.controller_path)}#{link.action}"
428
- action_link_id(action_id, id)
429
- end
430
-
431
- def action_link_html(link, url, html_options, record)
432
- label = html_options.delete(:link)
433
- label ||= link.label
434
- if url.nil?
435
- content_tag(:a, label, html_options)
436
- else
437
- link_to(label, url, html_options)
438
- end
439
- end
440
-
441
- def url_options_for_nested_link(column, record, link, url_options)
442
- if column && column.association
443
- url_options[:parent_scaffold] = controller_path
444
- url_options[column.association.active_record.name.foreign_key.to_sym] = url_options.delete(:id)
445
- if column.singular_association? && url_options[:action].to_sym != :index
446
- url_options[:id] = '--CHILD_ID--'
447
- else
448
- url_options[:id] = nil
449
- end
450
- elsif link.parameters && link.parameters[:named_scope]
451
- url_options[:parent_scaffold] = controller_path
452
- url_options[active_scaffold_config.model.name.foreign_key.to_sym] = url_options.delete(:id)
453
- end
454
- end
455
-
456
- def url_options_for_sti_link(column, record, link, url_options)
457
- # need to find out controller of current record type and set parameters
458
- # it's quite difficult to detect an sti link
459
- # if link.column.nil? we are sure that it isn't a singular association inline autolink
460
- # however that will not work if a sti parent is a singular association inline autolink
461
- return unless link.column.nil?
462
- return if (sti_controller_path = controller_path_for_activerecord(record.class)).nil?
463
- url_options[:controller] = sti_controller_path
464
- url_options[:parent_sti] = controller_path
465
- end
466
-
467
78
  def list_row_class_method(record)
468
79
  return @_list_row_class_method if defined? @_list_row_class_method
469
80
  class_override_helper = "#{clean_class_name(record.class.name)}_list_row_class"
@@ -488,6 +99,7 @@ module ActiveScaffold
488
99
  classes << 'sorted ' if active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.user.sorting.sorts_on?(column)
489
100
  classes << 'numeric ' if column.number?
490
101
  classes << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
102
+ classes
491
103
  end
492
104
  classes = "#{@_column_classes[column.name]} "
493
105
  classes << 'empty ' if column_empty? column_value
@@ -514,6 +126,9 @@ module ActiveScaffold
514
126
 
515
127
  def column_empty?(column_value)
516
128
  empty = column_value.nil?
129
+ # column_value != false would force boolean to be cast to integer
130
+ # when comparing to column_value of IPAddr class (PostgreSQL inet column type)
131
+ # rubocop:disable Style/YodaCondition
517
132
  empty ||= false != column_value && column_value.blank?
518
133
  empty ||= ['&nbsp;', empty_field_text].include? column_value if column_value.is_a? String
519
134
  empty
@@ -523,35 +138,16 @@ module ActiveScaffold
523
138
  active_scaffold_config.list.empty_field_text if active_scaffold_config.actions.include?(:list)
524
139
  end
525
140
 
526
- def column_calculation(column)
527
- if column.calculate.instance_of? Proc
528
- column.calculate.call(@records)
529
- else
530
- calculate_query.calculate(column.calculate, column.name)
531
- end
532
- end
533
-
534
- def render_column_calculation(column)
535
- calculation = column_calculation(column)
536
- override_formatter = "render_#{column.name}_#{column.calculate.is_a?(Proc) ? :calculate : column.calculate}"
537
- calculation = send(override_formatter, calculation) if respond_to? override_formatter
538
- format_column_calculation(column, calculation)
539
- end
540
-
541
- def format_column_calculation(column, calculation)
542
- "#{"#{as_(column.calculate)}: " unless column.calculate.is_a? Proc}#{format_column_value nil, column, calculation}"
543
- end
544
-
545
141
  def as_slider(options)
546
142
  content_tag(:span, '', class: 'as-slider', data: {slider: options})
547
143
  end
548
144
 
549
145
  def clean_column_name(name)
550
- name.to_s.gsub('?', '')
146
+ name.to_s.delete('?')
551
147
  end
552
148
 
553
149
  def clean_class_name(name)
554
- name.underscore.gsub('/', '_')
150
+ name.underscore.tr('/', '_')
555
151
  end
556
152
 
557
153
  # the naming convention for overriding with helpers
@@ -575,7 +171,24 @@ module ActiveScaffold
575
171
  end
576
172
  end
577
173
 
174
+ def history_state
175
+ if active_scaffold_config.store_user_settings
176
+ state = {page: @page.try(:number)}
177
+ state[:search] = search_params if respond_to?(:search_params) && search_params.present?
178
+ if active_scaffold_config.list.user.user_sorting?
179
+ column, state[:sort_direction] = active_scaffold_config.list.user.sorting.first
180
+ state[:sort] = column.name
181
+ else
182
+ state.merge sort: '', sort_direction: ''
183
+ end
184
+ state
185
+ else
186
+ {}
187
+ end
188
+ end
189
+
578
190
  def display_message(message)
191
+ message = safe_join message, tag(:br) if message.is_a?(Array)
579
192
  if (highlights = active_scaffold_config.highlight_messages)
580
193
  message = highlights.inject(message) do |msg, (phrases, highlighter)|
581
194
  highlight(msg, phrases, highlighter || {})
@@ -583,7 +196,9 @@ module ActiveScaffold
583
196
  end
584
197
  if (format = active_scaffold_config.timestamped_messages)
585
198
  format = :short if format == true
586
- message = "#{content_tag :div, l(Time.current, :format => format), :class => 'timestamp'} #{content_tag :div, message, :class => 'message-content'}".html_safe
199
+ messages = [content_tag(:div, l(Time.current, :format => format), :class => 'timestamp')]
200
+ messages << content_tag(:div, message, :class => 'message-content')
201
+ message = safe_join messages, ' '
587
202
  end
588
203
  message
589
204
  end
@@ -610,10 +225,10 @@ module ActiveScaffold
610
225
  ''
611
226
  else
612
227
  html = {}
613
- [:id, :class].each do |key|
228
+ %i[id class].each do |key|
614
229
  if options.include?(key)
615
230
  value = options[key]
616
- html[key] = value unless value.blank?
231
+ html[key] = value if value.present?
617
232
  else
618
233
  html[key] = 'errorExplanation'
619
234
  end
@@ -624,7 +239,7 @@ module ActiveScaffold
624
239
  if options.include?(:header_message)
625
240
  options[:header_message]
626
241
  else
627
- as_('errors.template.header', :count => count, :model => options[:object_name].to_s.gsub('_', ' '))
242
+ as_('errors.template.header', :count => count, :model => options[:object_name].to_s.tr('_', ' '))
628
243
  end
629
244
 
630
245
  message = options.include?(:message) ? options[:message] : as_('errors.template.body')
@@ -636,16 +251,16 @@ module ActiveScaffold
636
251
  end
637
252
  error_messages =
638
253
  if options[:list_type] == :br
639
- error_messages.join('<br/>').html_safe
254
+ safe_join error_messages, tag(:br)
640
255
  else
641
- content_tag(options[:list_type], error_messages.join.html_safe)
256
+ content_tag options[:list_type], safe_join(error_messages)
642
257
  end
643
258
 
644
259
  contents = []
645
- contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
646
- contents << content_tag(:p, message) unless message.blank?
260
+ contents << content_tag(options[:header_tag] || :h2, header_message) if header_message.present?
261
+ contents << content_tag(:p, message) if message.present?
647
262
  contents << error_messages
648
- contents = contents.join.html_safe
263
+ contents = safe_join(contents)
649
264
  options[:container_tag] ? content_tag(options[:container_tag], contents, html) : contents
650
265
  end
651
266
  end