active_scaffold 3.6.20 → 3.7.1
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 +47 -0
- data/README.md +29 -16
- data/app/assets/javascripts/jquery/active_scaffold.js +106 -68
- 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 +13 -2
- 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/_form_association_record.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_render_field.js.erb +24 -13
- data/config/locales/de.yml +6 -3
- data/config/locales/en.yml +3 -0
- data/config/locales/es.yml +3 -0
- data/config/locales/fr.yml +9 -6
- data/config/locales/hu.yml +20 -17
- data/config/locales/ja.yml +83 -80
- data/config/locales/ru.yml +17 -14
- 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/actions/update.rb +3 -3
- data/lib/active_scaffold/attribute_params.rb +22 -70
- data/lib/active_scaffold/bridges/active_storage/active_storage_helpers.rb +0 -3
- data/lib/active_scaffold/bridges/active_storage/form_ui.rb +6 -6
- data/lib/active_scaffold/bridges/active_storage/list_ui.rb +7 -7
- data/lib/active_scaffold/bridges/active_storage.rb +3 -0
- data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -2
- data/lib/active_scaffold/bridges/bitfields/bitfields_bridge.rb +2 -2
- data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +12 -14
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +2 -2
- data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen/helpers.rb +10 -10
- data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +7 -7
- data/lib/active_scaffold/bridges/date_picker/ext.rb +20 -9
- data/lib/active_scaffold/bridges/date_picker/helper.rb +9 -9
- data/lib/active_scaffold/bridges/date_picker.rb +2 -0
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -3
- data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +5 -5
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/list_ui.rb +3 -3
- data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +1 -1
- data/lib/active_scaffold/bridges/paper_trail/actions.rb +4 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -3
- data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +17 -17
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +6 -6
- data/lib/active_scaffold/bridges/tiny_mce.rb +1 -1
- data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +6 -11
- data/lib/active_scaffold/bridges.rb +0 -3
- 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/constraints.rb +22 -7
- data/lib/active_scaffold/core.rb +6 -10
- 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 +139 -28
- 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 +15 -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/routing_mapper.rb +1 -0
- data/lib/active_scaffold/extensions/unsaved_record.rb +9 -3
- data/lib/active_scaffold/finder.rb +147 -28
- data/lib/active_scaffold/helpers/action_link_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/controller_helpers.rb +9 -4
- data/lib/active_scaffold/helpers/form_column_helpers.rb +153 -107
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +48 -14
- data/lib/active_scaffold/helpers/list_column_helpers.rb +37 -20
- data/lib/active_scaffold/helpers/search_column_helpers.rb +137 -55
- data/lib/active_scaffold/helpers/show_column_helpers.rb +6 -6
- data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
- data/lib/active_scaffold/orm_checks.rb +21 -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 +3 -9
- data/lib/generators/active_scaffold/install_generator.rb +2 -2
- data/test/bridges/bridge_test.rb +1 -1
- data/test/bridges/date_picker_test.rb +3 -2
- data/test/bridges/paperclip_test.rb +18 -14
- data/test/bridges/tiny_mce_test.rb +5 -3
- 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/form_column_helpers_test.rb +7 -5
- data/test/helpers/pagination_helpers_test.rb +1 -1
- data/test/helpers/search_column_helpers_test.rb +2 -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 +2 -1
- data/test/misc/convert_numbers_format_test.rb +1 -1
- data/test/misc/finder_test.rb +39 -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 -17
- data/config/brakeman.ignore +0 -26
- data/config/brakeman.yml +0 -3
- data/config/i18n-tasks.yml +0 -121
- data/lib/active_scaffold/bridges/shared/date_bridge.rb +0 -221
- data/lib/active_scaffold/delayed_setup.rb +0 -41
- data/lib/active_scaffold/extensions/left_outer_joins.rb +0 -43
|
@@ -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)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module ActiveScaffold
|
|
2
2
|
module Helpers
|
|
3
3
|
module FormColumnHelpers
|
|
4
|
-
def active_scaffold_input_paperclip(column, options)
|
|
4
|
+
def active_scaffold_input_paperclip(column, options, ui_options: column.options)
|
|
5
5
|
record = options[:object]
|
|
6
6
|
paperclip = record.send(column.name.to_s)
|
|
7
|
-
content = active_scaffold_column_paperclip(record, column) if paperclip.file?
|
|
8
|
-
active_scaffold_file_with_remove_link(column, options, content, 'delete_', 'paperclip_controls')
|
|
7
|
+
content = active_scaffold_column_paperclip(record, column, ui_options: ui_options) if paperclip.file?
|
|
8
|
+
active_scaffold_file_with_remove_link(column, options, content, 'delete_', 'paperclip_controls', ui_options: ui_options)
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ActiveScaffold
|
|
2
2
|
module Helpers
|
|
3
3
|
module ListColumnHelpers
|
|
4
|
-
def active_scaffold_column_paperclip(record, column)
|
|
4
|
+
def active_scaffold_column_paperclip(record, column, ui_options: column.options)
|
|
5
5
|
paperclip = record.send(column.name.to_s)
|
|
6
6
|
return nil unless paperclip.file?
|
|
7
7
|
content =
|
|
@@ -10,21 +10,21 @@ class ActiveScaffold::Bridges::RecordSelect
|
|
|
10
10
|
|
|
11
11
|
module FormColumnHelpers
|
|
12
12
|
# requires RecordSelect plugin to be installed and configured.
|
|
13
|
-
def active_scaffold_input_record_select(column, options)
|
|
13
|
+
def active_scaffold_input_record_select(column, options, ui_options: column.options)
|
|
14
14
|
record = options.delete(:object)
|
|
15
15
|
if column.association&.singular?
|
|
16
|
-
multiple =
|
|
17
|
-
html = active_scaffold_record_select(record, column, options, record.send(column.name), multiple)
|
|
18
|
-
html << active_scaffold_new_record_subform(column, record, options) if
|
|
16
|
+
multiple = ui_options.dig(:html_options, :multiple)
|
|
17
|
+
html = active_scaffold_record_select(record, column, options, record.send(column.name), multiple, ui_options: ui_options)
|
|
18
|
+
html << active_scaffold_new_record_subform(column, record, options, ui_options: ui_options) if ui_options[:add_new]
|
|
19
19
|
html
|
|
20
20
|
elsif column.association&.collection?
|
|
21
|
-
active_scaffold_record_select(record, column, options, record.send(column.name), true)
|
|
21
|
+
active_scaffold_record_select(record, column, options, record.send(column.name), true, ui_options: ui_options)
|
|
22
22
|
else
|
|
23
|
-
active_scaffold_record_select_autocomplete(record, column, options)
|
|
23
|
+
active_scaffold_record_select_autocomplete(record, column, options, ui_options: ui_options)
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def active_scaffold_record_select(record, column, options, value, multiple)
|
|
27
|
+
def active_scaffold_record_select(record, column, options, value, multiple, ui_options: column.options)
|
|
28
28
|
unless column.association
|
|
29
29
|
raise ArgumentError, "record_select can only work against associations (and #{column.name} is not). "\
|
|
30
30
|
'A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user).'
|
|
@@ -43,7 +43,7 @@ class ActiveScaffold::Bridges::RecordSelect
|
|
|
43
43
|
record_select_options = active_scaffold_input_text_options(options).merge(
|
|
44
44
|
:controller => remote_controller
|
|
45
45
|
)
|
|
46
|
-
record_select_options.merge!(
|
|
46
|
+
record_select_options.merge!(ui_options)
|
|
47
47
|
|
|
48
48
|
html =
|
|
49
49
|
if multiple
|
|
@@ -51,29 +51,29 @@ 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
|
|
|
58
|
-
def active_scaffold_record_select_autocomplete(record, column, options)
|
|
58
|
+
def active_scaffold_record_select_autocomplete(record, column, options, ui_options: column.options)
|
|
59
59
|
record_select_options = active_scaffold_input_text_options(options).reverse_merge(
|
|
60
60
|
:controller => active_scaffold_controller_for(record.class).controller_path
|
|
61
|
-
).merge(
|
|
61
|
+
).merge(ui_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
|
|
67
67
|
|
|
68
68
|
module SearchColumnHelpers
|
|
69
|
-
def active_scaffold_search_record_select(column, options)
|
|
70
|
-
value = field_search_record_select_value(column, options[:value])
|
|
71
|
-
active_scaffold_record_select(options[:object], column, options, value,
|
|
69
|
+
def active_scaffold_search_record_select(column, options, ui_options: column.options)
|
|
70
|
+
value = field_search_record_select_value(column, options[:value], ui_options: ui_options)
|
|
71
|
+
active_scaffold_record_select(options[:object], column, options, value, ui_options[:multiple], ui_options: ui_options)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def field_search_record_select_value(column, value)
|
|
74
|
+
def field_search_record_select_value(column, value, ui_options: column.options)
|
|
75
75
|
return if value.blank?
|
|
76
|
-
if
|
|
76
|
+
if ui_options[:multiple]
|
|
77
77
|
column.association.klass.find value.collect!(&:to_i)
|
|
78
78
|
else
|
|
79
79
|
column.association.klass.find(value.to_i)
|
|
@@ -14,16 +14,16 @@ class ActiveScaffold::Bridges::TinyMce
|
|
|
14
14
|
# but not the plugins, toolbars etc.
|
|
15
15
|
# The other one is :tinymce_config, which selects the config to use from tinymce.yml.
|
|
16
16
|
# See the tinymce-rails gem documentation for usage.
|
|
17
|
-
def active_scaffold_input_text_editor(column, options)
|
|
18
|
-
options[:class] = "#{options[:class]} mceEditor #{
|
|
17
|
+
def active_scaffold_input_text_editor(column, options, ui_options: column.options)
|
|
18
|
+
options[:class] = "#{options[:class]} mceEditor #{ui_options[:class]}".strip
|
|
19
19
|
|
|
20
|
-
settings = tinymce_configuration(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
settings = tinymce_configuration(ui_options[:tinymce_config] || :default).options
|
|
21
|
+
.reject { |k, _v| k == 'selector' }
|
|
22
|
+
.merge(ui_options[:tinymce] || {})
|
|
23
23
|
options['data-tinymce'] = settings.to_json if ActiveScaffold.js_framework != :prototype
|
|
24
24
|
|
|
25
25
|
html = []
|
|
26
|
-
html << send(override_input(:textarea), column, options)
|
|
26
|
+
html << send(override_input(:textarea), column, options, ui_options: ui_options)
|
|
27
27
|
if ActiveScaffold.js_framework == :prototype && (request.xhr? || params[:iframe])
|
|
28
28
|
html << javascript_tag("tinyMCE.settings = #{settings.to_json}; tinyMCE.execCommand('mceAddEditor', false, '#{options[:id]}');")
|
|
29
29
|
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
|
|
|
@@ -63,18 +58,18 @@ module ActiveScaffold::Bridges
|
|
|
63
58
|
end
|
|
64
59
|
|
|
65
60
|
module FormColumnHelpers
|
|
66
|
-
def active_scaffold_input_usa_state(column, options)
|
|
61
|
+
def active_scaffold_input_usa_state(column, options, ui_options: column.options)
|
|
67
62
|
select_options = {:prompt => as_(:_select_)}
|
|
68
63
|
select_options.merge!(options)
|
|
69
|
-
options.reverse_merge!(
|
|
64
|
+
options.reverse_merge!(ui_options).except!(:prompt, :priority)
|
|
70
65
|
active_scaffold_select_name_with_multiple options
|
|
71
|
-
usa_state_select(:record, column.name,
|
|
66
|
+
usa_state_select(:record, column.name, ui_options[:priority], select_options, options.except(:object))
|
|
72
67
|
end
|
|
73
68
|
end
|
|
74
69
|
|
|
75
70
|
module SearchColumnHelpers
|
|
76
|
-
def active_scaffold_search_usa_state(column, options)
|
|
77
|
-
active_scaffold_input_usa_state(column, options.merge!(:selected => options.delete(:value)))
|
|
71
|
+
def active_scaffold_search_usa_state(column, options, ui_options: column.options)
|
|
72
|
+
active_scaffold_input_usa_state(column, options.merge!(:selected => options.delete(:value)), ui_options: ui_options)
|
|
78
73
|
end
|
|
79
74
|
end
|
|
80
75
|
end
|
|
@@ -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?
|
|
@@ -11,13 +11,27 @@ module ActiveScaffold
|
|
|
11
11
|
@active_scaffold_constraints ||= active_scaffold_embedded_params[:constraints] || {}
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
def register_constraint?(column_name, value)
|
|
15
|
+
if params_hash?(value)
|
|
16
|
+
false
|
|
17
|
+
elsif value.is_a?(Array)
|
|
18
|
+
column = active_scaffold_config.columns[column_name]
|
|
19
|
+
column && value.size > (column.association&.polymorphic? ? 2 : 1)
|
|
20
|
+
else
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
14
25
|
# For each enabled action, adds the constrained columns to the ActionColumns object (if it exists).
|
|
15
26
|
# This lets the ActionColumns object skip constrained columns.
|
|
16
27
|
#
|
|
17
|
-
# If the constraint value is a Hash, then we assume the constraint is a multi-level association constraint
|
|
28
|
+
# If the constraint value is a Hash, then we assume the constraint is a multi-level association constraint
|
|
29
|
+
# (the reverse of a has_many :through) and we do NOT register the constraint column.
|
|
30
|
+
# If the constraint value is an Array, or Array with more than 2 items for polymorphic column,
|
|
31
|
+
# we do NOT register the constraint column, as records will have different values in the column.
|
|
18
32
|
def register_constraints_with_action_columns(constrained_fields = nil)
|
|
19
33
|
constrained_fields ||= []
|
|
20
|
-
constrained_fields |= active_scaffold_constraints.
|
|
34
|
+
constrained_fields |= active_scaffold_constraints.select { |k, v| register_constraint?(k, v) }.keys.collect(&:to_sym)
|
|
21
35
|
exclude_actions = []
|
|
22
36
|
%i[list update].each do |action_name|
|
|
23
37
|
if active_scaffold_config.actions.include? action_name
|
|
@@ -111,10 +125,10 @@ module ActiveScaffold
|
|
|
111
125
|
value = association.klass.find(value).send(association.primary_key) if association.primary_key
|
|
112
126
|
|
|
113
127
|
if association.polymorphic?
|
|
114
|
-
unless value.is_a?(Array) && value.size
|
|
128
|
+
unless value.is_a?(Array) && value.size >= 2
|
|
115
129
|
raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(association), caller
|
|
116
130
|
end
|
|
117
|
-
condition = {table => {association.foreign_type => value[0], field => value[1]}}
|
|
131
|
+
condition = {table => {association.foreign_type => value[0], field => value.size == 2 ? value[1] : value[1..-1]}}
|
|
118
132
|
else
|
|
119
133
|
condition = {table => {field.to_s => value}}
|
|
120
134
|
end
|
|
@@ -149,11 +163,12 @@ module ActiveScaffold
|
|
|
149
163
|
if column.association.collection?
|
|
150
164
|
record.send(k.to_s).send(:<<, column.association.klass.find(v))
|
|
151
165
|
elsif column.association.polymorphic?
|
|
152
|
-
unless v.is_a?(Array) && v.size
|
|
166
|
+
unless v.is_a?(Array) && v.size >= 2
|
|
153
167
|
raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(column.association), caller
|
|
154
168
|
end
|
|
155
|
-
record.send("#{k}=", v[0].constantize.find(v[1]))
|
|
156
|
-
elsif !column.association.source_reflection&.options&.include?(:through) # regular singular association, or one-level through association
|
|
169
|
+
record.send("#{k}=", v[0].constantize.find(v[1])) if v.size == 2
|
|
170
|
+
elsif !column.association.source_reflection&.options&.include?(:through) && # regular singular association, or one-level through association
|
|
171
|
+
!v.is_a?(Array)
|
|
157
172
|
record.send("#{k}=", column.association.klass.find(v))
|
|
158
173
|
|
|
159
174
|
# setting the belongs_to side of a has_one isn't safe. if the has_one was already
|
data/lib/active_scaffold/core.rb
CHANGED
|
@@ -257,6 +257,8 @@ module ActiveScaffold
|
|
|
257
257
|
def self.column_type_cast(value, column)
|
|
258
258
|
if defined?(ActiveRecord) && column.is_a?(ActiveRecord::ConnectionAdapters::Column)
|
|
259
259
|
active_record_column_type_cast(value, column)
|
|
260
|
+
elsif defined?(ActiveModel) && column.is_a?(ActiveModel::Attribute)
|
|
261
|
+
active_record_column_type_cast(value, column.type)
|
|
260
262
|
elsif defined?(Mongoid) && column.is_a?(Mongoid::Fields::Standard)
|
|
261
263
|
mongoid_column_type_cast(value, column)
|
|
262
264
|
else
|
|
@@ -269,16 +271,10 @@ module ActiveScaffold
|
|
|
269
271
|
column.type.evolve value
|
|
270
272
|
end
|
|
271
273
|
|
|
272
|
-
def self.active_record_column_type_cast(value,
|
|
273
|
-
return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && %i[time datetime].include?(
|
|
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
|
+
def self.active_record_column_type_cast(value, column_or_type)
|
|
275
|
+
return Time.zone.at(value.to_i) if value =~ /\A\d+\z/ && %i[time datetime].include?(column_or_type.type)
|
|
276
|
+
cast_type = column_or_type.is_a?(ActiveRecord::ConnectionAdapters::Column) ? ActiveRecord::Type.lookup(column_or_type.type) : column_or_type
|
|
277
|
+
cast_type ? cast_type.cast(value) : value
|
|
282
278
|
end
|
|
283
279
|
end
|
|
284
280
|
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
|
|
@@ -2,15 +2,28 @@ module ActiveScaffold::DataStructures::Association
|
|
|
2
2
|
class Mongoid < Abstract
|
|
3
3
|
delegate :inverse_klass, :as, :dependent, :inverse, to: :@association
|
|
4
4
|
|
|
5
|
+
def belongs_to?
|
|
6
|
+
# once Ruby 2.6 support is dropped, use macro_mapping? always
|
|
7
|
+
defined?(::Mongoid::Association) ? macro_mapping?(:belongs_to) : super
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def has_one? # rubocop:disable Naming/PredicateName
|
|
11
|
+
defined?(::Mongoid::Association) ? macro_mapping?(:has_one) : super
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def has_many? # rubocop:disable Naming/PredicateName
|
|
15
|
+
defined?(::Mongoid::Association) ? macro_mapping?(:has_many) : super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def habtm?
|
|
19
|
+
defined?(::Mongoid::Association) ? macro_mapping?(:has_and_belongs_to_many) : super
|
|
20
|
+
end
|
|
21
|
+
|
|
5
22
|
# polymorphic belongs_to
|
|
6
23
|
def polymorphic?
|
|
7
24
|
belongs_to? && @association.polymorphic?
|
|
8
25
|
end
|
|
9
26
|
|
|
10
|
-
def primary_key
|
|
11
|
-
@association[:primary_key]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
27
|
def association_primary_key
|
|
15
28
|
@association.primary_key
|
|
16
29
|
end
|
|
@@ -19,10 +32,6 @@ module ActiveScaffold::DataStructures::Association
|
|
|
19
32
|
@association.type
|
|
20
33
|
end
|
|
21
34
|
|
|
22
|
-
def counter_cache
|
|
23
|
-
@association[:counter_cache]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
35
|
def table_name
|
|
27
36
|
@association.klass.collection.name
|
|
28
37
|
end
|
|
@@ -38,5 +47,9 @@ module ActiveScaffold::DataStructures::Association
|
|
|
38
47
|
def self.reflect_on_all_associations(klass)
|
|
39
48
|
klass.relations.values
|
|
40
49
|
end
|
|
50
|
+
|
|
51
|
+
def macro_mapping?(macro)
|
|
52
|
+
@association.is_a? ::Mongoid::Association::MACRO_MAPPING[macro]
|
|
53
|
+
end
|
|
41
54
|
end
|
|
42
55
|
end
|