active_scaffold 3.5.2 → 3.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -23,6 +23,7 @@ module ActiveScaffold::DataStructures
23
23
  @active_record_class = active_record_class
24
24
  @_inheritable = []
25
25
  @set = []
26
+ @sorted = nil
26
27
 
27
28
  add(*args)
28
29
  end
@@ -48,8 +49,8 @@ module ActiveScaffold::DataStructures
48
49
  column = self[association]
49
50
  raise ArgumentError, "unknown column #{association}" if column.nil?
50
51
  raise ArgumentError, "column #{association} is not an association" if column.association.nil?
51
- raise ArugmentError, "column #{association} is not singular association" unless column.association.singular?
52
- raise ArugmentError, "column #{association} is polymorphic association" if column.association.polymorphic?
52
+ raise ArgumentError, "column #{association} is not singular association" unless column.association.singular?
53
+ raise ArgumentError, "column #{association} is polymorphic association" if column.association.polymorphic?
53
54
 
54
55
  klass = column.association.klass
55
56
  columns.each do |col|
@@ -31,7 +31,7 @@ module ActiveScaffold::DataStructures
31
31
  false
32
32
  end
33
33
 
34
- def has_many?
34
+ def has_many? # rubocop:disable Naming/PredicateName
35
35
  false
36
36
  end
37
37
 
@@ -39,7 +39,7 @@ module ActiveScaffold::DataStructures
39
39
  false
40
40
  end
41
41
 
42
- def has_one?
42
+ def has_one? # rubocop:disable Naming/PredicateName
43
43
  false
44
44
  end
45
45
 
@@ -74,7 +74,7 @@ module ActiveScaffold::DataStructures
74
74
  column = parent_scaffold.active_scaffold_config.columns[params[:association].to_sym]
75
75
  @param_name = column.model.name.foreign_key.to_sym
76
76
  @parent_id = params[@param_name]
77
- @association = column.try(:association)
77
+ @association = column&.association
78
78
  @child_association = association.reverse_association(model) if association
79
79
  setup_constrained_fields
80
80
  end
@@ -83,15 +83,17 @@ module ActiveScaffold::DataStructures
83
83
 
84
84
  # A through association with has_one or has_many as source association
85
85
  # create cannot be called in nested through associations, and not-nested through associations
86
- # unless create columns include through reflection of reverse association
86
+ # unless is through singular or create columns include through reflection of reverse association
87
87
  # e.g. customer -> networks -> firewall, reverse is firewall -> network -> customer,
88
88
  # firewall can be created if create columns include network
89
89
  def readonly_through_association?(columns)
90
90
  return false unless through_association?
91
- return true if association.through_reflection.options[:through]
92
- !association.source_reflection.belongs_to? && (
93
- !child_association || !columns.include?(child_association.through_reflection.name)
94
- )
91
+ return true if association.through_reflection.options[:through] # create not possible, too many levels
92
+ return true if association.source_reflection.options[:through] # create not possible, too many levels
93
+ return false if association.through_singular? # create allowed, AS has code for this
94
+
95
+ # create allowed only if through reflection in record to be created is included in create columns
96
+ !child_association || !columns.include?(child_association.through_reflection.name)
95
97
  end
96
98
 
97
99
  def through_association?
@@ -104,25 +106,25 @@ module ActiveScaffold::DataStructures
104
106
 
105
107
  def default_sorting(chain)
106
108
  return @default_sorting if defined? @default_sorting
107
- if association.scope.is_a?(Proc) && chain.respond_to?(:values) && chain.values[:order]
108
- @default_sorting = chain.values[:order]
109
- @default_sorting = @default_sorting.map(&:to_sql) if @default_sorting[0].is_a? Arel::Nodes::Node
110
- @default_sorting = @default_sorting.join(', ')
111
- end
109
+ return unless association.scope.is_a?(Proc) && chain.respond_to?(:values) && chain.values[:order]
110
+ @default_sorting = chain.values[:order]
111
+ @default_sorting = @default_sorting.map(&:to_sql) if @default_sorting[0].is_a? Arel::Nodes::Node
112
+ @default_sorting = @default_sorting.join(', ')
112
113
  end
113
114
 
114
115
  def to_params
115
- super.merge(:association => @association.name, :assoc_id => parent_id)
116
+ super.merge(:association => @association.name, @param_name => parent_id)
116
117
  end
117
118
 
118
119
  protected
119
120
 
120
121
  def setup_constrained_fields
121
- @constrained_fields = []
122
- @constrained_fields << Array(association.foreign_key).map(&:to_sym) unless association.belongs_to?
123
- if child_association && child_association != association
124
- @constrained_fields << child_association.name
125
- end
122
+ @constrained_fields = Array(association.foreign_key).map(&:to_sym) unless association.belongs_to?
123
+ @constrained_fields ||= []
124
+ return unless child_association && child_association != association
125
+
126
+ @constrained_fields << child_association.name
127
+ @constrained_fields << child_association.foreign_type.to_sym if child_association.polymorphic?
126
128
  end
127
129
  end
128
130
 
@@ -7,6 +7,10 @@ module ActiveScaffold::DataStructures
7
7
  set_values(*args)
8
8
  end
9
9
 
10
+ def initialize_dup(other)
11
+ @set = other.set.dup
12
+ end
13
+
10
14
  def set_values(*args)
11
15
  @set = []
12
16
  add(*args)
@@ -56,5 +60,9 @@ module ActiveScaffold::DataStructures
56
60
  def empty?
57
61
  @set.empty?
58
62
  end
63
+
64
+ protected
65
+
66
+ attr_reader :set
59
67
  end
60
68
  end
@@ -14,6 +14,7 @@ module ActiveScaffold::DataStructures
14
14
  @clauses = []
15
15
  @constraint_columns = []
16
16
  @model = model
17
+ @sorting_by_primary_key = false
17
18
  end
18
19
 
19
20
  def set_default_sorting
@@ -55,6 +56,9 @@ module ActiveScaffold::DataStructures
55
56
  # set({column => direction}, {column => direction})
56
57
  # set([column, direction], [column, direction])
57
58
  def set(*args)
59
+ # TODO: add deprecation unless args.size == 1 && args[0].is_a? Hash
60
+ # when deprecation is removed:
61
+ # * change list#sorting= to sorting.set(val)
58
62
  clear
59
63
  if args.first.is_a?(Enumerable)
60
64
  args.each do |h|
@@ -103,6 +107,10 @@ module ActiveScaffold::DataStructures
103
107
  @clauses.each { |clause| yield clause }
104
108
  end
105
109
 
110
+ def each_column
111
+ @clauses.each { |clause| yield clause[0] }
112
+ end
113
+
106
114
  # provides quick access to the first (and sometimes only) clause
107
115
  def first
108
116
  @clauses.first
@@ -120,7 +128,7 @@ module ActiveScaffold::DataStructures
120
128
  order = []
121
129
  each do |sort_column, sort_direction|
122
130
  next if constraint_columns.include? sort_column.name
123
- sql = grouped_columns_calculations.try(:dig, sort_column.name) || sort_column.sort[:sql]
131
+ sql = grouped_columns_calculations&.dig(sort_column.name) || sort_column.sort[:sql]
124
132
  next if sql.blank?
125
133
  sql = sql.to_sql if sql.respond_to?(:to_sql)
126
134
 
@@ -200,7 +208,7 @@ module ActiveScaffold::DataStructures
200
208
  end
201
209
 
202
210
  def postgres?
203
- model.connection.try(:adapter_name) == 'PostgreSQL'
211
+ model.connection&.adapter_name == 'PostgreSQL'
204
212
  end
205
213
 
206
214
  def setup_primary_key_order_clause
@@ -11,14 +11,25 @@ module ActiveScaffold
11
11
 
12
12
  module ClassMethods
13
13
  def active_scaffold(model_id = nil, &block)
14
- @active_scaffold_delayed = proc { super(model_id, &block) }
14
+ @delayed_monitor ||= Monitor.new
15
+ @active_scaffold_delayed = proc do
16
+ begin
17
+ @_prefixes = nil # clean prefixes in case is already cached, so our local_prefixes override is picked up
18
+ super(model_id, &block)
19
+ @active_scaffold_delayed = @delayed_monitor = nil # after configuring, no need to keep proc or monitor
20
+ rescue StandardError
21
+ # clear config variable if failed, so next request tries again
22
+ @active_scaffold_config = nil
23
+ raise
24
+ end
25
+ end
15
26
  end
16
27
 
17
28
  def config_active_scaffold_delayed
18
- return unless @active_scaffold_delayed
19
- @_prefixes = nil # clean prefixes in case is already cached, so our local_prefixes override is picked up
20
- block, @active_scaffold_delayed = @active_scaffold_delayed, nil
21
- block.call
29
+ @delayed_monitor&.synchronize do
30
+ # if called in same thread while running config, do nothing
31
+ @active_scaffold_delayed&.call unless @active_scaffold_config
32
+ end
22
33
  end
23
34
 
24
35
  def active_scaffold_config
@@ -5,9 +5,10 @@ module ActiveScaffold
5
5
  if self.class.uses_active_scaffold? && params[:adapter] && @rendering_adapter.nil? && request.xhr?
6
6
  @rendering_adapter = true # recursion control
7
7
  # if we need an adapter, then we render the actual stuff to a string and insert it into the adapter template
8
- opts = args.blank? ? {} : args.first
8
+ opts = args.any? ? args.first : {}
9
+
9
10
  render :partial => params[:adapter][1..-1],
10
- :locals => {:payload => render_to_string(opts.merge(:layout => false), &block).html_safe},
11
+ :locals => {:payload => render_to_string(opts.merge(:layout => false), &block).html_safe}, # rubocop:disable Rails/OutputSafety
11
12
  :use_full_path => true, :layout => false, :content_type => :html
12
13
  @rendering_adapter = nil # recursion control
13
14
  else
@@ -39,8 +39,12 @@ module ActiveScaffold #:nodoc:
39
39
  if args.first.is_a?(Hash) && args.first[:active_scaffold]
40
40
  render_embedded args.first
41
41
  elsif args.first == :super
42
- @_view_paths ||= lookup_context.view_paths.clone
43
- @_last_template ||= lookup_context.last_template
42
+ if @lookup_context # rails 6
43
+ @_lookup_context ||= lookup_context
44
+ else # rails < 6
45
+ @_view_paths ||= lookup_context.view_paths.clone
46
+ @_last_template ||= lookup_context.last_template
47
+ end
44
48
  parts = @virtual_path.split('/')
45
49
  template = parts.pop
46
50
  prefix = parts.join('/')
@@ -58,22 +62,34 @@ module ActiveScaffold #:nodoc:
58
62
  else
59
63
  options[:prefixes] = ['active_scaffold_overrides']
60
64
  last_view_path = File.expand_path(File.dirname(File.dirname(lookup_context.last_template.inspect)), Rails.root)
61
- lookup_context.view_paths = view_paths.drop(view_paths.find_index { |path| path.to_s == last_view_path } + 1)
65
+ new_view_paths = view_paths.drop(view_paths.find_index { |path| path.to_s == last_view_path } + 1)
66
+ if @lookup_context
67
+ @lookup_context = build_lookup_context(new_view_paths)
68
+ else
69
+ lookup_context.view_paths = new_view_paths
70
+ end
62
71
  end
63
72
  result = super options
64
- lookup_context.view_paths = @_view_paths if @_view_paths
65
- lookup_context.last_template = @_last_template if @_last_template
73
+ @lookup_context = @_lookup_context if @_lookup_context # rails 6
74
+ lookup_context.view_paths = @_view_paths if @_view_paths # rails < 6
75
+ lookup_context.last_template = @_last_template if @_last_template # rails < 6
66
76
  result
67
77
  else
68
- @_view_paths ||= lookup_context.view_paths.clone
78
+ if @lookup_context # rails 6
79
+ @_lookup_context ||= lookup_context
80
+ else # rails < 6
81
+ @_view_paths ||= lookup_context.view_paths.clone
82
+ end
69
83
  last_template = lookup_context.last_template
70
- current_view = if args[0].is_a?(Hash)
71
- {:locals => args[0][:locals], :object => args[0][:object]}
72
- else # call is render 'partial', locals_hash
73
- {:locals => args[1]}
74
- end
84
+ current_view =
85
+ if args[0].is_a?(Hash)
86
+ {locals: args[0][:locals], object: args[0][:object]}
87
+ else # call is render 'partial', locals_hash
88
+ {locals: args[1]}
89
+ end
75
90
  view_stack << current_view if current_view
76
- lookup_context.view_paths = @_view_paths # reset view_paths in case a view render :super, and then render :partial
91
+ @lookup_context = @_lookup_context if @_lookup_context # rails 6, reset lookup_context in case a view render :super, and then render :partial
92
+ lookup_context.view_paths = @_view_paths if @_view_paths # rails < 6, reset view_paths in case a view render :super, and then render :partial
77
93
  result = super
78
94
  view_stack.pop if current_view.present?
79
95
  lookup_context.last_template = last_template
@@ -114,9 +130,13 @@ module ActiveScaffold #:nodoc:
114
130
  content_tag(:div, :id => id, :class => 'active-scaffold-component', :data => {:refresh => url}) do
115
131
  # parse the ActiveRecord model name from the controller path, which
116
132
  # might be a namespaced controller (e.g., 'admin/admins')
117
- model = remote_controller.to_s.sub(/.*\//, '').singularize
133
+ model = remote_controller.to_s.sub(%r{.*/}, '').singularize
118
134
  content_tag(:div, :class => 'active-scaffold-header') do
119
- content_tag :h2, link_to(options[:label] || active_scaffold_config_for(model).list.label, url, :remote => true, :class => 'load-embedded')
135
+ content_tag(:h2) do
136
+ link_label = options[:label] || active_scaffold_config_for(model).list.label
137
+ link_to(link_label, url, remote: true, class: 'load-embedded', data: {error_msg: as_(:error_500)}) <<
138
+ loading_indicator_tag(url_options)
139
+ end
120
140
  end
121
141
  end
122
142
  end
@@ -0,0 +1,91 @@
1
+ require 'cow_proxy'
2
+
3
+ module CowProxy
4
+ module ActiveScaffold
5
+ module DataStructures
6
+ class Column < ::CowProxy::WrapClass(::ActiveScaffold::DataStructures::Column)
7
+ # readonly and called many times in list action
8
+ delegate :name, :cache_key, :delegated_association, :association, to: :__getobj__
9
+
10
+ def link
11
+ return @link if defined?(@link)
12
+ if __getobj__.frozen?
13
+ link_var = __getobj__.instance_variable_get(:@link)
14
+ if link_var.is_a?(Proc)
15
+ @link = link_var.call self
16
+ return @link
17
+ end
18
+ end
19
+ super
20
+ end
21
+ end
22
+
23
+ class Set < ::CowProxy::WrapClass(::ActiveScaffold::DataStructures::Set)
24
+ protected
25
+
26
+ # Copy wrapped values to duplicated wrapped object
27
+ # @see CowProxy::Base#__copy_on_write__
28
+ # @return duplicated wrapped object
29
+ def __copy_on_write__(*)
30
+ super.tap do
31
+ new_set = __getobj__.instance_variable_get(:@set).dup
32
+ __getobj__.instance_variable_set(:@set, new_set)
33
+ end
34
+ end
35
+ end
36
+
37
+ class ActionColumns < ::CowProxy::WrapClass(::ActiveScaffold::DataStructures::ActionColumns)
38
+ def each_column(options = {})
39
+ __getobj__.each_column(options.reverse_merge(core_columns: action.core.columns)) do |column|
40
+ if column.is_a?(::ActiveScaffold::DataStructures::ActionColumns)
41
+ yield ::CowProxy.wrap(column).tap { |group| group.action = action }
42
+ else
43
+ yield column
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ class ActionLinks < ::CowProxy::WrapClass(::ActiveScaffold::DataStructures::ActionLinks)
50
+ def method_missing(name, *args, &block)
51
+ CowProxy.debug { "method missing #{name} in #{__getobj__.name}" }
52
+ return super if name =~ /[!?]$/
53
+ subgroup =
54
+ if _instance_variable_defined?("@#{name}")
55
+ _instance_variable_get("@#{name}")
56
+ else
57
+ __copy_on_write__ if __getobj__.frozen?
58
+ group = __getobj__.subgroup(name, args.first)
59
+ if group.frozen?
60
+ group = __wrap__(group)
61
+ else
62
+ CowProxy.debug { "created subgroup #{group.name}" }
63
+ end
64
+ _instance_variable_set("@#{name}", group)
65
+ end
66
+ yield subgroup if block
67
+ subgroup
68
+ end
69
+
70
+ def respond_to_missing?(name, *)
71
+ name !~ /[!?]$/
72
+ end
73
+
74
+ protected
75
+
76
+ # Copy wrapped values to duplicated wrapped object
77
+ # @see CowProxy::Base#__copy_on_write__
78
+ # @return duplicated wrapped object
79
+ def __copy_on_write__(*)
80
+ index = @parent_proxy.instance_variable_get(:@set).index(__getobj__) if @parent_proxy
81
+ super.tap do
82
+ CowProxy.debug { "replace #{index} with proxy obj in parent #{@parent_proxy.name}" } if index
83
+ @parent_proxy.instance_variable_get(:@set)[index] = self if index
84
+ new_set = __getobj__.instance_variable_get(:@set).dup
85
+ __getobj__.instance_variable_set(:@set, new_set)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,36 @@
1
+ module IceNine
2
+ class Freezer
3
+ def self.find(name)
4
+ freezer = name.split('::').reduce(self) do |mod, const|
5
+ mod.const_lookup(const) or break mod # rubocop:disable Style/AndOr
6
+ end
7
+ freezer if freezer < self # only return a descendant freezer
8
+ end
9
+
10
+ class ObjectWithExclussion < Object
11
+ class_attribute :excluded_vars
12
+ self.excluded_vars = []
13
+ def self.freeze_instance_variables(object, recursion_guard)
14
+ object.instance_variables.each do |ivar_name|
15
+ next if excluded_vars.include? ivar_name
16
+ Freezer.guarded_deep_freeze(
17
+ object.instance_variable_get(ivar_name),
18
+ recursion_guard
19
+ )
20
+ end
21
+ end
22
+ private_class_method :freeze_instance_variables
23
+ end
24
+
25
+ class ActiveScaffold < ::IceNine::Freezer::Object
26
+ class DataStructures < ::IceNine::Freezer::Object
27
+ class Column < ::IceNine::Freezer::ObjectWithExclussion
28
+ self.excluded_vars = %i[@active_record_class @column]
29
+ end
30
+
31
+ class Association < ::IceNine::Freezer::NoFreeze
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -18,11 +18,6 @@ if Rails.version < '5.0.0'
18
18
  end
19
19
  alias left_joins left_outer_joins
20
20
 
21
- def outer_joins(*args)
22
- ActiveSupport::Deprecation.warn 'use left_outer_joins or left_joins which is added to Rails 5.0.0'
23
- left_outer_joins(*args)
24
- end
25
-
26
21
  def left_outer_joins!(*args)
27
22
  self.joins_values += [''] # HACK: for using left_outer_joins in update_all/delete_all
28
23
  self.left_outer_joins_values += args
@@ -30,39 +25,19 @@ if Rails.version < '5.0.0'
30
25
  end
31
26
  alias left_joins! left_outer_joins!
32
27
 
33
- def outer_joins!(*args)
34
- ActiveSupport::Deprecation.warn 'use left_outer_joins! or left_joins! which is added to Rails 5.0.0'
35
- left_outer_joins!(*args)
36
- end
37
-
38
- if Rails.version < '4.1'
39
- def build_arel
40
- if left_outer_joins_values.empty?
41
- super
42
- else
43
- relation = except(:left_outer_joins)
44
- join_dependency = ActiveRecord::Associations::JoinDependency.new(@klass, left_outer_joins_values, [])
45
- join_dependency.join_associations.each do |association|
46
- relation = association.join_relation(relation)
47
- end
48
- relation.build_arel
49
- end
50
- end
51
- else
52
- def build_arel
53
- if left_outer_joins_values.empty?
54
- super
55
- else
56
- relation = except(:left_outer_joins)
57
- relation.joins! ActiveRecord::Associations::JoinDependency.new(@klass, left_outer_joins_values, [])
58
- relation.build_arel
59
- end
28
+ def build_arel
29
+ if left_outer_joins_values.empty?
30
+ super
31
+ else
32
+ relation = except(:left_outer_joins)
33
+ relation.joins! ActiveRecord::Associations::JoinDependency.new(@klass, left_outer_joins_values, [])
34
+ relation.build_arel
60
35
  end
61
36
  end
62
37
  end
63
38
  end
64
39
  ActiveRecord::Relation.send :include, ActiveScaffold::OuterJoins
65
40
  module ActiveRecord::Querying
66
- delegate :left_outer_joins, :left_joins, :outer_joins, :to => :all
41
+ delegate :left_outer_joins, :left_joins, :to => :all
67
42
  end
68
43
  end