active_scaffold 3.6.20 → 3.7.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +27 -0
- data/README.md +27 -16
- data/app/assets/javascripts/jquery/active_scaffold.js +38 -6
- data/app/assets/javascripts/jquery/active_scaffold_chosen.js +6 -5
- data/app/assets/javascripts/jquery/tiny_mce_bridge.js +18 -4
- data/app/assets/stylesheets/active_scaffold_layout.css +12 -1
- data/app/views/active_scaffold_overrides/_base_form.html.erb +5 -1
- data/app/views/active_scaffold_overrides/_field_search.html.erb +1 -0
- data/app/views/active_scaffold_overrides/_render_field.js.erb +19 -11
- data/config/locales/ja.yml +59 -59
- data/lib/active_scaffold/actions/common_search.rb +2 -2
- data/lib/active_scaffold/actions/core.rb +30 -10
- data/lib/active_scaffold/actions/field_search.rb +9 -6
- data/lib/active_scaffold/actions/nested.rb +7 -7
- data/lib/active_scaffold/attribute_params.rb +19 -57
- data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +0 -3
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/active_storage.rb +3 -0
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -2
- data/lib/active_scaffold/bridges/date_picker/helper.rb +4 -4
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +4 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +2 -2
- data/lib/active_scaffold/bridges/tiny_mce.rb +1 -1
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +1 -6
- data/lib/active_scaffold/config/core.rb +1 -1
- data/lib/active_scaffold/config/field_search.rb +9 -1
- data/lib/active_scaffold/config/form.rb +9 -1
- data/lib/active_scaffold/core.rb +2 -8
- data/lib/active_scaffold/data_structures/action_columns.rb +0 -25
- data/lib/active_scaffold/data_structures/action_links.rb +1 -1
- data/lib/active_scaffold/data_structures/association/abstract.rb +8 -0
- data/lib/active_scaffold/data_structures/association/active_mongoid.rb +8 -0
- data/lib/active_scaffold/data_structures/association/active_record.rb +1 -13
- data/lib/active_scaffold/data_structures/association/mongoid.rb +21 -8
- data/lib/active_scaffold/data_structures/column.rb +31 -5
- data/lib/active_scaffold/data_structures/columns.rb +12 -12
- data/lib/active_scaffold/data_structures/nested_info.rb +12 -0
- data/lib/active_scaffold/data_structures/sorting.rb +1 -1
- data/lib/active_scaffold/engine.rb +0 -1
- data/lib/active_scaffold/extensions/action_view_rendering.rb +13 -5
- data/lib/active_scaffold/extensions/cow_proxy.rb +1 -1
- data/lib/active_scaffold/extensions/unsaved_record.rb +9 -3
- data/lib/active_scaffold/finder.rb +5 -1
- data/lib/active_scaffold/helpers/action_link_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/form_column_helpers.rb +48 -22
- data/lib/active_scaffold/helpers/list_column_helpers.rb +3 -2
- data/lib/active_scaffold/helpers/search_column_helpers.rb +8 -2
- data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
- data/lib/active_scaffold/registry.rb +10 -15
- data/lib/active_scaffold/tableless.rb +10 -79
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/active_scaffold.rb +0 -7
- data/lib/generators/active_scaffold/install_generator.rb +2 -2
- data/test/bridges/bridge_test.rb +1 -1
- data/test/bridges/paperclip_test.rb +16 -13
- data/test/bridges/tiny_mce_test.rb +1 -1
- data/test/config/base_test.rb +1 -1
- data/test/config/core_test.rb +1 -1
- data/test/config/create_test.rb +1 -1
- data/test/config/delete_test.rb +1 -1
- data/test/config/field_search_test.rb +1 -1
- data/test/config/list_test.rb +1 -1
- data/test/config/nested_test.rb +1 -1
- data/test/config/search_test.rb +1 -1
- data/test/config/show_test.rb +1 -1
- data/test/config/subform_test.rb +1 -1
- data/test/config/update_test.rb +1 -1
- data/test/data_structures/action_columns_test.rb +1 -1
- data/test/data_structures/action_link_test.rb +1 -1
- data/test/data_structures/action_links_test.rb +1 -1
- data/test/data_structures/actions_test.rb +1 -1
- data/test/data_structures/association_column_test.rb +1 -1
- data/test/data_structures/column_test.rb +1 -1
- data/test/data_structures/columns_test.rb +1 -1
- data/test/data_structures/set_test.rb +1 -1
- data/test/data_structures/sorting_test.rb +1 -1
- data/test/data_structures/standard_column_test.rb +1 -1
- data/test/data_structures/validation_reflection_test.rb +1 -1
- data/test/data_structures/virtual_column_test.rb +1 -1
- data/test/extensions/active_record_test.rb +1 -1
- data/test/helpers/pagination_helpers_test.rb +1 -1
- data/test/misc/active_record_permissions_test.rb +1 -1
- data/test/misc/attribute_params_test.rb +1 -1
- data/test/misc/calculation_test.rb +1 -1
- data/test/misc/configurable_test.rb +1 -1
- data/test/misc/constraints_test.rb +1 -1
- data/test/misc/convert_numbers_format_test.rb +1 -1
- data/test/misc/finder_test.rb +1 -1
- data/test/misc/lang_test.rb +1 -1
- data/test/misc/parse_datetime_test.rb +1 -1
- data/test/misc/tableless_test.rb +1 -1
- data/test/test_helper.rb +4 -4
- metadata +5 -13
- data/lib/active_scaffold/delayed_setup.rb +0 -41
- data/lib/active_scaffold/extensions/left_outer_joins.rb +0 -43
|
@@ -6,6 +6,7 @@ module ActiveScaffold::Actions
|
|
|
6
6
|
before_action :check_input_device
|
|
7
7
|
before_action :register_constraints_with_action_columns, :unless => :nested?
|
|
8
8
|
after_action :clear_flashes
|
|
9
|
+
after_action :dl_cookie
|
|
9
10
|
around_action :clear_storage
|
|
10
11
|
rescue_from ActiveScaffold::RecordNotAllowed, ActiveScaffold::ActionNotAllowed, :with => :deny_access
|
|
11
12
|
end
|
|
@@ -22,7 +23,7 @@ module ActiveScaffold::Actions
|
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def render_field
|
|
25
|
-
if request.get?
|
|
26
|
+
if request.get? || request.head?
|
|
26
27
|
render_field_for_inplace_editing
|
|
27
28
|
respond_to do |format|
|
|
28
29
|
format.js { render :action => 'render_field_inplace', :layout => false }
|
|
@@ -61,14 +62,18 @@ module ActiveScaffold::Actions
|
|
|
61
62
|
@source_id = params.delete(:source_id)
|
|
62
63
|
@columns = @column.update_columns || []
|
|
63
64
|
@scope = params.delete(:scope)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if @scope
|
|
66
|
+
@form_action = :subform
|
|
67
|
+
elsif active_scaffold_config.actions.include? params[:form_action]&.to_sym
|
|
68
|
+
@form_action = params.delete(:form_action).to_sym
|
|
69
|
+
end
|
|
70
|
+
@form_action ||= params[:id] ? :update : :create
|
|
71
|
+
@main_columns = active_scaffold_config.send(@form_action).columns
|
|
67
72
|
@columns << @column.name if @column.options[:refresh_link] && @columns.exclude?(@column.name)
|
|
68
73
|
|
|
69
74
|
@record =
|
|
70
75
|
if @column.send_form_on_update_column
|
|
71
|
-
updated_record_with_form(@main_columns, params[:record], @scope)
|
|
76
|
+
updated_record_with_form(@main_columns, params[:record] || params[:search], @scope)
|
|
72
77
|
else
|
|
73
78
|
updated_record_with_column(@column, params.delete(:value), @scope)
|
|
74
79
|
end
|
|
@@ -100,7 +105,14 @@ module ActiveScaffold::Actions
|
|
|
100
105
|
record = params[:id] ? copy_attributes(find_if_allowed(params[:id], :read)) : new_model
|
|
101
106
|
apply_constraints_to_record(record) unless scope || params[:id]
|
|
102
107
|
create_association_with_parent record, true if nested?
|
|
103
|
-
|
|
108
|
+
if @form_action == :field_search && value.is_a?(Array) && column.association&.singular?
|
|
109
|
+
# don't assign value if it's an array and column is singular association,
|
|
110
|
+
# e.g. value came from multi-select on search form
|
|
111
|
+
# use instance variable so it's available in the view and helpers
|
|
112
|
+
@value = value
|
|
113
|
+
else
|
|
114
|
+
update_column_from_params(record, column, value, true)
|
|
115
|
+
end
|
|
104
116
|
record.id = params[:id]
|
|
105
117
|
record
|
|
106
118
|
end
|
|
@@ -165,6 +177,10 @@ module ActiveScaffold::Actions
|
|
|
165
177
|
flash.clear if request.xhr?
|
|
166
178
|
end
|
|
167
179
|
|
|
180
|
+
def dl_cookie
|
|
181
|
+
cookies[params[:_dl_cookie]] = {value: Time.now.to_i, expires: 1.day.since} if params[:_dl_cookie]
|
|
182
|
+
end
|
|
183
|
+
|
|
168
184
|
def each_marked_record(&block)
|
|
169
185
|
active_scaffold_config.model.as_marked.each(&block)
|
|
170
186
|
end
|
|
@@ -248,7 +264,7 @@ module ActiveScaffold::Actions
|
|
|
248
264
|
@conditions_from_params ||= begin
|
|
249
265
|
conditions = [{}]
|
|
250
266
|
params.except(:controller, :action, :page, :sort, :sort_direction, :format, :id).each do |key, value|
|
|
251
|
-
distinct = true if key
|
|
267
|
+
distinct = true if key.match?(/!$/)
|
|
252
268
|
column = active_scaffold_config._columns_hash[key.to_s[0..(distinct ? -2 : -1)]]
|
|
253
269
|
next unless column
|
|
254
270
|
key = column.name.to_sym
|
|
@@ -321,7 +337,8 @@ module ActiveScaffold::Actions
|
|
|
321
337
|
|
|
322
338
|
def check_input_device
|
|
323
339
|
return unless session[:input_device_type].nil?
|
|
324
|
-
if request.env['HTTP_USER_AGENT']
|
|
340
|
+
return if request.env['HTTP_USER_AGENT'].nil?
|
|
341
|
+
if request.env['HTTP_USER_AGENT'].match?(/(iPhone|iPod|iPad)/i)
|
|
325
342
|
session[:input_device_type] = 'TOUCH'
|
|
326
343
|
session[:hover_supported] = false
|
|
327
344
|
else
|
|
@@ -362,14 +379,14 @@ module ActiveScaffold::Actions
|
|
|
362
379
|
# flash[:info] = 'Player fired'
|
|
363
380
|
# end
|
|
364
381
|
def process_action_link_action(render_action = :action_update, crud_type_or_security_options = nil)
|
|
365
|
-
if request.get?
|
|
382
|
+
if request.get? || request.head?
|
|
366
383
|
# someone has disabled javascript, we have to show confirmation form first
|
|
367
384
|
@record = find_if_allowed(params[:id], :read) if params[:id]
|
|
368
385
|
respond_to_action(:action_confirmation)
|
|
369
386
|
else
|
|
370
387
|
@action_link = active_scaffold_config.action_links[action_name]
|
|
371
388
|
if params[:id]
|
|
372
|
-
crud_type_or_security_options ||= {:crud_type => request.
|
|
389
|
+
crud_type_or_security_options ||= {:crud_type => request.delete? ? :delete : :update, :action => action_name}
|
|
373
390
|
get_row(crud_type_or_security_options)
|
|
374
391
|
if @record.nil?
|
|
375
392
|
self.successful = false
|
|
@@ -378,6 +395,9 @@ module ActiveScaffold::Actions
|
|
|
378
395
|
yield @record
|
|
379
396
|
end
|
|
380
397
|
else
|
|
398
|
+
if @action_link && respond_to?(@action_link.security_method, true) && !send(@action_link.security_method)
|
|
399
|
+
raise ActiveScaffold::ActionNotAllowed
|
|
400
|
+
end
|
|
381
401
|
yield
|
|
382
402
|
end
|
|
383
403
|
respond_to_action(render_action)
|
|
@@ -154,7 +154,6 @@ module ActiveScaffold::Actions
|
|
|
154
154
|
filtered_columns = []
|
|
155
155
|
text_search = active_scaffold_config.field_search.text_search
|
|
156
156
|
columns = active_scaffold_config.field_search.columns
|
|
157
|
-
count_includes = active_scaffold_config.list.user.count_includes
|
|
158
157
|
search_params.each do |key, value|
|
|
159
158
|
next unless columns.include? key
|
|
160
159
|
column = active_scaffold_config.columns[key]
|
|
@@ -164,11 +163,7 @@ module ActiveScaffold::Actions
|
|
|
164
163
|
active_scaffold_conditions << search_condition
|
|
165
164
|
filtered_columns << column
|
|
166
165
|
end
|
|
167
|
-
|
|
168
|
-
active_scaffold_outer_joins.concat filtered_columns.map(&:search_joins).flatten.uniq.compact
|
|
169
|
-
else
|
|
170
|
-
set_outer_joins_for_search filtered_columns
|
|
171
|
-
end
|
|
166
|
+
setup_joins_for_filtered_columns(filtered_columns)
|
|
172
167
|
if filtered_columns.present? || grouped_search?
|
|
173
168
|
@filtered = active_scaffold_config.field_search.human_conditions ? filtered_columns : true
|
|
174
169
|
end
|
|
@@ -182,6 +177,14 @@ module ActiveScaffold::Actions
|
|
|
182
177
|
|
|
183
178
|
private
|
|
184
179
|
|
|
180
|
+
def setup_joins_for_filtered_columns(filtered_columns)
|
|
181
|
+
if grouped_search? || active_scaffold_config.list.user.count_includes.present?
|
|
182
|
+
active_scaffold_outer_joins.concat filtered_columns.map(&:search_joins).flatten.uniq.compact
|
|
183
|
+
else
|
|
184
|
+
set_outer_joins_for_search filtered_columns
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
185
188
|
def field_search_formats
|
|
186
189
|
(default_formats + active_scaffold_config.formats + active_scaffold_config.field_search.formats).uniq
|
|
187
190
|
end
|
|
@@ -8,7 +8,7 @@ module ActiveScaffold::Actions
|
|
|
8
8
|
base.module_eval do
|
|
9
9
|
before_action :set_nested
|
|
10
10
|
before_action :configure_nested
|
|
11
|
-
include ActiveScaffold::Actions::Nested::ChildMethods if active_scaffold_config.
|
|
11
|
+
include ActiveScaffold::Actions::Nested::ChildMethods if active_scaffold_config.columns.map(&:association).compact.any?(&:habtm?)
|
|
12
12
|
end
|
|
13
13
|
base.before_action :include_habtm_actions
|
|
14
14
|
base.helper_method :nested
|
|
@@ -120,9 +120,9 @@ module ActiveScaffold::Actions
|
|
|
120
120
|
|
|
121
121
|
def create_association_with_parent?(check_match = false)
|
|
122
122
|
# has_many is done by beginning_of_chain and rails if direct association, not in through associations
|
|
123
|
-
return false
|
|
123
|
+
return false unless nested.create_with_parent?
|
|
124
124
|
return false if check_match && !nested.match_model?(active_scaffold_config.model)
|
|
125
|
-
|
|
125
|
+
nested_parent_record.present?
|
|
126
126
|
end
|
|
127
127
|
|
|
128
128
|
def create_association_with_parent(record, check_match = false)
|
|
@@ -131,7 +131,7 @@ module ActiveScaffold::Actions
|
|
|
131
131
|
record.send("#{nested.child_association.name}=", nested_parent_record)
|
|
132
132
|
elsif nested.create_through_singular?
|
|
133
133
|
through = nested_parent_record.send(nested.association.through_reflection.name) ||
|
|
134
|
-
|
|
134
|
+
nested_parent_record.send("build_#{nested.association.through_reflection.name}")
|
|
135
135
|
if nested.source_reflection.reverse_association.collection?
|
|
136
136
|
record.send(nested.source_reflection.reverse) << through
|
|
137
137
|
else
|
|
@@ -167,7 +167,7 @@ module ActiveScaffold::Actions::Nested
|
|
|
167
167
|
end
|
|
168
168
|
|
|
169
169
|
def destroy_existing
|
|
170
|
-
return redirect_to(params.merge(:action => :delete, :only_path => true)) if request.get?
|
|
170
|
+
return redirect_to(params.merge(:action => :delete, :only_path => true)) if request.get? || request.head?
|
|
171
171
|
do_destroy_existing
|
|
172
172
|
respond_to_action(:destroy_existing)
|
|
173
173
|
end
|
|
@@ -247,8 +247,8 @@ module ActiveScaffold::Actions::Nested
|
|
|
247
247
|
parent_record = nested_parent_record(:update)
|
|
248
248
|
@record = active_scaffold_config.model.find(params[:associated_id])
|
|
249
249
|
if parent_record && @record
|
|
250
|
-
parent_record.send(nested.association.name) << @record
|
|
251
|
-
parent_record.save
|
|
250
|
+
self.successful = false unless parent_record.send(nested.association.name) << @record
|
|
251
|
+
parent_record.save if successful?
|
|
252
252
|
else
|
|
253
253
|
false
|
|
254
254
|
end
|
|
@@ -33,41 +33,10 @@ module ActiveScaffold
|
|
|
33
33
|
module AttributeParams
|
|
34
34
|
protected
|
|
35
35
|
|
|
36
|
-
# workaround to update counters when polymorphic has_many changes on persisted record
|
|
37
|
-
# TODO: remove when rails4 support is removed or counter cache for polymorphic has_many association works on rails4
|
|
38
|
-
def hack_for_has_many_counter_cache(parent_record, column, value)
|
|
39
|
-
association = parent_record.association(column.name)
|
|
40
|
-
counter_attr = association.send(:cached_counter_attribute_name)
|
|
41
|
-
difference = value.select(&:persisted?).size - parent_record.send(counter_attr)
|
|
42
|
-
|
|
43
|
-
if parent_record.new_record?
|
|
44
|
-
parent_record.send "#{column.name}=", value
|
|
45
|
-
parent_record.send "#{counter_attr}_will_change!"
|
|
46
|
-
else
|
|
47
|
-
# don't decrement counter for deleted records, on destroy they will update counter
|
|
48
|
-
difference += (parent_record.send(column.name) - value).size
|
|
49
|
-
association.send :update_counter, difference unless difference.zero?
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# update counters on old parents if belongs_to is changed
|
|
53
|
-
value.select(&:persisted?).each do |record|
|
|
54
|
-
key = record.send(column.association.foreign_key)
|
|
55
|
-
parent_record.class.decrement_counter counter_attr, key if key && key != parent_record.id # rubocop:disable Rails/SkipsModelValidations
|
|
56
|
-
end
|
|
57
|
-
parent_record.send "#{column.name}=", value if parent_record.persisted?
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# rails 4 needs this hack for polymorphic has_many
|
|
61
|
-
# TODO: remove when hack_for_has_many_counter_cache is not needed
|
|
62
|
-
def hack_for_has_many_counter_cache?(parent_record, column)
|
|
63
|
-
column.association.counter_cache_hack? && parent_record.association(column.name).send(:has_cached_counter?)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
36
|
# workaround for updating counters twice bug on rails4 (https://github.com/rails/rails/pull/14849)
|
|
67
|
-
# rails 4 needs this hack for non-polymorphic belongs_to, when selecting record, not creating new one (value is Hash)
|
|
68
37
|
# rails 5 needs this hack for belongs_to, when selecting record, not creating new one (value is Hash)
|
|
69
|
-
# TODO: remove when
|
|
70
|
-
def
|
|
38
|
+
# TODO: remove when rails5 support is removed
|
|
39
|
+
def belongs_to_counter_cache_hack?(association, value)
|
|
71
40
|
!params_hash?(value) && association.belongs_to? && association.counter_cache_hack?
|
|
72
41
|
end
|
|
73
42
|
|
|
@@ -92,21 +61,19 @@ module ActiveScaffold
|
|
|
92
61
|
multi_parameter_attrs = multi_parameter_attributes(attributes)
|
|
93
62
|
|
|
94
63
|
columns.each_column(for: parent_record, crud_type: crud_type, flatten: true) do |column|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
column.params.select { |p| attributes.key? p }.each { |p| parent_record.send("#{p}=", attributes[p]) }
|
|
64
|
+
# Set any passthrough parameters that may be associated with this column (ie, file column "keep" and "temp" attributes)
|
|
65
|
+
column.params.select { |p| attributes.key? p }.each { |p| parent_record.send("#{p}=", attributes[p]) }
|
|
98
66
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
end
|
|
104
|
-
rescue StandardError => e
|
|
105
|
-
message = "on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect} "\
|
|
106
|
-
"(value from params #{attributes[column.name].inspect})"
|
|
107
|
-
Rails.logger.error "#{e.class.name}: #{e.message} -- #{message}"
|
|
108
|
-
raise
|
|
67
|
+
if multi_parameter_attrs.key? column.name.to_s
|
|
68
|
+
parent_record.send(:assign_multiparameter_attributes, multi_parameter_attrs[column.name.to_s])
|
|
69
|
+
elsif attributes.key? column.name
|
|
70
|
+
update_column_from_params(parent_record, column, attributes[column.name], avoid_changes)
|
|
109
71
|
end
|
|
72
|
+
rescue StandardError => e
|
|
73
|
+
message = "on the ActiveScaffold column = :#{column.name} for #{parent_record.inspect} "\
|
|
74
|
+
"(value from params #{attributes[column.name].inspect})"
|
|
75
|
+
Rails.logger.error "#{e.class.name}: #{e.message} -- #{message}"
|
|
76
|
+
raise
|
|
110
77
|
end
|
|
111
78
|
|
|
112
79
|
parent_record
|
|
@@ -132,7 +99,7 @@ module ActiveScaffold
|
|
|
132
99
|
end
|
|
133
100
|
|
|
134
101
|
def update_column_association(parent_record, column, attribute, value)
|
|
135
|
-
if
|
|
102
|
+
if belongs_to_counter_cache_hack?(column.association, attribute)
|
|
136
103
|
parent_record.send "#{column.association.foreign_key}=", value&.id
|
|
137
104
|
parent_record.association(column.name).target = value
|
|
138
105
|
elsif column.association.collection? && column.association.through_singular?
|
|
@@ -140,8 +107,6 @@ module ActiveScaffold
|
|
|
140
107
|
through_record = parent_record.send(through)
|
|
141
108
|
through_record ||= parent_record.send "build_#{through}"
|
|
142
109
|
through_record.send "#{column.association.source_reflection.name}=", value
|
|
143
|
-
elsif hack_for_has_many_counter_cache?(parent_record, column)
|
|
144
|
-
hack_for_has_many_counter_cache(parent_record, column, value)
|
|
145
110
|
else
|
|
146
111
|
parent_record.send "#{column.name}=", value
|
|
147
112
|
end
|
|
@@ -184,7 +149,8 @@ module ActiveScaffold
|
|
|
184
149
|
|
|
185
150
|
def association_value_from_param_simple_value(parent_record, column, value)
|
|
186
151
|
if column.association.singular?
|
|
187
|
-
|
|
152
|
+
# value may be Array if using update_columns in field_search with multi-select
|
|
153
|
+
column.association.klass(parent_record)&.find(value) if value.present? && !value.is_a?(Array)
|
|
188
154
|
else # column.association.collection?
|
|
189
155
|
column_plural_assocation_value_from_value(column, Array(value))
|
|
190
156
|
end
|
|
@@ -327,13 +293,9 @@ module ActiveScaffold
|
|
|
327
293
|
if ActiveScaffold::OrmChecks.mongoid? klass
|
|
328
294
|
column.default_val
|
|
329
295
|
elsif ActiveScaffold::OrmChecks.active_record? klass
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
column_type = ActiveScaffold::OrmChecks.column_type(klass, column_name)
|
|
334
|
-
cast_type = ActiveRecord::Type.lookup column_type
|
|
335
|
-
cast_type ? cast_type.deserialize(column.default) : column.default
|
|
336
|
-
end
|
|
296
|
+
column_type = ActiveScaffold::OrmChecks.column_type(klass, column_name)
|
|
297
|
+
cast_type = ActiveRecord::Type.lookup column_type
|
|
298
|
+
cast_type ? cast_type.deserialize(column.default) : column.default
|
|
337
299
|
end
|
|
338
300
|
end
|
|
339
301
|
end
|
|
@@ -2,9 +2,6 @@ module ActiveScaffold
|
|
|
2
2
|
module Bridges
|
|
3
3
|
class ActiveStorage
|
|
4
4
|
module ActiveStorageBridgeHelpers
|
|
5
|
-
mattr_accessor :thumbnail_variant
|
|
6
|
-
self.thumbnail_variant = {resize_to_limit: [nil, 30]}
|
|
7
|
-
|
|
8
5
|
class << self
|
|
9
6
|
# has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: false
|
|
10
7
|
def active_storage_has_one_fields(klass)
|
|
@@ -22,7 +22,7 @@ module ActiveScaffold
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def link_for_attachment(attachment, column)
|
|
25
|
-
variant = column.options[:thumb] || ActiveScaffold::Bridges::ActiveStorage
|
|
25
|
+
variant = column.options[:thumb] || ActiveScaffold::Bridges::ActiveStorage.thumbnail_variant
|
|
26
26
|
content =
|
|
27
27
|
if variant && attachment.variable? && column.options[:thumb] != false
|
|
28
28
|
image_tag(attachment.variant(variant))
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
class ActiveScaffold::Bridges::ActiveStorage < ActiveScaffold::DataStructures::Bridge
|
|
2
|
+
cattr_accessor :thumbnail_variant
|
|
3
|
+
self.thumbnail_variant = {resize_to_limit: [nil, 30]}
|
|
4
|
+
|
|
2
5
|
def self.install
|
|
3
6
|
Dir[File.join(__dir__, 'active_storage', '*.rb')].each { |file| require file }
|
|
4
7
|
ActiveScaffold::Config::Core.send :prepend, ActiveScaffold::Bridges::ActiveStorage::ActiveStorageBridge
|
|
@@ -8,9 +8,9 @@ module ActiveScaffold
|
|
|
8
8
|
|
|
9
9
|
model.bitfields.each_value do |options|
|
|
10
10
|
columns << options.keys
|
|
11
|
-
options.
|
|
11
|
+
options.each_key.with_index(1) do |column, i|
|
|
12
12
|
columns[column].form_ui = :checkbox
|
|
13
|
-
columns[column].weight = 1000 +
|
|
13
|
+
columns[column].weight = 1000 + i
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module ActiveScaffold::Bridges
|
|
2
2
|
class DatePicker
|
|
3
3
|
module Helper
|
|
4
|
+
UNSUPPORTED_FORMAT_OPTIONS = /%[cUWwxXZ]/
|
|
4
5
|
DATE_FORMAT_CONVERSION = {
|
|
5
6
|
/%a/ => 'D',
|
|
6
7
|
/%A/ => 'DD',
|
|
@@ -19,7 +20,7 @@ module ActiveScaffold::Bridges
|
|
|
19
20
|
/%p/ => 'tt',
|
|
20
21
|
/%S/ => 'ss',
|
|
21
22
|
/%z/ => 'z',
|
|
22
|
-
|
|
23
|
+
UNSUPPORTED_FORMAT_OPTIONS => ''
|
|
23
24
|
}.freeze
|
|
24
25
|
|
|
25
26
|
def self.date_options_for_locales
|
|
@@ -83,9 +84,8 @@ module ActiveScaffold::Bridges
|
|
|
83
84
|
|
|
84
85
|
def self.to_datepicker_format(rails_format)
|
|
85
86
|
return nil if rails_format.nil?
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
options = unsupported.to_s.scan(/\[(.*)\]/).dig(0, 0)&.each_char&.map { |c| "%#{c}" }
|
|
87
|
+
if rails_format.match?(UNSUPPORTED_FORMAT_OPTIONS)
|
|
88
|
+
options = UNSUPPORTED_FORMAT_OPTIONS.to_s.scan(/\[(.*)\]/).dig(0, 0)&.each_char&.map { |c| "%#{c}" }
|
|
89
89
|
Rails.logger.warn(
|
|
90
90
|
"AS DatePicker::Helper: rails date format #{rails_format} includes options "\
|
|
91
91
|
"which can't be converted to jquery datepicker format. "\
|
|
@@ -12,7 +12,10 @@ module ActiveScaffold::Actions
|
|
|
12
12
|
def deleted
|
|
13
13
|
query = PaperTrail::Version.destroys.where(:item_type => active_scaffold_config.model.name)
|
|
14
14
|
if nested? && nested.child_association&.belongs_to? && PaperTrail::Version.respond_to?(:where_object)
|
|
15
|
-
|
|
15
|
+
foreign_key = nested.child_association.foreign_key
|
|
16
|
+
parent_id = nested.parent_id
|
|
17
|
+
parent_id = parent_id&.to_i if self.class.active_scaffold_config.columns[foreign_key]&.number?
|
|
18
|
+
query = query.where_object(foreign_key => parent_id)
|
|
16
19
|
end
|
|
17
20
|
pager = Paginator.new(query.count, active_scaffold_config.list.per_page) do |offset, per_page|
|
|
18
21
|
query.offset(offset).limit(per_page).map(&:reify)
|
|
@@ -51,7 +51,7 @@ class ActiveScaffold::Bridges::RecordSelect
|
|
|
51
51
|
else
|
|
52
52
|
record_select_field(options[:name], value || klass.new, record_select_options)
|
|
53
53
|
end
|
|
54
|
-
html = self.class.field_error_proc
|
|
54
|
+
html = instance_exec(html, self, &self.class.field_error_proc) if record.errors[column.name].any?
|
|
55
55
|
html
|
|
56
56
|
end
|
|
57
57
|
|
|
@@ -60,7 +60,7 @@ class ActiveScaffold::Bridges::RecordSelect
|
|
|
60
60
|
:controller => active_scaffold_controller_for(record.class).controller_path
|
|
61
61
|
).merge(column.options)
|
|
62
62
|
html = record_select_autocomplete(options[:name], record, record_select_options)
|
|
63
|
-
html = self.class.field_error_proc
|
|
63
|
+
html = instance_exec(html, self, &self.class.field_error_proc) if record.errors[column.name].any?
|
|
64
64
|
html
|
|
65
65
|
end
|
|
66
66
|
end
|
|
@@ -11,7 +11,7 @@ class ActiveScaffold::Bridges::TinyMce < ActiveScaffold::DataStructures::Bridge
|
|
|
11
11
|
def self.javascripts
|
|
12
12
|
case ActiveScaffold.js_framework
|
|
13
13
|
when :jquery
|
|
14
|
-
['tinymce
|
|
14
|
+
['tinymce', 'jquery/tiny_mce_bridge']
|
|
15
15
|
when :prototype
|
|
16
16
|
['tinymce', 'prototype/tiny_mce_bridge']
|
|
17
17
|
end
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
module ActiveScaffold::Bridges
|
|
2
2
|
class UsaStateSelect
|
|
3
3
|
module UsaStateSelectHelpers
|
|
4
|
-
def usa_state_select_options(options)
|
|
5
|
-
# TODO: remove when rails 3.2 support is dropped
|
|
6
|
-
defined?(ActionView::Helpers::InstanceTag) ? options[:object] : options
|
|
7
|
-
end
|
|
8
|
-
|
|
9
4
|
def usa_state_select(object, method, priority_states = nil, options = {}, html_options = {})
|
|
10
|
-
ActionView::Helpers::Tags::UsaStateSelect.new(object, method, self,
|
|
5
|
+
ActionView::Helpers::Tags::UsaStateSelect.new(object, method, self, options).to_usa_state_select_tag(priority_states, options, html_options)
|
|
11
6
|
end
|
|
12
7
|
end
|
|
13
8
|
|
|
@@ -112,7 +112,7 @@ module ActiveScaffold::Config
|
|
|
112
112
|
def columns=(val)
|
|
113
113
|
@columns._inheritable = val.collect(&:to_sym)
|
|
114
114
|
# Add virtual columns
|
|
115
|
-
@columns
|
|
115
|
+
@columns.add(*val)
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
# lets you override the global ActiveScaffold frontend for a specific controller
|
|
@@ -7,6 +7,7 @@ module ActiveScaffold::Config
|
|
|
7
7
|
super
|
|
8
8
|
@text_search = self.class.text_search
|
|
9
9
|
@human_conditions = self.class.human_conditions
|
|
10
|
+
@floating_footer = self.class.floating_footer
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
# global level configuration
|
|
@@ -29,6 +30,10 @@ module ActiveScaffold::Config
|
|
|
29
30
|
cattr_accessor :human_conditions, instance_accessor: false
|
|
30
31
|
@@human_conditions = false
|
|
31
32
|
|
|
33
|
+
# whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
|
|
34
|
+
class_attribute :floating_footer, instance_accessor: false
|
|
35
|
+
@@floating_footer = false
|
|
36
|
+
|
|
32
37
|
# instance-level configuration
|
|
33
38
|
# ----------------------------
|
|
34
39
|
|
|
@@ -71,8 +76,11 @@ module ActiveScaffold::Config
|
|
|
71
76
|
# instead of just filtered you may show the user a humanized search condition statment
|
|
72
77
|
attr_accessor :human_conditions
|
|
73
78
|
|
|
79
|
+
# whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
|
|
80
|
+
attr_accessor :floating_footer
|
|
81
|
+
|
|
74
82
|
UserSettings.class_eval do
|
|
75
|
-
user_attr :optional_columns, :group_options, :grouped_columns, :human_conditions
|
|
83
|
+
user_attr :optional_columns, :group_options, :grouped_columns, :human_conditions, :floating_footer
|
|
76
84
|
end
|
|
77
85
|
end
|
|
78
86
|
end
|
|
@@ -5,6 +5,7 @@ module ActiveScaffold::Config
|
|
|
5
5
|
@show_unauthorized_columns = self.class.show_unauthorized_columns
|
|
6
6
|
@refresh_list = self.class.refresh_list
|
|
7
7
|
@persistent = self.class.persistent
|
|
8
|
+
@floating_footer = self.class.floating_footer
|
|
8
9
|
|
|
9
10
|
# no global setting here because multipart should only be set for specific forms
|
|
10
11
|
@multipart = false
|
|
@@ -23,6 +24,10 @@ module ActiveScaffold::Config
|
|
|
23
24
|
class_attribute :refresh_list, instance_accessor: false
|
|
24
25
|
@@refresh_list = false
|
|
25
26
|
|
|
27
|
+
# whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
|
|
28
|
+
class_attribute :floating_footer, instance_accessor: false
|
|
29
|
+
@@floating_footer = false
|
|
30
|
+
|
|
26
31
|
# instance-level configuration
|
|
27
32
|
# ----------------------------
|
|
28
33
|
|
|
@@ -41,6 +46,9 @@ module ActiveScaffold::Config
|
|
|
41
46
|
# whether we should refresh list after create or not
|
|
42
47
|
attr_accessor :refresh_list
|
|
43
48
|
|
|
49
|
+
# whether footer should float when form is too long to fit in the screen, so footer is always available while scrolling
|
|
50
|
+
attr_accessor :floating_footer
|
|
51
|
+
|
|
44
52
|
columns_accessor :columns do
|
|
45
53
|
columns.exclude :created_on, :created_at, :updated_on, :updated_at, :as_marked
|
|
46
54
|
columns.exclude(*@core.columns.collect { |c| c.name if c.association&.polymorphic? }.compact)
|
|
@@ -53,7 +61,7 @@ module ActiveScaffold::Config
|
|
|
53
61
|
end
|
|
54
62
|
|
|
55
63
|
UserSettings.class_eval do
|
|
56
|
-
user_attr :persistent, :refresh_list, :show_unauthorized_columns
|
|
64
|
+
user_attr :persistent, :refresh_list, :show_unauthorized_columns, :floating_footer
|
|
57
65
|
|
|
58
66
|
attr_writer :multipart
|
|
59
67
|
def multipart?
|
data/lib/active_scaffold/core.rb
CHANGED
|
@@ -271,14 +271,8 @@ module ActiveScaffold
|
|
|
271
271
|
|
|
272
272
|
def self.active_record_column_type_cast(value, column)
|
|
273
273
|
return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && %i[time datetime].include?(column.type)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
elsif column.type.respond_to? :cast # jruby-jdbc and rails 5
|
|
277
|
-
column.type.cast value
|
|
278
|
-
else
|
|
279
|
-
cast_type = ActiveRecord::Type.lookup column.type
|
|
280
|
-
cast_type ? cast_type.cast(value) : value
|
|
281
|
-
end
|
|
274
|
+
cast_type = ActiveRecord::Type.lookup column.type
|
|
275
|
+
cast_type ? cast_type.cast(value) : value
|
|
282
276
|
end
|
|
283
277
|
end
|
|
284
278
|
end
|
|
@@ -98,31 +98,6 @@ module ActiveScaffold::DataStructures
|
|
|
98
98
|
visible_columns(options.reverse_merge(flatten: true)).map(&:name)
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
def each(options = nil, &proc)
|
|
102
|
-
if options
|
|
103
|
-
ActiveSupport::Deprecation.warn 'use each_column'
|
|
104
|
-
each_column(options, &proc)
|
|
105
|
-
else
|
|
106
|
-
super(&proc)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def collect_visible(options = {}, &proc)
|
|
111
|
-
ActiveSupport::Deprecation.warn "use visible_columns#{"(#{options.inspect})" if options.present?}#{'.map(&proc)' if proc}"
|
|
112
|
-
columns = visible_columns(options)
|
|
113
|
-
proc ? columns.map(&proc) : columns
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def names
|
|
117
|
-
ActiveSupport::Deprecation.warn 'use visible_columns.map(&:name)'
|
|
118
|
-
visible_columns(flatten: true).map(&:name)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def names_without_auth_check
|
|
122
|
-
ActiveSupport::Deprecation.warn 'use to_a'
|
|
123
|
-
to_a
|
|
124
|
-
end
|
|
125
|
-
|
|
126
101
|
def action_name
|
|
127
102
|
@action.user_settings_key
|
|
128
103
|
end
|
|
@@ -144,7 +144,7 @@ module ActiveScaffold::DataStructures
|
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
def method_missing(name, *args, &block)
|
|
147
|
-
return super if name
|
|
147
|
+
return super if name.match?(/[!?]$/)
|
|
148
148
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
|
149
149
|
def #{name}(label = nil) # rubocop:disable Style/CommentedKeyword
|
|
150
150
|
@#{name} ||= subgroup('#{name}'.to_sym, label)
|
|
@@ -54,6 +54,14 @@ module ActiveScaffold::DataStructures::Association
|
|
|
54
54
|
through? && through_reflection.collection?
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
def primary_key
|
|
58
|
+
@association.options[:primary_key]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def counter_cache
|
|
62
|
+
@association.options[:counter_cache]
|
|
63
|
+
end
|
|
64
|
+
|
|
57
65
|
def polymorphic?
|
|
58
66
|
false
|
|
59
67
|
end
|
|
@@ -5,6 +5,14 @@ module ActiveScaffold::DataStructures::Association
|
|
|
5
5
|
klass.am_relations.values
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
def primary_key
|
|
9
|
+
@association[:primary_key]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def counter_cache
|
|
13
|
+
@association[:counter_cache]
|
|
14
|
+
end
|
|
15
|
+
|
|
8
16
|
def inverse_klass
|
|
9
17
|
as ? @association[:inverse_class_name].constantize : super
|
|
10
18
|
end
|
|
@@ -30,14 +30,6 @@ module ActiveScaffold::DataStructures::Association
|
|
|
30
30
|
@association.active_record
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def primary_key
|
|
34
|
-
@association.options[:primary_key]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def counter_cache
|
|
38
|
-
@association.options[:counter_cache]
|
|
39
|
-
end
|
|
40
|
-
|
|
41
33
|
def as
|
|
42
34
|
@association.options[:as]
|
|
43
35
|
end
|
|
@@ -64,11 +56,7 @@ module ActiveScaffold::DataStructures::Association
|
|
|
64
56
|
end
|
|
65
57
|
|
|
66
58
|
def counter_cache_hack?
|
|
67
|
-
|
|
68
|
-
Rails.version < '5.0' && as
|
|
69
|
-
elsif belongs_to?
|
|
70
|
-
counter_cache && (Rails.version >= '5.0' || !polymorphic?)
|
|
71
|
-
end
|
|
59
|
+
belongs_to? && counter_cache && Rails.version < '6.0'
|
|
72
60
|
end
|
|
73
61
|
|
|
74
62
|
protected
|