active_scaffold 3.5.5 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGELOG → CHANGELOG.rdoc} +75 -0
  3. data/README.md +21 -10
  4. data/app/assets/javascripts/active_scaffold.js.erb +0 -1
  5. data/app/assets/javascripts/jquery/active_scaffold.js +98 -7
  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.html.erb +2 -1
  11. data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +3 -2
  12. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +26 -10
  13. data/app/views/active_scaffold_overrides/_horizontal_subform.html.erb +4 -4
  14. data/app/views/active_scaffold_overrides/_horizontal_subform_header.html.erb +2 -1
  15. data/app/views/active_scaffold_overrides/_list.html.erb +2 -1
  16. data/app/views/active_scaffold_overrides/_list_header.html.erb +5 -7
  17. data/app/views/active_scaffold_overrides/_list_messages.html.erb +1 -0
  18. data/app/views/active_scaffold_overrides/_list_record.html.erb +4 -5
  19. data/app/views/active_scaffold_overrides/_list_with_header.html.erb +1 -1
  20. data/app/views/active_scaffold_overrides/_messages.html.erb +1 -0
  21. data/app/views/active_scaffold_overrides/_refresh_list.js.erb +4 -0
  22. data/app/views/active_scaffold_overrides/_render_field.js.erb +2 -1
  23. data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -1
  24. data/app/views/active_scaffold_overrides/_show_columns.html.erb +2 -2
  25. data/app/views/active_scaffold_overrides/_show_horizontal_record.html.erb +4 -4
  26. data/app/views/active_scaffold_overrides/_update_calculations.js.erb +1 -1
  27. data/app/views/active_scaffold_overrides/_update_column.js.erb +2 -2
  28. data/app/views/active_scaffold_overrides/_vertical_subform.html.erb +2 -2
  29. data/app/views/active_scaffold_overrides/action_confirmation.html.erb +2 -2
  30. data/app/views/active_scaffold_overrides/delete.html.erb +2 -2
  31. data/app/views/active_scaffold_overrides/on_action_update.js.erb +16 -6
  32. data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
  33. data/app/views/active_scaffold_overrides/row.js.erb +1 -1
  34. data/app/views/active_scaffold_overrides/update_column.js.erb +2 -2
  35. data/config/locales/de.yml +2 -1
  36. data/config/locales/en.yml +1 -0
  37. data/config/locales/es.yml +1 -0
  38. data/config/locales/fr.yml +2 -1
  39. data/config/locales/hu.yml +1 -0
  40. data/config/locales/ja.yml +1 -0
  41. data/config/locales/ru.yml +1 -0
  42. data/lib/active_scaffold.rb +19 -16
  43. data/lib/active_scaffold/actions/common_search.rb +11 -8
  44. data/lib/active_scaffold/actions/core.rb +91 -70
  45. data/lib/active_scaffold/actions/create.rb +28 -28
  46. data/lib/active_scaffold/actions/delete.rb +3 -3
  47. data/lib/active_scaffold/actions/field_search.rb +53 -43
  48. data/lib/active_scaffold/actions/list.rb +111 -27
  49. data/lib/active_scaffold/actions/nested.rb +65 -48
  50. data/lib/active_scaffold/actions/search.rb +1 -1
  51. data/lib/active_scaffold/actions/show.rb +4 -4
  52. data/lib/active_scaffold/actions/subform.rb +23 -22
  53. data/lib/active_scaffold/actions/update.rb +96 -77
  54. data/lib/active_scaffold/active_record_permissions.rb +2 -11
  55. data/lib/active_scaffold/attribute_params.rb +102 -94
  56. data/lib/active_scaffold/bridges.rb +8 -8
  57. data/lib/active_scaffold/bridges/active_storage.rb +6 -0
  58. data/lib/active_scaffold/bridges/active_storage/active_storage_bridge.rb +34 -0
  59. data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +54 -0
  60. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +22 -0
  61. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +36 -0
  62. data/lib/active_scaffold/bridges/bitfields.rb +2 -1
  63. data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +12 -15
  64. data/lib/active_scaffold/bridges/bitfields/list_ui.rb +19 -0
  65. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +1 -1
  66. data/lib/active_scaffold/bridges/cancan/cancan_bridge.rb +3 -12
  67. data/lib/active_scaffold/bridges/carrierwave/carrierwave_bridge.rb +1 -1
  68. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +2 -2
  69. data/lib/active_scaffold/bridges/chosen/helpers.rb +7 -6
  70. data/lib/active_scaffold/bridges/date_picker/ext.rb +0 -13
  71. data/lib/active_scaffold/bridges/date_picker/helper.rb +49 -44
  72. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +1 -1
  73. data/lib/active_scaffold/bridges/file_column/as_file_column_bridge.rb +1 -1
  74. data/lib/active_scaffold/bridges/file_column/file_column_helpers.rb +3 -3
  75. data/lib/active_scaffold/bridges/file_column/form_ui.rb +3 -3
  76. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +10 -7
  77. data/lib/active_scaffold/bridges/paper_trail.rb +1 -1
  78. data/lib/active_scaffold/bridges/paper_trail/actions.rb +3 -1
  79. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  80. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge.rb +1 -1
  81. data/lib/active_scaffold/bridges/paperclip/paperclip_bridge_helpers.rb +2 -2
  82. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -17
  83. data/lib/active_scaffold/bridges/shared/date_bridge.rb +20 -19
  84. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +3 -1
  85. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +21 -4
  86. data/lib/active_scaffold/config/base.rb +133 -41
  87. data/lib/active_scaffold/config/core.rb +146 -18
  88. data/lib/active_scaffold/config/delete.rb +14 -1
  89. data/lib/active_scaffold/config/field_search.rb +7 -1
  90. data/lib/active_scaffold/config/form.rb +10 -1
  91. data/lib/active_scaffold/config/list.rb +39 -13
  92. data/lib/active_scaffold/config/mark.rb +4 -2
  93. data/lib/active_scaffold/config/nested.rb +16 -17
  94. data/lib/active_scaffold/config/search.rb +9 -0
  95. data/lib/active_scaffold/config/show.rb +4 -0
  96. data/lib/active_scaffold/config/update.rb +4 -0
  97. data/lib/active_scaffold/configurable.rb +14 -7
  98. data/lib/active_scaffold/constraints.rb +22 -20
  99. data/lib/active_scaffold/core.rb +67 -28
  100. data/lib/active_scaffold/data_structures/action_columns.rb +50 -59
  101. data/lib/active_scaffold/data_structures/action_link.rb +50 -20
  102. data/lib/active_scaffold/data_structures/action_links.rb +15 -13
  103. data/lib/active_scaffold/data_structures/association/abstract.rb +38 -15
  104. data/lib/active_scaffold/data_structures/association/active_mongoid.rb +2 -6
  105. data/lib/active_scaffold/data_structures/association/active_record.rb +6 -2
  106. data/lib/active_scaffold/data_structures/association/mongoid.rb +0 -3
  107. data/lib/active_scaffold/data_structures/column.rb +75 -66
  108. data/lib/active_scaffold/data_structures/columns.rb +3 -2
  109. data/lib/active_scaffold/data_structures/nested_info.rb +33 -19
  110. data/lib/active_scaffold/data_structures/set.rb +8 -0
  111. data/lib/active_scaffold/data_structures/sorting.rb +10 -2
  112. data/lib/active_scaffold/delayed_setup.rb +16 -5
  113. data/lib/active_scaffold/extensions/action_controller_rendering.rb +3 -2
  114. data/lib/active_scaffold/extensions/action_view_rendering.rb +93 -32
  115. data/lib/active_scaffold/extensions/cow_proxy.rb +95 -0
  116. data/lib/active_scaffold/extensions/ice_nine.rb +36 -0
  117. data/lib/active_scaffold/extensions/left_outer_joins.rb +8 -33
  118. data/lib/active_scaffold/extensions/localize.rb +3 -1
  119. data/lib/active_scaffold/extensions/routing_mapper.rb +6 -45
  120. data/lib/active_scaffold/extensions/to_label.rb +3 -2
  121. data/lib/active_scaffold/extensions/unsaved_record.rb +2 -4
  122. data/lib/active_scaffold/finder.rb +110 -77
  123. data/lib/active_scaffold/helpers/action_link_helpers.rb +62 -36
  124. data/lib/active_scaffold/helpers/association_helpers.rb +18 -16
  125. data/lib/active_scaffold/helpers/controller_helpers.rb +34 -10
  126. data/lib/active_scaffold/helpers/form_column_helpers.rb +196 -124
  127. data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -1
  128. data/lib/active_scaffold/helpers/id_helpers.rb +6 -2
  129. data/lib/active_scaffold/helpers/list_column_helpers.rb +90 -57
  130. data/lib/active_scaffold/helpers/pagination_helpers.rb +2 -2
  131. data/lib/active_scaffold/helpers/search_column_helpers.rb +43 -41
  132. data/lib/active_scaffold/helpers/show_column_helpers.rb +3 -5
  133. data/lib/active_scaffold/helpers/view_helpers.rb +39 -36
  134. data/lib/active_scaffold/marked_model.rb +2 -2
  135. data/lib/active_scaffold/orm_checks.rb +3 -7
  136. data/lib/active_scaffold/paginator.rb +7 -7
  137. data/lib/active_scaffold/registry.rb +33 -0
  138. data/lib/active_scaffold/responds_to_parent.rb +8 -11
  139. data/lib/active_scaffold/tableless.rb +83 -67
  140. data/lib/active_scaffold/version.rb +2 -2
  141. data/lib/generators/active_scaffold/controller_generator.rb +2 -2
  142. data/lib/generators/active_scaffold/install_generator.rb +52 -4
  143. data/lib/generators/active_scaffold/resource_generator.rb +2 -2
  144. data/shoulda_macros/macros.rb +3 -1
  145. data/test/bridges/date_picker_test.rb +1 -2
  146. data/test/bridges/paperclip_test.rb +6 -6
  147. data/test/class_with_finder.rb +2 -2
  148. data/test/company.rb +4 -4
  149. data/test/config/create_test.rb +4 -2
  150. data/test/config/nested_test.rb +1 -1
  151. data/test/config/show_test.rb +1 -1
  152. data/test/config/update_test.rb +7 -6
  153. data/test/data_structures/action_columns_test.rb +2 -2
  154. data/test/data_structures/action_links_test.rb +1 -1
  155. data/test/data_structures/column_test.rb +3 -6
  156. data/test/data_structures/columns_test.rb +2 -2
  157. data/test/data_structures/sorting_test.rb +7 -0
  158. data/test/extensions/action_view_rendering_test.rb +20 -0
  159. data/test/extensions/active_record_test.rb +4 -4
  160. data/test/extensions/routing_mapper_test.rb +2 -2
  161. data/test/helpers/list_column_helpers_test.rb +3 -1
  162. data/test/misc/active_record_permissions_test.rb +3 -11
  163. data/test/misc/attribute_params_test.rb +12 -8
  164. data/test/misc/calculation_test.rb +1 -1
  165. data/test/misc/configurable_test.rb +10 -10
  166. data/test/misc/constraints_test.rb +3 -3
  167. data/test/misc/convert_numbers_format_test.rb +7 -3
  168. data/test/misc/lang_test.rb +1 -1
  169. data/test/misc/parse_datetime_test.rb +3 -4
  170. data/test/misc/tableless_test.rb +14 -0
  171. data/test/mock_app/Rakefile +1 -1
  172. data/test/mock_app/app/assets/config/manifest.js +0 -0
  173. data/test/mock_app/app/controllers/cars_controller.rb +1 -0
  174. data/test/mock_app/app/controllers/people_controller.rb +5 -1
  175. data/test/mock_app/app/controllers/roles_controller.rb +4 -0
  176. data/test/mock_app/app/views/active_scaffold_overrides/_form.html.erb +2 -0
  177. data/test/mock_app/app/views/active_scaffold_overrides/list.html.erb +2 -0
  178. data/test/mock_app/app/views/people/_first_name_form_column.html.erb +2 -0
  179. data/test/mock_app/app/views/people/_form.html.erb +2 -0
  180. data/test/mock_app/app/views/people/list.html.erb +2 -0
  181. data/test/mock_app/config/application.rb +2 -1
  182. data/test/mock_app/config/boot.rb +1 -1
  183. data/test/mock_app/config/environment.rb +2 -2
  184. data/test/mock_app/config/routes.rb +4 -1
  185. data/test/mock_app/db/schema.rb +2 -0
  186. data/test/performance/list_cars_performance_test.rb +34 -0
  187. data/test/performance/list_people_performance_test.rb +31 -0
  188. data/test/performance_test_help.rb +3 -0
  189. data/test/test_helper.rb +12 -4
  190. metadata +71 -15
  191. data/app/assets/javascripts/prototype/rico_corner.js +0 -370
  192. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +0 -7
@@ -14,12 +14,10 @@ module ActiveScaffold
14
14
  # second, check if the dev has specified a valid list_ui for this column
15
15
  elsif column.show_ui && (method = override_show_column_ui(column.show_ui))
16
16
  send(method, value_record, column)
17
+ elsif column.column && (method = override_show_column_ui(column.column.type))
18
+ send(method, value_record, column)
17
19
  else
18
- if column.column && (method = override_show_column_ui(column.column.type))
19
- send(method, value_record, column)
20
- else
21
- get_column_value(record, column)
22
- end
20
+ get_column_value(record, column)
23
21
  end
24
22
  end
25
23
 
@@ -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,8 +37,11 @@ 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
48
- lookup_context.exists?(template_name, '', partial).tap do
40
+ if @_view_paths
41
+ restore_view_paths = lookup_context.view_paths
42
+ lookup_context.view_paths = @_view_paths
43
+ end
44
+ (@_lookup_context || lookup_context).exists?(template_name, '', partial).tap do
49
45
  lookup_context.view_paths = restore_view_paths if @_view_paths
50
46
  end
51
47
  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
@@ -38,15 +34,21 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
38
34
  def columns(table_name)
39
35
  klass.columns
40
36
  end
37
+
38
+ if Rails.version >= '6.0.0'
39
+ def data_sources
40
+ klass ? [klass.table_name] : []
41
+ end
42
+ end
41
43
  end
42
44
 
43
45
  class Column < ActiveRecord::ConnectionAdapters::Column
44
46
  if Rails.version >= '5.0.0'
45
- def initialize(name, default, sql_type = nil, null = true)
47
+ def initialize(name, default, sql_type = nil, null = true, **)
46
48
  metadata = ActiveRecord::Base.connection.send :fetch_type_metadata, sql_type
47
49
  super(name, default, metadata, null)
48
50
  end
49
- elsif Rails.version >= '4.2.0'
51
+ else
50
52
  def initialize(name, default, sql_type = nil, null = true)
51
53
  cast_type = ActiveRecord::Base.connection.send :lookup_cast_type, sql_type
52
54
  super(name, default, cast_type, sql_type, null)
@@ -55,16 +57,18 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
55
57
  end
56
58
 
57
59
  module Tableless
58
- def association_scope
59
- @association_scope ||= overrided_association_scope if klass < ActiveScaffold::Tableless
60
- super
61
- end
60
+ if Rails.version < '5.2.0'
61
+ def skip_statement_cache?
62
+ klass < ActiveScaffold::Tableless ? true : super
63
+ end
62
64
 
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
65
+ def association_scope
66
+ @association_scope ||= AssociationScope.scope(self, klass.connection) if klass < ActiveScaffold::Tableless
67
+ super
68
+ end
69
+ else
70
+ def skip_statement_cache?(scope)
71
+ klass < ActiveScaffold::Tableless ? true : super
68
72
  end
69
73
  end
70
74
 
@@ -84,19 +88,19 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
84
88
  end
85
89
 
86
90
  module TablelessCollectionAssociation
87
- def get_records
91
+ def get_records # rubocop:disable Naming/AccessorMethodName
88
92
  klass < ActiveScaffold::Tableless ? scope.to_a : super
89
93
  end
90
94
  end
91
95
 
92
96
  module CollectionAssociation
93
97
  def self.included(base)
94
- base.prepend TablelessCollectionAssociation if Rails.version >= '4.2'
98
+ base.prepend TablelessCollectionAssociation
95
99
  end
96
100
  end
97
101
 
98
102
  module TablelessSingularAssociation
99
- def get_records
103
+ def get_records # rubocop:disable Naming/AccessorMethodName
100
104
  klass < ActiveScaffold::Tableless ? scope.limit(1).to_a : super
101
105
  end
102
106
  end
@@ -110,20 +114,13 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
110
114
  module RelationExtension
111
115
  attr_reader :conditions
112
116
 
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
117
+ def initialize(klass, *)
118
+ super
119
+ @conditions ||= []
123
120
  end
124
121
 
125
122
  def initialize_copy(other)
126
- @conditions = @conditions.try(:dup) || []
123
+ @conditions = @conditions&.dup || []
127
124
  super
128
125
  end
129
126
 
@@ -135,9 +132,9 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
135
132
  self
136
133
  end
137
134
 
138
- def merge(r)
135
+ def merge(rel)
139
136
  super.tap do |merged|
140
- merged.conditions.concat r.conditions unless r.nil? || r.is_a?(Array)
137
+ merged.conditions.concat rel.conditions unless rel.nil? || rel.is_a?(Array)
141
138
  end
142
139
  end
143
140
 
@@ -158,50 +155,72 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
158
155
  def execute_simple_calculation(operation, column_name, distinct)
159
156
  @klass.execute_simple_calculation(self, operation, column_name, distinct)
160
157
  end
158
+
159
+ def implicit_order_column
160
+ @klass.implicit_order_column
161
+ end
162
+
163
+ def exists?
164
+ limit(1).to_a.present?
165
+ end
161
166
  end
162
167
 
163
- class Relation < ActiveRecord::Relation
168
+ class Relation < ::ActiveRecord::Relation
164
169
  include RelationExtension
165
170
  end
166
171
  class << self
167
172
  private
168
173
 
169
174
  def relation
170
- args = [self, arel_table]
171
- args << predicate_builder if Rails.version >= '5.0.0'
175
+ args = [self]
176
+ if Rails.version < '5.2.0'
177
+ args << arel_table
178
+ args << predicate_builder if Rails.version >= '5.0.0'
179
+ end
172
180
  ActiveScaffold::Tableless::Relation.new(*args)
173
181
  end
182
+
183
+ if Rails.version >= '5.2'
184
+ def cached_find_by_statement(key, &block)
185
+ StatementCache.new(key, self, &block)
186
+ end
187
+ end
174
188
  end
175
189
 
176
190
  class StatementCache
177
- def initialize(key)
191
+ def initialize(key, model = nil)
178
192
  @key = key
193
+ @model = model
179
194
  end
180
195
 
181
- def execute(values, model, connection)
182
- model.where(@key => values)
196
+ if Rails.version < '5.2' # 5.0 and 5.1
197
+ def execute(values, model, connection)
198
+ model.where(@key => values)
199
+ end
200
+ else
201
+ def execute(values, connection)
202
+ @model.where(@key => values)
203
+ end
183
204
  end
184
205
  end
185
206
 
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
207
+ def self.columns_hash
208
+ if self < ActiveScaffold::Tableless
209
+ @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
201
210
  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
211
+ super
212
+ end
213
+ end
214
+ if Rails.version < '5.0' # 4.2.x
215
+ def self.initialize_find_by_cache
216
+ self.find_by_statement_cache = Hash.new { |h, k| h[k] = StatementCache.new(k) } # rubocop:disable Rails/DynamicFindBy
217
+ end
218
+ elsif Rails.version < '5.2' # 5.0 and 5.1
219
+ def self.initialize_find_by_cache
220
+ @find_by_statement_cache = {
221
+ true => Hash.new { |h, k| h[k] = StatementCache.new(k) },
222
+ false => Hash.new { |h, k| h[k] = StatementCache.new(k) }
223
+ }
205
224
  end
206
225
  end
207
226
 
@@ -236,11 +255,10 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
236
255
  end
237
256
 
238
257
  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
258
+ unless operation == 'count' && [relation.klass.primary_key, :all].include?(column_name)
242
259
  raise "self.execute_simple_calculation must be implemented in a Tableless model to support #{operation} #{column_name}#{' distinct' if distinct} columns"
243
260
  end
261
+ find_all(relation).size
244
262
  end
245
263
 
246
264
  def destroy
@@ -250,10 +268,8 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
250
268
  def _create_record #:nodoc:
251
269
  run_callbacks(:create) {}
252
270
  end
253
- alias create_record _create_record # for rails4 < 4.0.6, < 4.1.2
254
271
 
255
272
  def _update_record(*) #:nodoc:
256
273
  run_callbacks(:update) {}
257
274
  end
258
- alias update_record _update_record # for rails4 < 4.0.6, < 4.1.2
259
275
  end