active_scaffold 3.5.2 → 3.6.0.rc1

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +66 -0
  3. data/README.md +17 -7
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +63 -6
  6. data/app/assets/stylesheets/active_scaffold_colors.scss +1 -1
  7. data/app/assets/stylesheets/active_scaffold_layout.css +52 -29
  8. data/app/views/active_scaffold_overrides/_base_form.html.erb +2 -2
  9. data/app/views/active_scaffold_overrides/_form.html.erb +1 -1
  10. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  11. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +6 -6
  12. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +1 -1
  13. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +1 -1
  14. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  16. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  17. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  18. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  19. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  20. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  21. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  22. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  23. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  24. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  25. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  26. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  27. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  28. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  29. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  30. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  31. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  32. data/app/views/active_scaffold_overrides/update_column.js.erb +1 -1
  33. data/config/locales/de.yml +2 -1
  34. data/config/locales/en.yml +1 -0
  35. data/config/locales/es.yml +1 -0
  36. data/config/locales/fr.yml +2 -1
  37. data/config/locales/hu.yml +1 -0
  38. data/config/locales/ja.yml +1 -0
  39. data/config/locales/ru.yml +1 -0
  40. data/lib/active_scaffold.rb +19 -16
  41. data/lib/active_scaffold/actions/common_search.rb +11 -8
  42. data/lib/active_scaffold/actions/core.rb +89 -71
  43. data/lib/active_scaffold/actions/create.rb +28 -28
  44. data/lib/active_scaffold/actions/delete.rb +3 -3
  45. data/lib/active_scaffold/actions/field_search.rb +53 -43
  46. data/lib/active_scaffold/actions/list.rb +111 -27
  47. data/lib/active_scaffold/actions/nested.rb +65 -48
  48. data/lib/active_scaffold/actions/search.rb +1 -1
  49. data/lib/active_scaffold/actions/show.rb +4 -4
  50. data/lib/active_scaffold/actions/subform.rb +12 -17
  51. data/lib/active_scaffold/actions/update.rb +96 -77
  52. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  53. data/lib/active_scaffold/attribute_params.rb +104 -86
  54. data/lib/active_scaffold/bridges.rb +8 -8
  55. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  56. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +33 -0
  57. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  58. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  59. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  60. data/lib/active_scaffold/bridges/bitfields.rb +1 -0
  61. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  62. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  63. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +9 -12
  64. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  65. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  66. data/lib/active_scaffold/bridges/chosen/helpers.rb +11 -9
  67. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  68. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  69. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  70. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  71. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  72. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  73. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  74. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  75. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  76. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  77. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  78. data/lib/active_scaffold/bridges/record_select/helpers.rb +12 -16
  79. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  80. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  81. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  82. data/lib/active_scaffold/config/base.rb +133 -41
  83. data/lib/active_scaffold/config/core.rb +146 -18
  84. data/lib/active_scaffold/config/delete.rb +14 -1
  85. data/lib/active_scaffold/config/field_search.rb +7 -1
  86. data/lib/active_scaffold/config/form.rb +10 -1
  87. data/lib/active_scaffold/config/list.rb +39 -13
  88. data/lib/active_scaffold/config/mark.rb +4 -2
  89. data/lib/active_scaffold/config/nested.rb +16 -17
  90. data/lib/active_scaffold/config/search.rb +9 -0
  91. data/lib/active_scaffold/config/show.rb +4 -0
  92. data/lib/active_scaffold/config/update.rb +4 -0
  93. data/lib/active_scaffold/configurable.rb +14 -7
  94. data/lib/active_scaffold/constraints.rb +22 -20
  95. data/lib/active_scaffold/core.rb +68 -29
  96. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  97. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  98. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  99. data/lib/active_scaffold/data_structures/association/abstract.rb +41 -15
  100. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  101. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  102. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  103. data/lib/active_scaffold/data_structures/column.rb +75 -66
  104. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  105. data/lib/active_scaffold/data_structures/nested_info.rb +21 -19
  106. data/lib/active_scaffold/data_structures/set.rb +8 -0
  107. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  108. data/lib/active_scaffold/delayed_setup.rb +16 -5
  109. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  110. data/lib/active_scaffold/extensions/action_view_rendering.rb +34 -14
  111. data/lib/active_scaffold/extensions/cow_proxy.rb +91 -0
  112. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  113. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  114. data/lib/active_scaffold/extensions/localize.rb +3 -1
  115. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  116. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  117. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  118. data/lib/active_scaffold/finder.rb +104 -73
  119. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  120. data/lib/active_scaffold/helpers/association_helpers.rb +21 -19
  121. data/lib/active_scaffold/helpers/controller_helpers.rb +23 -10
  122. data/lib/active_scaffold/helpers/form_column_helpers.rb +157 -121
  123. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  124. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  125. data/lib/active_scaffold/helpers/list_column_helpers.rb +82 -53
  126. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  127. data/lib/active_scaffold/helpers/search_column_helpers.rb +29 -34
  128. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  129. data/lib/active_scaffold/helpers/view_helpers.rb +38 -35
  130. data/lib/active_scaffold/marked_model.rb +2 -2
  131. data/lib/active_scaffold/orm_checks.rb +3 -7
  132. data/lib/active_scaffold/paginator.rb +7 -7
  133. data/lib/active_scaffold/registry.rb +33 -0
  134. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  135. data/lib/active_scaffold/tableless.rb +67 -65
  136. data/lib/active_scaffold/version.rb +2 -2
  137. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  138. data/lib/generators/active_scaffold/install_generator.rb +1 -1
  139. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  140. data/shoulda_macros/macros.rb +3 -1
  141. data/test/bridges/date_picker_test.rb +1 -2
  142. data/test/bridges/paperclip_test.rb +6 -6
  143. data/test/class_with_finder.rb +2 -2
  144. data/test/company.rb +4 -4
  145. data/test/config/create_test.rb +4 -2
  146. data/test/config/nested_test.rb +1 -1
  147. data/test/config/show_test.rb +1 -1
  148. data/test/config/update_test.rb +7 -6
  149. data/test/data_structures/action_columns_test.rb +2 -2
  150. data/test/data_structures/action_links_test.rb +1 -1
  151. data/test/data_structures/column_test.rb +3 -6
  152. data/test/data_structures/columns_test.rb +2 -2
  153. data/test/data_structures/sorting_test.rb +7 -0
  154. data/test/extensions/active_record_test.rb +4 -4
  155. data/test/extensions/routing_mapper_test.rb +2 -2
  156. data/test/helpers/list_column_helpers_test.rb +3 -1
  157. data/test/misc/active_record_permissions_test.rb +3 -11
  158. data/test/misc/attribute_params_test.rb +12 -8
  159. data/test/misc/calculation_test.rb +1 -1
  160. data/test/misc/configurable_test.rb +10 -10
  161. data/test/misc/constraints_test.rb +2 -2
  162. data/test/misc/convert_numbers_format_test.rb +7 -3
  163. data/test/misc/lang_test.rb +1 -1
  164. data/test/misc/parse_datetime_test.rb +3 -4
  165. data/test/misc/tableless_test.rb +6 -0
  166. data/test/mock_app/Rakefile +1 -1
  167. data/test/mock_app/app/assets/config/manifest.js +0 -0
  168. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  169. data/test/mock_app/app/controllers/people_controller.rb +3 -1
  170. data/test/mock_app/config/application.rb +2 -1
  171. data/test/mock_app/config/boot.rb +1 -1
  172. data/test/mock_app/config/environment.rb +2 -2
  173. data/test/mock_app/config/routes.rb +4 -1
  174. data/test/mock_app/db/schema.rb +2 -0
  175. data/test/performance/list_cars_performance_test.rb +34 -0
  176. data/test/performance/list_people_performance_test.rb +31 -0
  177. data/test/performance_test_help.rb +3 -0
  178. data/test/test_helper.rb +10 -2
  179. metadata +56 -15
  180. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  181. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -7
@@ -17,17 +17,10 @@ module ActiveScaffold
17
17
  ## Delegates
18
18
  ##
19
19
 
20
- # access to the configuration variable
21
- def active_scaffold_config
22
- controller.class.active_scaffold_config
23
- end
24
-
25
- def active_scaffold_config_for(*args)
26
- controller.class.active_scaffold_config_for(*args)
27
- end
28
-
29
- def active_scaffold_controller_for(*args)
30
- controller.class.active_scaffold_controller_for(*args)
20
+ def active_scaffold_controller_for(klass)
21
+ ActiveScaffold::Registry.cache :as_controller, klass do
22
+ controller.class.active_scaffold_controller_for(klass)
23
+ end
31
24
  end
32
25
 
33
26
  ##
@@ -44,7 +37,10 @@ module ActiveScaffold
44
37
  # This is the template finder logic, keep it updated with however we find stuff in rails
45
38
  # currently this very similar to the logic in ActionBase::Base.render for options file
46
39
  def template_exists?(template_name, partial = false)
47
- restore_view_paths, lookup_context.view_paths = lookup_context.view_paths, @_view_paths if @_view_paths
40
+ if @_view_paths
41
+ restore_view_paths = lookup_context.view_paths
42
+ lookup_context.view_paths = @_view_paths
43
+ end
48
44
  lookup_context.exists?(template_name, '', partial).tap do
49
45
  lookup_context.view_paths = restore_view_paths if @_view_paths
50
46
  end
@@ -62,17 +58,22 @@ module ActiveScaffold
62
58
 
63
59
  # a general-use loading indicator (the "stuff is happening, please wait" feedback)
64
60
  def loading_indicator_tag(options)
65
- image_tag 'active_scaffold/indicator.gif', :style => 'visibility:hidden;', :id => loading_indicator_id(options), :alt => 'loading indicator', :class => 'loading-indicator'
61
+ # it's call many times and we can cache same result
62
+ @_loading_indicator_path ||= image_path('active_scaffold/indicator.gif')
63
+ # it's call many times in long lists, image_tag is a bit slower
64
+ tag :img, src: @_loading_indicator_path, style: 'visibility:hidden;', id: loading_indicator_id(options), alt: 'loading indicator', class: 'loading-indicator'
66
65
  end
67
66
 
68
67
  # Creates a javascript-based link that toggles the visibility of some element on the page.
69
- # By default, it toggles the visibility of the sibling after the one it's nested in. You may pass custom javascript logic in options[:of] to change that, though. For example, you could say :of => '$("my_div_id")'.
68
+ # By default, it toggles the visibility of the sibling after the one it's nested in.
69
+ # You may pass custom javascript logic in options[:of] to change that, though. For example, you could say :of => '$("my_div_id")'.
70
70
  # You may also flag whether the other element is visible by default or not, and the initial text will adjust accordingly.
71
71
  def link_to_visibility_toggle(id, options = {})
72
- options[:default_visible] = true if options[:default_visible].nil?
73
72
  options[:hide_label] ||= as_(:hide)
74
73
  options[:show_label] ||= as_(:show_block)
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'
74
+ label = options[:default_visible].nil? || options[:default_visible] ? options[:hide_label] : options[:show_label]
75
+ data = {:show => options[:show_label], :hide => options[:hide_label], :toggable => id}
76
+ link_to label, '#', :data => data, :style => 'display: none;', :class => 'as-js-button visibility-toggle'
76
77
  end
77
78
 
78
79
  def list_row_class_method(record)
@@ -86,6 +87,10 @@ module ActiveScaffold
86
87
  class_override_helper ? send(class_override_helper, record) : ''
87
88
  end
88
89
 
90
+ def list_row_attributes(tr_class, tr_id, data_refresh)
91
+ {class: "record #{tr_class}", id: tr_id, data: {refresh: data_refresh}}
92
+ end
93
+
89
94
  def column_attributes(column, record)
90
95
  method = override_helper column, 'column_attributes'
91
96
  return send(method, record) if method
@@ -93,15 +98,14 @@ module ActiveScaffold
93
98
  end
94
99
 
95
100
  def column_class(column, column_value, record)
96
- @_column_classes ||= {}
97
- @_column_classes[column.name] ||= begin
101
+ classes = ActiveScaffold::Registry.cache :column_classes, column.cache_key do
98
102
  classes = "#{column.name}-column "
99
103
  classes << 'sorted ' if active_scaffold_config.actions.include?(:list) && active_scaffold_config.list.user.sorting.sorts_on?(column)
100
104
  classes << 'numeric ' if column.number?
101
- classes << column.css_class unless column.css_class.nil? || column.css_class.is_a?(Proc)
105
+ classes << column.css_class << ' ' unless column.css_class.nil? || column.css_class.is_a?(Proc)
102
106
  classes
103
107
  end
104
- classes = "#{@_column_classes[column.name]} "
108
+ classes = classes.dup
105
109
  classes << 'empty ' if column_empty? column_value
106
110
  classes << 'in_place_editor_field ' if inplace_edit?(record, column) || column.list_ui == :marked
107
111
  if column.css_class.is_a?(Proc)
@@ -124,18 +128,23 @@ module ActiveScaffold
124
128
  classes
125
129
  end
126
130
 
131
+ def as_main_div_data
132
+ params[:eid] ? {eid: id_from_controller(params[:eid])} : {}
133
+ end
134
+
127
135
  def column_empty?(column_value)
136
+ @_empty_values ||= ['&nbsp;', empty_field_text].compact
128
137
  empty = column_value.nil?
129
138
  # column_value != false would force boolean to be cast to integer
130
139
  # when comparing to column_value of IPAddr class (PostgreSQL inet column type)
131
- # rubocop:disable Style/YodaCondition
132
- empty ||= false != column_value && column_value.blank?
133
- empty ||= ['&nbsp;', empty_field_text].include? column_value if column_value.is_a? String
140
+ empty ||= false != column_value && column_value.blank? # rubocop:disable Style/YodaCondition
141
+ empty ||= @_empty_values.include? column_value
134
142
  empty
135
143
  end
136
144
 
137
145
  def empty_field_text
138
- active_scaffold_config.list.empty_field_text if active_scaffold_config.actions.include?(:list)
146
+ return @_empty_field_text if defined? @_empty_field_text
147
+ @_empty_field_text = (active_scaffold_config.list.empty_field_text if active_scaffold_config.actions.include?(:list))
139
148
  end
140
149
 
141
150
  def as_slider(options)
@@ -156,11 +165,7 @@ module ActiveScaffold
156
165
  end
157
166
 
158
167
  def override_helper(column, suffix)
159
- hash = @_override_helpers ||= {}
160
- hash = hash[suffix] ||= {}
161
- hash = hash[column.active_record_class.name] ||= {}
162
- return hash[column.name] if hash.include? column.name
163
- hash[column.name] = begin
168
+ ActiveScaffold::Registry.cache suffix, column.cache_key do
164
169
  method_with_class = override_helper_name(column, suffix, true)
165
170
  if respond_to?(method_with_class)
166
171
  method_with_class
@@ -173,7 +178,7 @@ module ActiveScaffold
173
178
 
174
179
  def history_state
175
180
  if active_scaffold_config.store_user_settings
176
- state = {page: @page.try(:number)}
181
+ state = {page: @page&.number}
177
182
  state[:search] = search_params if respond_to?(:search_params) && search_params.present?
178
183
  if active_scaffold_config.list.user.user_sorting?
179
184
  column, state[:sort_direction] = active_scaffold_config.list.user.sorting.first
@@ -189,12 +194,12 @@ module ActiveScaffold
189
194
 
190
195
  def display_message(message)
191
196
  message = safe_join message, tag(:br) if message.is_a?(Array)
192
- if (highlights = active_scaffold_config.highlight_messages)
197
+ if (highlights = active_scaffold_config.user.highlight_messages)
193
198
  message = highlights.inject(message) do |msg, (phrases, highlighter)|
194
199
  highlight(msg, phrases, highlighter || {})
195
200
  end
196
201
  end
197
- if (format = active_scaffold_config.timestamped_messages)
202
+ if (format = active_scaffold_config.user.timestamped_messages)
198
203
  format = :short if format == true
199
204
  messages = [content_tag(:div, l(Time.current, :format => format), :class => 'timestamp')]
200
205
  messages << content_tag(:div, message, :class => 'message-content')
@@ -211,9 +216,7 @@ module ActiveScaffold
211
216
  object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model)
212
217
  object = convert_to_model(object)
213
218
 
214
- if object.class.respond_to?(:model_name)
215
- options[:object_name] ||= object.class.model_name.human.downcase
216
- end
219
+ options[:object_name] ||= object.class.model_name.human.downcase if object.class.respond_to?(:model_name)
217
220
 
218
221
  object
219
222
  end
@@ -24,11 +24,11 @@ module ActiveScaffold
24
24
 
25
25
  module ClassMethods
26
26
  def marked_records
27
- Thread.current[:marked_records] ||= {}
27
+ ActiveScaffold::Registry.marked_records ||= {}
28
28
  end
29
29
 
30
30
  def marked_records=(marked)
31
- Thread.current[:marked_records] = marked
31
+ ActiveScaffold::Registry.marked_records = marked
32
32
  end
33
33
 
34
34
  def marked_record_ids
@@ -43,7 +43,7 @@ module ActiveScaffold
43
43
  elsif mongoid? klass
44
44
  klass.fields
45
45
  else
46
- []
46
+ {}
47
47
  end
48
48
  end
49
49
 
@@ -69,13 +69,9 @@ module ActiveScaffold
69
69
 
70
70
  def type_for_attribute(klass, column_name)
71
71
  if active_record? klass
72
- if klass.respond_to? :type_for_attribute
73
- klass.type_for_attribute column_name.to_s
74
- else # Rails.version < 4.2
75
- klass.column_types[column_name.to_s]
76
- end
72
+ klass.type_for_attribute column_name.to_s
77
73
  elsif mongoid? klass
78
- klass.fields[column_name.to_s].type
74
+ klass.fields[column_name.to_s]&.type
79
75
  end
80
76
  end
81
77
 
@@ -19,16 +19,15 @@ class Paginator
19
19
  # (and the number of items to show per page, for
20
20
  # convenience, if the arity is 2)
21
21
  def initialize(count, per_page, &select)
22
- @count, @per_page = count, per_page
23
- unless select
24
- raise MissingSelectError, 'Must provide block to select data for each page'
25
- end
22
+ @count = count
23
+ @per_page = per_page
24
+ raise MissingSelectError, 'Must provide block to select data for each page' unless select
26
25
  @select = select
27
26
  end
28
27
 
29
28
  # Total number of pages
30
29
  def number_of_pages
31
- (@count / @per_page).to_i + (@count % @per_page > 0 ? 1 : 0)
30
+ (@count / @per_page).to_i + ((@count % @per_page).positive? ? 1 : 0)
32
31
  end
33
32
 
34
33
  # First page object
@@ -57,7 +56,7 @@ class Paginator
57
56
 
58
57
  # Retrieve page object by number
59
58
  def page(number)
60
- number = (n = number.to_i) > 0 ? n : 1
59
+ number = [1, number.to_i].max
61
60
  Page.new(self, number) do
62
61
  offset = (number - 1) * @per_page
63
62
  args = [offset]
@@ -80,7 +79,8 @@ class Paginator
80
79
  attr_reader :number, :pager
81
80
 
82
81
  def initialize(pager, number, &select) #:nodoc:
83
- @pager, @number = pager, number
82
+ @pager = pager
83
+ @number = number
84
84
  @offset = (number - 1) * pager.per_page
85
85
  @select = select
86
86
  end
@@ -0,0 +1,33 @@
1
+ module ActiveScaffold
2
+ class Registry
3
+ extend ActiveSupport::PerThreadRegistry
4
+ attr_accessor :current_user_proc, :current_ability_proc, :marked_records
5
+
6
+ def user_settings
7
+ @user_settings ||= {}
8
+ end
9
+
10
+ def constraint_columns
11
+ @constraint_columns ||= Hash.new { |h, k| h[k] = [] }
12
+ end
13
+
14
+ def unauthorized_columns
15
+ @unauthorized_columns ||= Hash.new { |h, k| h[k] = [] }
16
+ end
17
+
18
+ def cache(kind, key = nil, &block)
19
+ unless key
20
+ key = kind
21
+ kind = :cache
22
+ end
23
+ @cache ||= {}
24
+ cache = @cache[kind] ||= {}
25
+ return cache[key] if cache.include? key
26
+ cache[key] ||= yield
27
+ end
28
+
29
+ def self.instance
30
+ RequestStore.store[@per_thread_registry_key] ||= new
31
+ end
32
+ end
33
+ end
@@ -9,11 +9,12 @@ module ActiveScaffold
9
9
  return unless performed?
10
10
 
11
11
  # Either pull out a redirect or the request body
12
- script = if response.headers['Location']
13
- "document.location.href = '#{self.class.helpers.escape_javascript response.headers.delete('Location').to_s}'"
14
- else
15
- response.body || ''
16
- end
12
+ script =
13
+ if response.headers['Location']
14
+ "document.location.href = '#{self.class.helpers.escape_javascript response.headers.delete('Location').to_s}'"
15
+ else
16
+ response.body || ''
17
+ end
17
18
  response.status = 200 if (300...400).cover? response.status
18
19
 
19
20
  # Eval in parent scope and replace document location of this frame
@@ -34,12 +35,8 @@ module ActiveScaffold
34
35
  instance_variable_set(:@_response_body, nil)
35
36
  end
36
37
 
37
- # We're returning HTML instead of JS now
38
- if Rails.version < '4.1'
39
- render text: script, content_type: 'text/html' # remove when rails 4.0 is not supported
40
- else
41
- render html: script.html_safe, content_type: 'text/html' # rubocop:disable Rails/OutputSafety
42
- end
38
+ # We're returning HTML instead of JS now, content_type needed if not inside respond_to block
39
+ render html: script.html_safe, content_type: 'text/html' # rubocop:disable Rails/OutputSafety
43
40
  end
44
41
  alias respond_to_parent responds_to_parent
45
42
  end
@@ -1,10 +1,8 @@
1
- class ActiveScaffold::Tableless < ActiveRecord::Base
1
+ class ActiveScaffold::Tableless < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord
2
2
  class AssociationScope < ActiveRecord::Associations::AssociationScope
3
- if defined?(ActiveRecord::Associations::AssociationScope::INSTANCE) # rails >= 4.1
4
- INSTANCE = respond_to?(:create) ? create : new # create for rails >= 4.2
5
- def self.scope(association, connection)
6
- INSTANCE.scope association, connection
7
- end
3
+ INSTANCE = create
4
+ def self.scope(association, connection)
5
+ INSTANCE.scope association, connection
8
6
  end
9
7
 
10
8
  if Rails.version < '5.0.0'
@@ -19,11 +17,9 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
19
17
  end
20
18
  end
21
19
 
22
- if Rails.version >= '4.1'
23
- def add_constraints(scope, owner, assoc_klass, refl, tracker)
24
- tracker.instance_variable_set(:@assoc_klass, assoc_klass)
25
- super
26
- end
20
+ def add_constraints(scope, owner, assoc_klass, refl, tracker)
21
+ tracker.instance_variable_set(:@assoc_klass, assoc_klass)
22
+ super
27
23
  end
28
24
  end
29
25
  end
@@ -46,7 +42,7 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
46
42
  metadata = ActiveRecord::Base.connection.send :fetch_type_metadata, sql_type
47
43
  super(name, default, metadata, null)
48
44
  end
49
- elsif Rails.version >= '4.2.0'
45
+ else
50
46
  def initialize(name, default, sql_type = nil, null = true)
51
47
  cast_type = ActiveRecord::Base.connection.send :lookup_cast_type, sql_type
52
48
  super(name, default, cast_type, sql_type, null)
@@ -55,16 +51,18 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
55
51
  end
56
52
 
57
53
  module Tableless
58
- def association_scope
59
- @association_scope ||= overrided_association_scope if klass < ActiveScaffold::Tableless
60
- super
61
- end
54
+ if Rails.version < '5.2.0'
55
+ def skip_statement_cache?
56
+ klass < ActiveScaffold::Tableless ? true : super
57
+ end
62
58
 
63
- def overrided_association_scope
64
- if AssociationScope.respond_to?(:scope) # rails >= 4.1
65
- AssociationScope.scope(self, klass.connection)
66
- else # rails < 4.1
67
- AssociationScope.new(self).scope
59
+ def association_scope
60
+ @association_scope ||= AssociationScope.scope(self, klass.connection) if klass < ActiveScaffold::Tableless
61
+ super
62
+ end
63
+ else
64
+ def skip_statement_cache?(scope)
65
+ klass < ActiveScaffold::Tableless ? true : super
68
66
  end
69
67
  end
70
68
 
@@ -84,19 +82,19 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
84
82
  end
85
83
 
86
84
  module TablelessCollectionAssociation
87
- def get_records
85
+ def get_records # rubocop:disable Naming/AccessorMethodName
88
86
  klass < ActiveScaffold::Tableless ? scope.to_a : super
89
87
  end
90
88
  end
91
89
 
92
90
  module CollectionAssociation
93
91
  def self.included(base)
94
- base.prepend TablelessCollectionAssociation if Rails.version >= '4.2'
92
+ base.prepend TablelessCollectionAssociation
95
93
  end
96
94
  end
97
95
 
98
96
  module TablelessSingularAssociation
99
- def get_records
97
+ def get_records # rubocop:disable Naming/AccessorMethodName
100
98
  klass < ActiveScaffold::Tableless ? scope.limit(1).to_a : super
101
99
  end
102
100
  end
@@ -110,20 +108,13 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
110
108
  module RelationExtension
111
109
  attr_reader :conditions
112
110
 
113
- if Rails.version >= '5.0'
114
- def initialize(klass, table, predicate_builder, values = {})
115
- super
116
- @conditions ||= []
117
- end
118
- else
119
- def initialize(klass, table)
120
- super
121
- @conditions ||= []
122
- end
111
+ def initialize(klass, *)
112
+ super
113
+ @conditions ||= []
123
114
  end
124
115
 
125
116
  def initialize_copy(other)
126
- @conditions = @conditions.try(:dup) || []
117
+ @conditions = @conditions&.dup || []
127
118
  super
128
119
  end
129
120
 
@@ -135,9 +126,9 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
135
126
  self
136
127
  end
137
128
 
138
- def merge(r)
129
+ def merge(rel)
139
130
  super.tap do |merged|
140
- merged.conditions.concat r.conditions unless r.nil? || r.is_a?(Array)
131
+ merged.conditions.concat rel.conditions unless rel.nil? || rel.is_a?(Array)
141
132
  end
142
133
  end
143
134
 
@@ -167,41 +158,55 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
167
158
  private
168
159
 
169
160
  def relation
170
- args = [self, arel_table]
171
- args << predicate_builder if Rails.version >= '5.0.0'
161
+ args = [self]
162
+ if Rails.version < '5.2.0'
163
+ args << arel_table
164
+ args << predicate_builder if Rails.version >= '5.0.0'
165
+ end
172
166
  ActiveScaffold::Tableless::Relation.new(*args)
173
167
  end
168
+
169
+ if Rails.version >= '5.2'
170
+ def cached_find_by_statement(key, &block)
171
+ StatementCache.new(key, self, &block)
172
+ end
173
+ end
174
174
  end
175
175
 
176
176
  class StatementCache
177
- def initialize(key)
177
+ def initialize(key, model = nil)
178
178
  @key = key
179
+ @model = model
179
180
  end
180
181
 
181
- def execute(values, model, connection)
182
- model.where(@key => values)
182
+ if Rails.version < '5.2' # 5.0 and 5.1
183
+ def execute(values, model, connection)
184
+ model.where(@key => values)
185
+ end
186
+ else
187
+ def execute(values, connection)
188
+ @model.where(@key => values)
189
+ end
183
190
  end
184
191
  end
185
192
 
186
- unless Rails.version < '4.2'
187
- def self.columns_hash
188
- if self < ActiveScaffold::Tableless
189
- @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
190
- else
191
- super
192
- end
193
- end
194
- if Rails.version >= '5.0'
195
- def self.initialize_find_by_cache
196
- @find_by_statement_cache = {
197
- true => Hash.new { |h, k| h[k] = StatementCache.new(k) },
198
- false => Hash.new { |h, k| h[k] = StatementCache.new(k) }
199
- }
200
- end
193
+ def self.columns_hash
194
+ if self < ActiveScaffold::Tableless
195
+ @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
201
196
  else
202
- def self.initialize_find_by_cache
203
- self.find_by_statement_cache = Hash.new { |h, k| h[k] = StatementCache.new(k) }
204
- end
197
+ super
198
+ end
199
+ end
200
+ if Rails.version < '5.0' # 4.2.x
201
+ def self.initialize_find_by_cache
202
+ self.find_by_statement_cache = Hash.new { |h, k| h[k] = StatementCache.new(k) } # rubocop:disable Rails/DynamicFindBy
203
+ end
204
+ elsif Rails.version < '5.2' # 5.0 and 5.1
205
+ def self.initialize_find_by_cache
206
+ @find_by_statement_cache = {
207
+ true => Hash.new { |h, k| h[k] = StatementCache.new(k) },
208
+ false => Hash.new { |h, k| h[k] = StatementCache.new(k) }
209
+ }
205
210
  end
206
211
  end
207
212
 
@@ -236,11 +241,10 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
236
241
  end
237
242
 
238
243
  def self.execute_simple_calculation(relation, operation, column_name, distinct)
239
- if operation == 'count' && [relation.klass.primary_key, :all].include?(column_name)
240
- find_all(relation).size
241
- else
244
+ unless operation == 'count' && [relation.klass.primary_key, :all].include?(column_name)
242
245
  raise "self.execute_simple_calculation must be implemented in a Tableless model to support #{operation} #{column_name}#{' distinct' if distinct} columns"
243
246
  end
247
+ find_all(relation).size
244
248
  end
245
249
 
246
250
  def destroy
@@ -250,10 +254,8 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
250
254
  def _create_record #:nodoc:
251
255
  run_callbacks(:create) {}
252
256
  end
253
- alias create_record _create_record # for rails4 < 4.0.6, < 4.1.2
254
257
 
255
258
  def _update_record(*) #:nodoc:
256
259
  run_callbacks(:update) {}
257
260
  end
258
- alias update_record _update_record # for rails4 < 4.0.6, < 4.1.2
259
261
  end