rails_admin 3.1.2 → 3.3.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/Gemfile +20 -15
- data/README.md +2 -2
- data/app/assets/javascripts/rails_admin/application.js.erb +3 -2
- data/app/assets/stylesheets/rails_admin/application.scss.erb +1 -1
- data/app/controllers/rails_admin/main_controller.rb +5 -1
- data/app/helpers/rails_admin/application_helper.rb +4 -0
- data/app/helpers/rails_admin/form_builder.rb +2 -2
- data/app/helpers/rails_admin/main_helper.rb +1 -1
- data/app/views/layouts/rails_admin/_head.html.erb +10 -7
- data/app/views/rails_admin/main/_form_boolean.html.erb +2 -2
- data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +5 -35
- data/app/views/rails_admin/main/_form_filtering_select.html.erb +6 -18
- data/app/views/rails_admin/main/_form_nested_many.html.erb +1 -1
- data/app/views/rails_admin/main/_form_nested_one.html.erb +1 -1
- data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +12 -21
- data/app/views/rails_admin/main/delete.html.erb +1 -1
- data/app/views/rails_admin/main/index.html.erb +2 -2
- data/config/initializers/active_record_extensions.rb +0 -23
- data/lib/generators/rails_admin/importmap_formatter.rb +1 -1
- data/lib/generators/rails_admin/install_generator.rb +13 -1
- data/lib/generators/rails_admin/templates/rails_admin.vite.js +2 -0
- data/lib/rails_admin/abstract_model.rb +18 -7
- data/lib/rails_admin/adapters/active_record/association.rb +27 -10
- data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
- data/lib/rails_admin/adapters/active_record.rb +52 -5
- data/lib/rails_admin/adapters/active_record.rb.bak +348 -0
- data/lib/rails_admin/adapters/mongoid/association.rb +3 -3
- data/lib/rails_admin/adapters/mongoid/bson.rb +1 -0
- data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
- data/lib/rails_admin/adapters/mongoid.rb +8 -3
- data/lib/rails_admin/config/actions/index.rb +5 -3
- data/lib/rails_admin/config/fields/association.rb +41 -2
- data/lib/rails_admin/config/fields/base.rb +5 -5
- data/lib/rails_admin/config/fields/collection_association.rb +90 -0
- data/lib/rails_admin/config/fields/factories/active_storage.rb +2 -2
- data/lib/rails_admin/config/fields/factories/carrierwave.rb +1 -1
- data/lib/rails_admin/config/fields/factories/dragonfly.rb +1 -1
- data/lib/rails_admin/config/fields/factories/paperclip.rb +1 -1
- data/lib/rails_admin/config/fields/factories/shrine.rb +1 -1
- data/lib/rails_admin/config/fields/singular_association.rb +59 -0
- data/lib/rails_admin/config/fields/types/active_storage.rb +12 -7
- data/lib/rails_admin/config/fields/types/all.rb +0 -1
- data/lib/rails_admin/config/fields/types/belongs_to_association.rb +17 -20
- data/lib/rails_admin/config/fields/types/dragonfly.rb +0 -1
- data/lib/rails_admin/config/fields/types/file_upload.rb +7 -1
- data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -2
- data/lib/rails_admin/config/fields/types/has_many_association.rb +2 -24
- data/lib/rails_admin/config/fields/types/has_one_association.rb +12 -22
- data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +13 -8
- data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +7 -1
- data/lib/rails_admin/config/fields/types/polymorphic_association.rb +32 -9
- data/lib/rails_admin/config.rb +5 -0
- data/lib/rails_admin/engine.rb +5 -0
- data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +1 -1
- data/lib/rails_admin/extensions/url_for_extension.rb +15 -0
- data/lib/rails_admin/support/composite_keys_serializer.rb +15 -0
- data/lib/rails_admin/support/datetime.rb +1 -0
- data/lib/rails_admin/version.rb +2 -2
- data/package.json +2 -2
- data/src/rails_admin/abstract-select.js +30 -0
- data/src/rails_admin/base.js +4 -1
- data/src/rails_admin/filtering-multiselect.js +2 -4
- data/src/rails_admin/filtering-select.js +2 -4
- metadata +41 -16
- data/lib/rails_admin/adapters/composite_primary_keys/association.rb +0 -45
- data/lib/rails_admin/adapters/composite_primary_keys.rb +0 -40
- data/lib/rails_admin/config/fields/types/composite_keys_belongs_to_association.rb +0 -31
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_admin/config/fields/association'
|
4
|
+
|
5
|
+
module RailsAdmin
|
6
|
+
module Config
|
7
|
+
module Fields
|
8
|
+
class CollectionAssociation < Association
|
9
|
+
# orderable associated objects
|
10
|
+
register_instance_option :orderable do
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
register_instance_option :partial do
|
15
|
+
nested_form ? :form_nested_many : :form_filtering_multiselect
|
16
|
+
end
|
17
|
+
|
18
|
+
def collection(scope = nil)
|
19
|
+
if scope
|
20
|
+
super
|
21
|
+
elsif associated_collection_cache_all
|
22
|
+
selected = selected_ids
|
23
|
+
i = 0
|
24
|
+
super.sort_by { |a| [selected.index(a[1]) || selected.size, i += 1] }
|
25
|
+
else
|
26
|
+
value.map { |o| [o.send(associated_object_label_method), format_key(o.send(associated_primary_key))] }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def associated_prepopulate_params
|
31
|
+
{associated_model_config.abstract_model.param_key => {association.foreign_key => bindings[:object].try(:id)}}
|
32
|
+
end
|
33
|
+
|
34
|
+
def multiple?
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def selected_ids
|
39
|
+
value.map { |s| format_key(s.send(associated_primary_key)).to_s }
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_input(params)
|
43
|
+
return unless associated_model_config.abstract_model.primary_key.is_a?(Array)
|
44
|
+
|
45
|
+
if nested_form
|
46
|
+
params[method_name].each_value do |value|
|
47
|
+
value[:id] = associated_model_config.abstract_model.parse_id(value[:id])
|
48
|
+
end
|
49
|
+
elsif params[method_name].is_a?(Array)
|
50
|
+
params[method_name] = params[method_name].map { |key| associated_model_config.abstract_model.parse_id(key) if key.present? }.compact
|
51
|
+
if params[method_name].empty?
|
52
|
+
# Workaround for Arel::Visitors::UnsupportedVisitError in #ids_writer, until https://github.com/rails/rails/pull/51116 is in place
|
53
|
+
params.delete(method_name)
|
54
|
+
params[name] = []
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def form_default_value
|
60
|
+
(default_value if bindings[:object].new_record? && value.empty?)
|
61
|
+
end
|
62
|
+
|
63
|
+
def form_value
|
64
|
+
form_default_value.nil? ? selected_ids : form_default_value
|
65
|
+
end
|
66
|
+
|
67
|
+
def widget_options
|
68
|
+
{
|
69
|
+
xhr: !associated_collection_cache_all,
|
70
|
+
'edit-url': (inline_edit && bindings[:view].authorized?(:edit, associated_model_config.abstract_model) ? bindings[:view].edit_path(model_name: associated_model_config.abstract_model.to_param, id: '__ID__') : ''),
|
71
|
+
remote_source: bindings[:view].index_path(associated_model_config.abstract_model, source_object_id: abstract_model.format_id(bindings[:object].id), source_abstract_model: abstract_model.to_param, associated_collection: name, current_action: bindings[:view].current_action, compact: true),
|
72
|
+
scopeBy: dynamic_scope_relationships,
|
73
|
+
sortable: !!orderable,
|
74
|
+
removable: !!removable,
|
75
|
+
cacheAll: !!associated_collection_cache_all,
|
76
|
+
regional: {
|
77
|
+
add: ::I18n.t('admin.misc.add_new'),
|
78
|
+
chooseAll: ::I18n.t('admin.misc.chose_all'),
|
79
|
+
clearAll: ::I18n.t('admin.misc.clear_all'),
|
80
|
+
down: ::I18n.t('admin.misc.down'),
|
81
|
+
remove: ::I18n.t('admin.misc.remove'),
|
82
|
+
search: ::I18n.t('admin.misc.search'),
|
83
|
+
up: ::I18n.t('admin.misc.up'),
|
84
|
+
},
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -13,9 +13,9 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
|
|
13
13
|
fields << field
|
14
14
|
associations =
|
15
15
|
if properties.type == :has_many
|
16
|
-
["#{name}_attachments"
|
16
|
+
[:"#{name}_attachments", :"#{name}_blobs"]
|
17
17
|
else
|
18
|
-
["#{name}_attachment"
|
18
|
+
[:"#{name}_attachment", :"#{name}_blob"]
|
19
19
|
end
|
20
20
|
children_fields = associations.map do |child_name|
|
21
21
|
child_association = parent.abstract_model.associations.detect { |p| p.name.to_sym == child_name }
|
@@ -7,7 +7,7 @@ require 'rails_admin/config/fields/types/file_upload'
|
|
7
7
|
RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
|
8
8
|
model = parent.abstract_model.model
|
9
9
|
if defined?(::CarrierWave) && model.is_a?(CarrierWave::Mount) && model.uploaders.include?(attachment_name = properties.name.to_s.chomp('_file_name').to_sym)
|
10
|
-
columns = [model.uploader_options[attachment_name][:mount_on] || attachment_name, "#{attachment_name}_content_type"
|
10
|
+
columns = [model.uploader_options[attachment_name][:mount_on] || attachment_name, :"#{attachment_name}_content_type", :"#{attachment_name}_file_size"]
|
11
11
|
field = RailsAdmin::Config::Fields::Types.load(
|
12
12
|
%i[serialized json].include?(properties.type) ? :multiple_carrierwave : :carrierwave,
|
13
13
|
).new(parent, attachment_name, properties)
|
@@ -10,7 +10,7 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
|
|
10
10
|
field = RailsAdmin::Config::Fields::Types.load(:dragonfly).new(parent, attachment_name, properties)
|
11
11
|
children_fields = []
|
12
12
|
extensions.each do |ext|
|
13
|
-
children_column_name = "#{attachment_name}_#{ext}"
|
13
|
+
children_column_name = :"#{attachment_name}_#{ext}"
|
14
14
|
child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
|
15
15
|
next unless child_properties
|
16
16
|
|
@@ -11,7 +11,7 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
|
|
11
11
|
field = RailsAdmin::Config::Fields::Types.load(:paperclip).new(parent, attachment_name, properties)
|
12
12
|
children_fields = []
|
13
13
|
extensions.each do |ext|
|
14
|
-
children_column_name = "#{attachment_name}_#{ext}"
|
14
|
+
children_column_name = :"#{attachment_name}_#{ext}"
|
15
15
|
child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
|
16
16
|
next unless child_properties
|
17
17
|
|
@@ -16,7 +16,7 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
|
|
16
16
|
field = RailsAdmin::Config::Fields::Types.load(:shrine).new(parent, attachment_name, properties)
|
17
17
|
fields << field
|
18
18
|
|
19
|
-
data_field_name = "#{attachment_name}_data"
|
19
|
+
data_field_name = :"#{attachment_name}_data"
|
20
20
|
child_properties = parent.abstract_model.properties.detect { |p| p.name == data_field_name }
|
21
21
|
next true unless child_properties
|
22
22
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_admin/config/fields/association'
|
4
|
+
|
5
|
+
module RailsAdmin
|
6
|
+
module Config
|
7
|
+
module Fields
|
8
|
+
class SingularAssociation < Association
|
9
|
+
register_instance_option :filter_operators do
|
10
|
+
%w[_discard like not_like is starts_with ends_with] + (required? ? [] : %w[_separator _present _blank])
|
11
|
+
end
|
12
|
+
|
13
|
+
register_instance_option :formatted_value do
|
14
|
+
(o = value) && o.send(associated_model_config.object_label_method)
|
15
|
+
end
|
16
|
+
|
17
|
+
register_instance_option :partial do
|
18
|
+
nested_form ? :form_nested_one : :form_filtering_select
|
19
|
+
end
|
20
|
+
|
21
|
+
def collection(scope = nil)
|
22
|
+
if associated_collection_cache_all || scope
|
23
|
+
super
|
24
|
+
else
|
25
|
+
[[formatted_value, selected_id]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def multiple?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def selected_id
|
34
|
+
raise NoMethodError # abstract
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_input(params)
|
38
|
+
return unless nested_form && params[method_name].try(:[], :id).present?
|
39
|
+
|
40
|
+
ids = associated_model_config.abstract_model.parse_id(params[method_name][:id])
|
41
|
+
ids = ids.to_composite_keys.to_s if ids.respond_to?(:to_composite_keys)
|
42
|
+
params[method_name][:id] = ids
|
43
|
+
end
|
44
|
+
|
45
|
+
def form_value
|
46
|
+
form_default_value.nil? ? selected_id : form_default_value
|
47
|
+
end
|
48
|
+
|
49
|
+
def widget_options
|
50
|
+
{
|
51
|
+
xhr: !associated_collection_cache_all,
|
52
|
+
remote_source: bindings[:view].index_path(associated_model_config.abstract_model, source_object_id: abstract_model.format_id(bindings[:object].id), source_abstract_model: abstract_model.to_param, associated_collection: name, current_action: bindings[:view].current_action, compact: true),
|
53
|
+
scopeBy: dynamic_scope_relationships,
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -18,10 +18,7 @@ module RailsAdmin
|
|
18
18
|
end
|
19
19
|
|
20
20
|
register_instance_option :image? do
|
21
|
-
|
22
|
-
mime_type = Mime::Type.lookup_by_extension(value.filename.extension_without_delimiter)
|
23
|
-
mime_type.to_s.match?(/^image/)
|
24
|
-
end
|
21
|
+
value && (value.representable? || value.content_type.match?(/^image/))
|
25
22
|
end
|
26
23
|
|
27
24
|
register_instance_option :eager_load do
|
@@ -40,14 +37,22 @@ module RailsAdmin
|
|
40
37
|
)
|
41
38
|
end
|
42
39
|
|
40
|
+
register_instance_option :searchable do
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
register_instance_option :sortable do
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
43
48
|
def resource_url(thumb = false)
|
44
49
|
return nil unless value
|
45
50
|
|
46
|
-
if thumb && value.
|
51
|
+
if thumb && value.representable?
|
47
52
|
thumb = thumb_method if thumb == true
|
48
|
-
|
53
|
+
representation = value.representation(thumb)
|
49
54
|
Rails.application.routes.url_helpers.rails_blob_representation_path(
|
50
|
-
|
55
|
+
representation.blob.signed_id, representation.variation.key, representation.blob.filename, only_path: true
|
51
56
|
)
|
52
57
|
else
|
53
58
|
Rails.application.routes.url_helpers.rails_blob_path(value, only_path: true)
|
@@ -6,7 +6,6 @@ require 'rails_admin/config/fields/types/active_storage'
|
|
6
6
|
require 'rails_admin/config/fields/types/belongs_to_association'
|
7
7
|
require 'rails_admin/config/fields/types/boolean'
|
8
8
|
require 'rails_admin/config/fields/types/bson_object_id'
|
9
|
-
require 'rails_admin/config/fields/types/composite_keys_belongs_to_association'
|
10
9
|
require 'rails_admin/config/fields/types/date'
|
11
10
|
require 'rails_admin/config/fields/types/datetime'
|
12
11
|
require 'rails_admin/config/fields/types/decimal'
|
@@ -1,22 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rails_admin/config/fields/
|
3
|
+
require 'rails_admin/config/fields/singular_association'
|
4
4
|
|
5
5
|
module RailsAdmin
|
6
6
|
module Config
|
7
7
|
module Fields
|
8
8
|
module Types
|
9
|
-
class BelongsToAssociation < RailsAdmin::Config::Fields::
|
9
|
+
class BelongsToAssociation < RailsAdmin::Config::Fields::SingularAssociation
|
10
10
|
RailsAdmin::Config::Fields::Types.register(self)
|
11
11
|
|
12
|
-
register_instance_option :filter_operators do
|
13
|
-
%w[_discard like not_like is starts_with ends_with] + (required? ? [] : %w[_separator _present _blank])
|
14
|
-
end
|
15
|
-
|
16
|
-
register_instance_option :formatted_value do
|
17
|
-
(o = value) && o.send(associated_model_config.object_label_method)
|
18
|
-
end
|
19
|
-
|
20
12
|
register_instance_option :sortable do
|
21
13
|
@sortable ||= abstract_model.adapter_supports_joins? && associated_model_config.abstract_model.properties.collect(&:name).include?(associated_model_config.object_label_method) ? associated_model_config.object_label_method : {abstract_model.table_name => method_name}
|
22
14
|
end
|
@@ -25,24 +17,29 @@ module RailsAdmin
|
|
25
17
|
@searchable ||= associated_model_config.abstract_model.properties.collect(&:name).include?(associated_model_config.object_label_method) ? [associated_model_config.object_label_method, {abstract_model.model => method_name}] : {abstract_model.model => method_name}
|
26
18
|
end
|
27
19
|
|
28
|
-
register_instance_option :partial do
|
29
|
-
nested_form ? :form_nested_one : :form_filtering_select
|
30
|
-
end
|
31
|
-
|
32
20
|
register_instance_option :eager_load do
|
33
21
|
true
|
34
22
|
end
|
35
23
|
|
36
|
-
|
37
|
-
|
24
|
+
register_instance_option :allowed_methods do
|
25
|
+
nested_form ? [method_name] : Array(association.foreign_key)
|
38
26
|
end
|
39
27
|
|
40
|
-
def
|
41
|
-
|
28
|
+
def selected_id
|
29
|
+
if association.foreign_key.is_a?(Array)
|
30
|
+
format_key(association.foreign_key.map { |attribute| bindings[:object].safe_send(attribute) })
|
31
|
+
else
|
32
|
+
bindings[:object].safe_send(association.key_accessor)
|
33
|
+
end
|
42
34
|
end
|
43
35
|
|
44
|
-
def
|
45
|
-
|
36
|
+
def parse_input(params)
|
37
|
+
return super if nested_form
|
38
|
+
return unless params[method_name].present? && association.foreign_key.is_a?(Array)
|
39
|
+
|
40
|
+
association.foreign_key.zip(RailsAdmin.config.composite_keys_serializer.deserialize(params.delete(method_name))).each do |key, value|
|
41
|
+
params[key] = value
|
42
|
+
end
|
46
43
|
end
|
47
44
|
end
|
48
45
|
end
|
@@ -12,7 +12,6 @@ module RailsAdmin
|
|
12
12
|
RailsAdmin::Config::Fields::Types.register(self)
|
13
13
|
|
14
14
|
register_instance_option :image? do
|
15
|
-
false unless value
|
16
15
|
if abstract_model.model.new.respond_to?("#{name}_name")
|
17
16
|
mime_type = Mime::Type.lookup_by_extension(bindings[:object].send("#{name}_name").to_s.split('.').last)
|
18
17
|
mime_type.to_s.match?(/^image/)
|
@@ -52,7 +52,7 @@ module RailsAdmin
|
|
52
52
|
end
|
53
53
|
|
54
54
|
register_instance_option :image? do
|
55
|
-
mime_type = Mime::Type.lookup_by_extension(
|
55
|
+
mime_type = Mime::Type.lookup_by_extension(extension)
|
56
56
|
mime_type.to_s.match?(/^image/)
|
57
57
|
end
|
58
58
|
|
@@ -66,6 +66,12 @@ module RailsAdmin
|
|
66
66
|
}
|
67
67
|
end
|
68
68
|
|
69
|
+
def extension
|
70
|
+
URI.parse(resource_url).path.split('.').last
|
71
|
+
rescue URI::InvalidURIError
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
69
75
|
# virtual class
|
70
76
|
def resource_url
|
71
77
|
raise 'not implemented'
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rails_admin/config/fields/
|
3
|
+
require 'rails_admin/config/fields/collection_association'
|
4
4
|
|
5
5
|
module RailsAdmin
|
6
6
|
module Config
|
7
7
|
module Fields
|
8
8
|
module Types
|
9
|
-
class HasAndBelongsToManyAssociation < RailsAdmin::Config::Fields::
|
9
|
+
class HasAndBelongsToManyAssociation < RailsAdmin::Config::Fields::CollectionAssociation
|
10
10
|
# Register field type for the type loader
|
11
11
|
RailsAdmin::Config::Fields::Types.register(self)
|
12
12
|
end
|
@@ -1,36 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rails_admin/config/fields/
|
3
|
+
require 'rails_admin/config/fields/collection_association'
|
4
4
|
|
5
5
|
module RailsAdmin
|
6
6
|
module Config
|
7
7
|
module Fields
|
8
8
|
module Types
|
9
|
-
class HasManyAssociation < RailsAdmin::Config::Fields::
|
9
|
+
class HasManyAssociation < RailsAdmin::Config::Fields::CollectionAssociation
|
10
10
|
# Register field type for the type loader
|
11
11
|
RailsAdmin::Config::Fields::Types.register(self)
|
12
|
-
|
13
|
-
register_instance_option :partial do
|
14
|
-
nested_form ? :form_nested_many : :form_filtering_multiselect
|
15
|
-
end
|
16
|
-
|
17
|
-
# orderable associated objects
|
18
|
-
register_instance_option :orderable do
|
19
|
-
false
|
20
|
-
end
|
21
|
-
|
22
|
-
def method_name
|
23
|
-
nested_form ? "#{name}_attributes".to_sym : super
|
24
|
-
end
|
25
|
-
|
26
|
-
# Reader for validation errors of the bound object
|
27
|
-
def errors
|
28
|
-
bindings[:object].errors[name]
|
29
|
-
end
|
30
|
-
|
31
|
-
def associated_prepopulate_params
|
32
|
-
{associated_model_config.abstract_model.param_key => {association.foreign_key => bindings[:object].try(:id)}}
|
33
|
-
end
|
34
12
|
end
|
35
13
|
end
|
36
14
|
end
|
@@ -1,42 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rails_admin/config/fields/
|
3
|
+
require 'rails_admin/config/fields/singular_association'
|
4
4
|
|
5
5
|
module RailsAdmin
|
6
6
|
module Config
|
7
7
|
module Fields
|
8
8
|
module Types
|
9
|
-
class HasOneAssociation < RailsAdmin::Config::Fields::
|
9
|
+
class HasOneAssociation < RailsAdmin::Config::Fields::SingularAssociation
|
10
10
|
# Register field type for the type loader
|
11
11
|
RailsAdmin::Config::Fields::Types.register(self)
|
12
12
|
|
13
|
-
register_instance_option :
|
14
|
-
|
13
|
+
register_instance_option :allowed_methods do
|
14
|
+
nested_form ? [method_name] : [name]
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
# Accessor for field's formatted value
|
22
|
-
register_instance_option :formatted_value do
|
23
|
-
(o = value) && o.send(associated_model_config.object_label_method)
|
24
|
-
end
|
25
|
-
|
26
|
-
def selected_id
|
27
|
-
value.try(:id).try(:to_s)
|
17
|
+
def associated_prepopulate_params
|
18
|
+
{associated_model_config.abstract_model.param_key => {association.foreign_key => bindings[:object].try(:id)}}
|
28
19
|
end
|
29
20
|
|
30
|
-
def
|
31
|
-
|
32
|
-
end
|
21
|
+
def parse_input(params)
|
22
|
+
return super if nested_form
|
33
23
|
|
34
|
-
|
35
|
-
|
24
|
+
id = params.delete(method_name)
|
25
|
+
params[name] = associated_model_config.abstract_model.get(id) if id
|
36
26
|
end
|
37
27
|
|
38
|
-
def
|
39
|
-
|
28
|
+
def selected_id
|
29
|
+
format_key(value.try(:id)).try(:to_s)
|
40
30
|
end
|
41
31
|
end
|
42
32
|
end
|
@@ -23,19 +23,16 @@ module RailsAdmin
|
|
23
23
|
end
|
24
24
|
|
25
25
|
register_instance_option :image? do
|
26
|
-
|
27
|
-
mime_type = Mime::Type.lookup_by_extension(value.filename.extension_without_delimiter)
|
28
|
-
mime_type.to_s.match?(/^image/)
|
29
|
-
end
|
26
|
+
value && (value.representable? || value.content_type.match?(/^image/))
|
30
27
|
end
|
31
28
|
|
32
29
|
def resource_url(thumb = false)
|
33
30
|
return nil unless value
|
34
31
|
|
35
|
-
if thumb && value.
|
36
|
-
|
32
|
+
if thumb && value.representable?
|
33
|
+
representation = value.representation(thumb_method)
|
37
34
|
Rails.application.routes.url_helpers.rails_blob_representation_path(
|
38
|
-
|
35
|
+
representation.blob.signed_id, representation.variation.key, representation.blob.filename, only_path: true
|
39
36
|
)
|
40
37
|
else
|
41
38
|
Rails.application.routes.url_helpers.rails_blob_path(value, only_path: true)
|
@@ -48,7 +45,7 @@ module RailsAdmin
|
|
48
45
|
end
|
49
46
|
|
50
47
|
register_instance_option :keep_method do
|
51
|
-
method_name if ::ActiveStorage.replace_on_assign_to_many
|
48
|
+
method_name if ::ActiveStorage.gem_version >= Gem::Version.new('7.1') || ::ActiveStorage.replace_on_assign_to_many
|
52
49
|
end
|
53
50
|
|
54
51
|
register_instance_option :delete_method do
|
@@ -70,6 +67,14 @@ module RailsAdmin
|
|
70
67
|
direct? && {data: {direct_upload_url: bindings[:view].main_app.rails_direct_uploads_url}} || {},
|
71
68
|
)
|
72
69
|
end
|
70
|
+
|
71
|
+
register_instance_option :searchable do
|
72
|
+
false
|
73
|
+
end
|
74
|
+
|
75
|
+
register_instance_option :sortable do
|
76
|
+
false
|
77
|
+
end
|
73
78
|
end
|
74
79
|
end
|
75
80
|
end
|
@@ -47,13 +47,19 @@ module RailsAdmin
|
|
47
47
|
end
|
48
48
|
|
49
49
|
register_instance_option :image? do
|
50
|
-
mime_type = Mime::Type.lookup_by_extension(
|
50
|
+
mime_type = Mime::Type.lookup_by_extension(extension)
|
51
51
|
mime_type.to_s.match?(/^image/)
|
52
52
|
end
|
53
53
|
|
54
54
|
def resource_url(_thumb = false)
|
55
55
|
raise 'not implemented'
|
56
56
|
end
|
57
|
+
|
58
|
+
def extension
|
59
|
+
URI.parse(resource_url).path.split('.').last
|
60
|
+
rescue URI::InvalidURIError
|
61
|
+
nil
|
62
|
+
end
|
57
63
|
end
|
58
64
|
|
59
65
|
def initialize(*args)
|
@@ -51,26 +51,29 @@ module RailsAdmin
|
|
51
51
|
false
|
52
52
|
end
|
53
53
|
|
54
|
-
def
|
55
|
-
|
54
|
+
def associated_model_config
|
55
|
+
@associated_model_config ||= association.klass.collect { |type| RailsAdmin.config(type) }.reject(&:excluded?)
|
56
|
+
end
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
[
|
58
|
+
def collection(_scope = nil)
|
59
|
+
if value
|
60
|
+
[[formatted_value, selected_id]]
|
61
|
+
else
|
62
|
+
[[]]
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
63
|
-
def
|
64
|
-
|
66
|
+
def type_column
|
67
|
+
association.foreign_type.to_s
|
65
68
|
end
|
66
69
|
|
67
|
-
def
|
70
|
+
def type_collection
|
68
71
|
associated_model_config.collect do |config|
|
69
72
|
[config.label, config.abstract_model.model.name]
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
73
|
-
def
|
76
|
+
def type_urls
|
74
77
|
types = associated_model_config.collect do |config|
|
75
78
|
[config.abstract_model.model.name, config.abstract_model.to_param]
|
76
79
|
end
|
@@ -82,6 +85,26 @@ module RailsAdmin
|
|
82
85
|
bindings[:object].send(association.name)
|
83
86
|
end
|
84
87
|
|
88
|
+
def widget_options_for_types
|
89
|
+
type_collection.inject({}) do |options, model|
|
90
|
+
options.merge(
|
91
|
+
model.second.downcase.gsub('::', '-') => {
|
92
|
+
xhr: true,
|
93
|
+
remote_source: bindings[:view].index_path(model.second.underscore, source_object_id: bindings[:object].id, source_abstract_model: abstract_model.to_param, current_action: bindings[:view].current_action, compact: true),
|
94
|
+
float_left: false,
|
95
|
+
},
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def widget_options
|
101
|
+
widget_options_for_types[selected_type.try(:downcase)] || {float_left: false}
|
102
|
+
end
|
103
|
+
|
104
|
+
def selected_type
|
105
|
+
bindings[:object].send(type_column)
|
106
|
+
end
|
107
|
+
|
85
108
|
def parse_input(params)
|
86
109
|
if (type_value = params[association.foreign_type.to_sym]).present?
|
87
110
|
config = associated_model_config.find { |c| type_value == c.abstract_model.model.name }
|
data/lib/rails_admin/config.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rails_admin/config/lazy_model'
|
4
4
|
require 'rails_admin/config/sections/list'
|
5
|
+
require 'rails_admin/support/composite_keys_serializer'
|
5
6
|
require 'active_support/core_ext/module/attribute_accessors'
|
6
7
|
|
7
8
|
module RailsAdmin
|
@@ -84,6 +85,9 @@ module RailsAdmin
|
|
84
85
|
# Set where RailsAdmin fetches JS/CSS from, defaults to :sprockets
|
85
86
|
attr_writer :asset_source
|
86
87
|
|
88
|
+
# For customization of composite keys representation
|
89
|
+
attr_accessor :composite_keys_serializer
|
90
|
+
|
87
91
|
# Setup authentication to be run as a before filter
|
88
92
|
# This is run inside the controller instance so you can setup any authentication you need to
|
89
93
|
#
|
@@ -329,6 +333,7 @@ module RailsAdmin
|
|
329
333
|
@navigation_static_links = {}
|
330
334
|
@navigation_static_label = nil
|
331
335
|
@asset_source = nil
|
336
|
+
@composite_keys_serializer = RailsAdmin::Support::CompositeKeysSerializer
|
332
337
|
@parent_controller = '::ActionController::Base'
|
333
338
|
@forgery_protection_settings = {with: :exception}
|
334
339
|
RailsAdmin::Config::Actions.reset
|
data/lib/rails_admin/engine.rb
CHANGED
@@ -4,6 +4,7 @@ require 'kaminari'
|
|
4
4
|
require 'nested_form'
|
5
5
|
require 'rails'
|
6
6
|
require 'rails_admin'
|
7
|
+
require 'rails_admin/extensions/url_for_extension'
|
7
8
|
require 'rails_admin/version'
|
8
9
|
require 'turbo-rails'
|
9
10
|
|
@@ -15,6 +16,10 @@ module RailsAdmin
|
|
15
16
|
|
16
17
|
config.action_dispatch.rescue_responses['RailsAdmin::ActionNotAllowed'] = :forbidden
|
17
18
|
|
19
|
+
initializer 'RailsAdmin load UrlForExtension' do
|
20
|
+
RailsAdmin::Engine.routes.singleton_class.prepend(RailsAdmin::Extensions::UrlForExtension)
|
21
|
+
end
|
22
|
+
|
18
23
|
initializer 'RailsAdmin reload config in development' do |app|
|
19
24
|
config.initializer_path = app.root.join('config/initializers/rails_admin.rb')
|
20
25
|
|
@@ -146,7 +146,7 @@ module RailsAdmin
|
|
146
146
|
versions = object.nil? ? versions_for_model(model) : object.public_send(model.model.versions_association_name)
|
147
147
|
versions = versions.where('event LIKE ?', "%#{query}%") if query.present?
|
148
148
|
versions = versions.order(sort)
|
149
|
-
versions =
|
149
|
+
versions = versions.send(Kaminari.config.page_method_name, current_page).per(per_page) unless all
|
150
150
|
paginated_proxies = Kaminari.paginate_array([], total_count: versions.try(:total_count) || versions.count)
|
151
151
|
paginated_proxies = paginated_proxies.send(
|
152
152
|
paginated_proxies.respond_to?(Kaminari.config.page_method_name) ? Kaminari.config.page_method_name : :page,
|