rails_admin 3.1.4 → 3.2.0.rc
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +19 -14
- 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 +7 -5
- 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/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 +25 -8
- data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
- data/lib/rails_admin/adapters/active_record.rb +51 -5
- data/lib/rails_admin/adapters/mongoid/association.rb +1 -1
- data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
- data/lib/rails_admin/adapters/mongoid.rb +6 -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 +4 -4
- data/lib/rails_admin/config/fields/collection_association.rb +90 -0
- 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/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 +3 -3
- 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 +1 -4
- data/src/rails_admin/widgets.js +1 -0
- metadata +39 -15
- 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
@@ -15,7 +15,7 @@ module RailsAdmin
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def get(id, scope = scoped)
|
18
|
-
object = scope
|
18
|
+
object = primary_key_scope(scope, id).first
|
19
19
|
return unless object
|
20
20
|
|
21
21
|
object.extend(ObjectExtension)
|
@@ -72,6 +72,14 @@ module RailsAdmin
|
|
72
72
|
|
73
73
|
delegate :primary_key, :table_name, to: :model, prefix: false
|
74
74
|
|
75
|
+
def quoted_table_name
|
76
|
+
model.quoted_table_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def quote_column_name(name)
|
80
|
+
model.connection.quote_column_name(name)
|
81
|
+
end
|
82
|
+
|
75
83
|
def encoding
|
76
84
|
adapter =
|
77
85
|
if ::ActiveRecord::Base.respond_to?(:connection_db_config)
|
@@ -107,10 +115,42 @@ module RailsAdmin
|
|
107
115
|
true
|
108
116
|
end
|
109
117
|
|
118
|
+
def format_id(id)
|
119
|
+
if primary_key.is_a? Array
|
120
|
+
RailsAdmin.config.composite_keys_serializer.serialize(id)
|
121
|
+
else
|
122
|
+
id
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def parse_id(id)
|
127
|
+
if primary_key.is_a?(Array)
|
128
|
+
ids = RailsAdmin.config.composite_keys_serializer.deserialize(id)
|
129
|
+
primary_key.each_with_index do |key, i|
|
130
|
+
ids[i] = model.type_for_attribute(key).cast(ids[i])
|
131
|
+
end
|
132
|
+
ids
|
133
|
+
else
|
134
|
+
id
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
110
138
|
private
|
111
139
|
|
140
|
+
def primary_key_scope(scope, id)
|
141
|
+
if primary_key.is_a? Array
|
142
|
+
scope.where(primary_key.zip(parse_id(id)).to_h)
|
143
|
+
else
|
144
|
+
scope.where(primary_key => id)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
112
148
|
def bulk_scope(scope, options)
|
113
|
-
|
149
|
+
if primary_key.is_a? Array
|
150
|
+
options[:bulk_ids].map { |id| primary_key_scope(scope, id) }.reduce(&:or)
|
151
|
+
else
|
152
|
+
scope.where(primary_key => options[:bulk_ids])
|
153
|
+
end
|
114
154
|
end
|
115
155
|
|
116
156
|
def sort_scope(scope, options)
|
@@ -201,6 +241,8 @@ module RailsAdmin
|
|
201
241
|
case @type
|
202
242
|
when :boolean
|
203
243
|
boolean_unary_operators
|
244
|
+
when :uuid
|
245
|
+
uuid_unary_operators
|
204
246
|
when :integer, :decimal, :float
|
205
247
|
numeric_unary_operators
|
206
248
|
else
|
@@ -230,6 +272,7 @@ module RailsAdmin
|
|
230
272
|
)
|
231
273
|
end
|
232
274
|
alias_method :numeric_unary_operators, :boolean_unary_operators
|
275
|
+
alias_method :uuid_unary_operators, :boolean_unary_operators
|
233
276
|
|
234
277
|
def range_filter(min, max)
|
235
278
|
if min && max && min == max
|
@@ -255,9 +298,12 @@ module RailsAdmin
|
|
255
298
|
end
|
256
299
|
|
257
300
|
def build_statement_for_boolean
|
258
|
-
|
259
|
-
|
260
|
-
|
301
|
+
case @value
|
302
|
+
when 'false', 'f', '0'
|
303
|
+
["(#{@column} IS NULL OR #{@column} = ?)", false]
|
304
|
+
when 'true', 't', '1'
|
305
|
+
["(#{@column} = ?)", true]
|
306
|
+
end
|
261
307
|
end
|
262
308
|
|
263
309
|
def column_for_value(value)
|
@@ -46,7 +46,7 @@ module RailsAdmin
|
|
46
46
|
|
47
47
|
def klass
|
48
48
|
if polymorphic? && %i[referenced_in belongs_to].include?(macro)
|
49
|
-
polymorphic_parents(:mongoid,
|
49
|
+
polymorphic_parents(:mongoid, association.inverse_class_name, name) || []
|
50
50
|
else
|
51
51
|
association.klass
|
52
52
|
end
|
@@ -251,9 +251,12 @@ module RailsAdmin
|
|
251
251
|
end
|
252
252
|
|
253
253
|
def build_statement_for_boolean
|
254
|
-
|
255
|
-
|
256
|
-
|
254
|
+
case @value
|
255
|
+
when 'false', 'f', '0'
|
256
|
+
{@column => false}
|
257
|
+
when 'true', 't', '1'
|
258
|
+
{@column => true}
|
259
|
+
end
|
257
260
|
end
|
258
261
|
|
259
262
|
def column_for_value(value)
|
@@ -50,9 +50,11 @@ module RailsAdmin
|
|
50
50
|
format.json do
|
51
51
|
output =
|
52
52
|
if params[:compact]
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
if @association
|
54
|
+
@association.collection(@objects).collect { |(label, id)| {id: id, label: label} }
|
55
|
+
else
|
56
|
+
@objects.collect { |object| {id: object.id.to_s, label: object.send(@model_config.object_label_method).to_s} }
|
57
|
+
end
|
56
58
|
else
|
57
59
|
@objects.to_json(@schema)
|
58
60
|
end
|
@@ -13,7 +13,7 @@ module RailsAdmin
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def method_name
|
16
|
-
association.key_accessor
|
16
|
+
nested_form ? :"#{name}_attributes" : association.key_accessor
|
17
17
|
end
|
18
18
|
|
19
19
|
register_instance_option :pretty_value do
|
@@ -56,7 +56,30 @@ module RailsAdmin
|
|
56
56
|
# preload entire associated collection (per associated_collection_scope) on load
|
57
57
|
# Be sure to set limit in associated_collection_scope if set is large
|
58
58
|
register_instance_option :associated_collection_cache_all do
|
59
|
-
@associated_collection_cache_all ||= (associated_model_config.abstract_model.count < associated_model_limit)
|
59
|
+
@associated_collection_cache_all ||= dynamically_scope_by.blank? && (associated_model_config.abstract_model.count < associated_model_limit)
|
60
|
+
end
|
61
|
+
|
62
|
+
# client-side dynamic scoping
|
63
|
+
register_instance_option :dynamically_scope_by do
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
# parses #dynamically_scope_by and returns a Hash in the form of
|
68
|
+
# {[form field name in this model]: [field name in the associated model]}
|
69
|
+
def dynamic_scope_relationships
|
70
|
+
@dynamic_scope_relationships ||=
|
71
|
+
Array.wrap(dynamically_scope_by).flat_map do |field|
|
72
|
+
field.is_a?(Hash) ? field.to_a : [[field, field]]
|
73
|
+
end.map do |field_name, target_name| # rubocop:disable Style/MultilineBlockChain
|
74
|
+
field = section.fields.detect { |f| f.name == field_name }
|
75
|
+
raise "Field '#{field_name}' was given for #dynamically_scope_by but not found in '#{abstract_model.model_name}'" unless field
|
76
|
+
|
77
|
+
target_field = associated_model_config.list.fields.detect { |f| f.name == target_name }
|
78
|
+
raise "Field '#{field_name}' was given for #dynamically_scope_by but not found in '#{associated_model_config.abstract_model.model_name}'" unless target_field
|
79
|
+
raise "Field '#{field_name}' in '#{associated_model_config.abstract_model.model_name}' can't be used for dynamic scoping because it's not filterable" unless target_field.filterable
|
80
|
+
|
81
|
+
[field.method_name, target_name]
|
82
|
+
end.to_h
|
60
83
|
end
|
61
84
|
|
62
85
|
# determines whether association's elements can be removed
|
@@ -111,6 +134,12 @@ module RailsAdmin
|
|
111
134
|
bindings[:object].send(association.name)
|
112
135
|
end
|
113
136
|
|
137
|
+
# Returns collection of all selectable records
|
138
|
+
def collection(scope = nil)
|
139
|
+
(scope || bindings[:controller].list_entries(associated_model_config, :index, associated_collection_scope, false)).
|
140
|
+
map { |o| [o.send(associated_object_label_method), format_key(o.send(associated_primary_key)).to_s] }
|
141
|
+
end
|
142
|
+
|
114
143
|
# has many?
|
115
144
|
def multiple?
|
116
145
|
true
|
@@ -123,6 +152,16 @@ module RailsAdmin
|
|
123
152
|
def associated_model_limit
|
124
153
|
RailsAdmin.config.default_associated_collection_limit
|
125
154
|
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def format_key(key)
|
159
|
+
if key.is_a?(Array)
|
160
|
+
RailsAdmin.config.composite_keys_serializer.serialize(key)
|
161
|
+
else
|
162
|
+
key
|
163
|
+
end
|
164
|
+
end
|
126
165
|
end
|
127
166
|
end
|
128
167
|
end
|
@@ -62,15 +62,15 @@ module RailsAdmin
|
|
62
62
|
|
63
63
|
def sort_column
|
64
64
|
if sortable == true
|
65
|
-
"#{abstract_model.
|
65
|
+
"#{abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(name)}"
|
66
66
|
elsif (sortable.is_a?(String) || sortable.is_a?(Symbol)) && sortable.to_s.include?('.') # just provide sortable, don't do anything smart
|
67
67
|
sortable
|
68
68
|
elsif sortable.is_a?(Hash) # just join sortable hash, don't do anything smart
|
69
69
|
"#{sortable.keys.first}.#{sortable.values.first}"
|
70
|
-
elsif association # use column on target table
|
71
|
-
"#{associated_model_config.abstract_model.
|
70
|
+
elsif association? # use column on target table
|
71
|
+
"#{associated_model_config.abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(sortable)}"
|
72
72
|
else # use described column in the field conf.
|
73
|
-
"#{abstract_model.
|
73
|
+
"#{abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(sortable)}"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -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
|
@@ -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" : 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
|