rails_admin 3.2.0.beta → 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 +0 -9
- data/app/helpers/rails_admin/application_helper.rb +4 -0
- data/app/helpers/rails_admin/form_builder.rb +2 -2
- data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +5 -36
- data/app/views/rails_admin/main/_form_filtering_select.html.erb +6 -19
- data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +12 -21
- data/config/initializers/active_record_extensions.rb +0 -23
- data/lib/rails_admin/abstract_model.rb +10 -7
- data/lib/rails_admin/adapters/active_record/association.rb +24 -7
- data/lib/rails_admin/adapters/active_record.rb +34 -2
- data/lib/rails_admin/config/actions/index.rb +5 -3
- data/lib/rails_admin/config/fields/association.rb +17 -1
- 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 +4 -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 +7 -28
- data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +4 -7
- 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/version.rb +1 -1
- data/package.json +2 -2
- data/src/rails_admin/widgets.js +1 -0
- metadata +6 -5
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb8262bbe1aab2c4d873c5a470ca69ff43800ba59d0f319d20039be36e34a640
|
4
|
+
data.tar.gz: 7dea99571de5a200d22096ee47881d0b114033eb8643d95af58041115cf66088
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddb8cabf32fa1023033bc51d8eb2ffa287a8981f7bd10dd862237f1aa5e1a8b84c8b2df64558e1a9bca6c306af42239e952988959fb26b2d68228f9bf828f62d
|
7
|
+
data.tar.gz: ee7a91df4279aa73f889c83c52bcd6e5bb64ae217e2e03aa92bcef08f084f0bef8ce1736405fe390d4c9e5651349cff9e5cc789b0cd7899dce4d911b4125ff05
|
data/Gemfile
CHANGED
@@ -21,7 +21,6 @@ group :test do
|
|
21
21
|
gem 'carrierwave', ['>= 2.0.0.rc', '< 3']
|
22
22
|
gem 'cuprite', '!= 0.15.1'
|
23
23
|
gem 'database_cleaner-active_record', '>= 2.0', require: false
|
24
|
-
gem 'database_cleaner-mongoid', '>= 2.0', require: false
|
25
24
|
gem 'dragonfly', '~> 1.0'
|
26
25
|
gem 'factory_bot', '>= 4.2', '!= 6.4.5'
|
27
26
|
gem 'generator_spec', '>= 0.8'
|
@@ -54,12 +53,4 @@ group :active_record do
|
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
group :mongoid do
|
58
|
-
gem 'cancancan-mongoid'
|
59
|
-
gem 'carrierwave-mongoid', '>= 0.6.3', require: 'carrierwave/mongoid'
|
60
|
-
gem 'kaminari-mongoid'
|
61
|
-
gem 'mongoid-paperclip', '>= 0.0.8', require: 'mongoid_paperclip'
|
62
|
-
gem 'shrine-mongoid', '~> 1.0'
|
63
|
-
end
|
64
|
-
|
65
56
|
gemspec
|
@@ -7,6 +7,10 @@ module RailsAdmin
|
|
7
7
|
action(action_name, abstract_model, object).try(:authorized?)
|
8
8
|
end
|
9
9
|
|
10
|
+
def current_action
|
11
|
+
params[:action].in?(%w[create new]) ? 'create' : 'update'
|
12
|
+
end
|
13
|
+
|
10
14
|
def current_action?(action, abstract_model = @abstract_model, object = @object)
|
11
15
|
@action.custom_key == action.custom_key &&
|
12
16
|
abstract_model.try(:to_param) == @abstract_model.try(:to_param) &&
|
@@ -108,8 +108,8 @@ module RailsAdmin
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def hidden_field(method, options = {})
|
111
|
-
if method == :id
|
112
|
-
super method, {value: object.id
|
111
|
+
if method == :id && object.id.is_a?(Array)
|
112
|
+
super method, {value: RailsAdmin.config.composite_keys_serializer.serialize(object.id)}
|
113
113
|
else
|
114
114
|
super
|
115
115
|
end
|
@@ -1,45 +1,14 @@
|
|
1
1
|
<%
|
2
2
|
config = field.associated_model_config
|
3
|
-
source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
|
4
|
-
|
5
|
-
selected = form.object.send(field.name)
|
6
|
-
selected_ids = selected.map{|s| s.send(field.associated_primary_key).to_s}
|
7
|
-
|
8
|
-
current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
|
9
|
-
|
10
|
-
xhr = !field.associated_collection_cache_all
|
11
|
-
|
12
|
-
collection = if xhr
|
13
|
-
selected.map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key)] }
|
14
|
-
else
|
15
|
-
i = 0
|
16
|
-
controller.list_entries(config, :index, field.associated_collection_scope, false).map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key).to_s] }.sort_by {|a| [selected_ids.index(a[1]) || selected_ids.size, i+=1] }
|
17
|
-
end
|
18
|
-
|
19
|
-
js_data = {
|
20
|
-
xhr: xhr,
|
21
|
-
:'edit-url' => (field.inline_edit && authorized?(:edit, config.abstract_model) ? edit_path(model_name: config.abstract_model.to_param, id: '__ID__') : ''),
|
22
|
-
remote_source: index_path(config.abstract_model, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, associated_collection: field.name, current_action: current_action, compact: true),
|
23
|
-
scopeBy: field.dynamic_scope_relationships,
|
24
|
-
sortable: !!field.orderable,
|
25
|
-
removable: !!field.removable,
|
26
|
-
cacheAll: !!field.associated_collection_cache_all,
|
27
|
-
regional: {
|
28
|
-
add: t('admin.misc.add_new'),
|
29
|
-
chooseAll: t('admin.misc.chose_all'),
|
30
|
-
clearAll: t('admin.misc.clear_all'),
|
31
|
-
down: t('admin.misc.down'),
|
32
|
-
remove: t('admin.misc.remove'),
|
33
|
-
search: t('admin.misc.search'),
|
34
|
-
up: t('admin.misc.up')
|
35
|
-
}
|
36
|
-
}
|
37
3
|
%>
|
4
|
+
|
38
5
|
<div class="row">
|
39
6
|
<div class="col-auto">
|
40
7
|
<input name="<%= form.dom_name(field) %>" type="hidden" />
|
41
|
-
|
42
|
-
|
8
|
+
<%=
|
9
|
+
form.select field.method_name, field.collection, { selected: field.form_value, object: form.object },
|
10
|
+
field.html_attributes.reverse_merge({data: { filteringmultiselect: true, options: field.widget_options.to_json }, multiple: true})
|
11
|
+
%>
|
43
12
|
</div>
|
44
13
|
<% if authorized?(:new, config.abstract_model) && field.inline_add %>
|
45
14
|
<div class="col-sm-4 modal-actions">
|
@@ -1,34 +1,21 @@
|
|
1
1
|
<%
|
2
2
|
config = field.associated_model_config
|
3
|
-
source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
|
4
|
-
|
5
|
-
current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
|
6
|
-
|
7
|
-
edit_url = authorized?(:edit, config.abstract_model) ? edit_path(model_name: config.abstract_model.to_param, modal: true, id: '__ID__') : ''
|
8
|
-
|
9
|
-
xhr = !field.associated_collection_cache_all
|
10
|
-
|
11
|
-
collection = xhr ? [[field.formatted_value, field.selected_id]] : controller.list_entries(config, :index, field.associated_collection_scope, false).map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key).to_s] }
|
12
|
-
|
13
|
-
js_data = {
|
14
|
-
xhr: xhr,
|
15
|
-
remote_source: index_path(config.abstract_model.to_param, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, associated_collection: field.name, current_action: current_action, compact: true),
|
16
|
-
scopeBy: field.dynamic_scope_relationships
|
17
|
-
}
|
18
3
|
%>
|
19
4
|
|
20
5
|
<div class="row">
|
21
6
|
<div class="col-sm-4">
|
22
|
-
|
23
|
-
|
7
|
+
<%=
|
8
|
+
form.select field.method_name, field.collection, { selected: field.form_value, include_blank: true },
|
9
|
+
field.html_attributes.reverse_merge({ data: { filteringselect: true, options: field.widget_options.to_json }, placeholder: t('admin.misc.search') })
|
10
|
+
%>
|
24
11
|
</div>
|
25
12
|
<div class="col-sm-8 mt-2 mt-md-0 modal-actions">
|
26
13
|
<% if authorized?(:new, config.abstract_model) && field.inline_add %>
|
27
14
|
<% path_hash = { model_name: config.abstract_model.to_param, modal: true }.merge!(field.associated_prepopulate_params) %>
|
28
15
|
<%= link_to "<i class=\"fas fa-plus\"></i> ".html_safe + wording_for(:link, :new, config.abstract_model), '#', data: { link: new_path(path_hash) }, class: "btn btn-info create" %>
|
29
16
|
<% end %>
|
30
|
-
<% if
|
31
|
-
<%= link_to "<i class=\"fas fa-pencil-alt\"></i> ".html_safe + wording_for(:link, :edit, config.abstract_model), '#', data: { link:
|
17
|
+
<% if authorized?(:edit, config.abstract_model) && field.inline_edit %>
|
18
|
+
<%= link_to "<i class=\"fas fa-pencil-alt\"></i> ".html_safe + wording_for(:link, :edit, config.abstract_model), '#', data: { link: edit_path(model_name: config.abstract_model.to_param, modal: true, id: '__ID__') }, class: "btn btn-info update ms-2#{' disabled' if field.value.nil?}" %>
|
32
19
|
<% end %>
|
33
20
|
</div>
|
34
21
|
</div>
|
@@ -1,32 +1,23 @@
|
|
1
1
|
<%
|
2
|
-
|
3
|
-
type_column = field.association.foreign_type.to_s
|
4
|
-
selected_type = field.bindings[:object].send(type_column)
|
5
|
-
selected = field.bindings[:object].send(field.association.name)
|
6
|
-
collection = selected ? [[field.formatted_value, selected.id]] : [[]]
|
7
|
-
column_type_dom_id = form.dom_id(field).sub(field.method_name.to_s, type_column)
|
8
|
-
current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
|
9
|
-
|
10
|
-
default_options = { float_left: false }
|
11
|
-
|
12
|
-
js_data = type_collection.inject({}) do |options, model|
|
13
|
-
source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
|
14
|
-
options.merge(model.second.downcase.gsub('::', '-') => {
|
15
|
-
xhr: true,
|
16
|
-
remote_source: index_path(model.second.underscore, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, current_action: current_action, compact: true),
|
17
|
-
float_left: false
|
18
|
-
})
|
19
|
-
end
|
2
|
+
column_type_dom_id = form.dom_id(field).sub(field.method_name.to_s, field.type_column)
|
20
3
|
%>
|
21
4
|
|
22
5
|
<div class="row">
|
23
6
|
<div class="col-sm-3">
|
24
|
-
<%
|
7
|
+
<% field.widget_options_for_types.each do |model, value| %>
|
25
8
|
<div data-options="<%= value.to_json %>" id="<%= model %>-js-options"></div>
|
26
9
|
<% end %>
|
27
|
-
<%=
|
10
|
+
<%=
|
11
|
+
form.select field.type_column, field.type_collection, {include_blank: true, selected: field.selected_type},
|
12
|
+
class: "form-select", id: column_type_dom_id, data: { polymorphic: true, urls: field.type_urls.to_json },
|
13
|
+
style: "float: left; margin-right: 10px;"
|
14
|
+
%>
|
28
15
|
</div>
|
29
16
|
<div class="col-sm-4">
|
30
|
-
<%=
|
17
|
+
<%=
|
18
|
+
form.select field.method_name, field.collection, {include_blank: true, selected: field.selected_id},
|
19
|
+
class: "form-control", data: { filteringselect: true, options: field.widget_options },
|
20
|
+
placeholder: 'Search'
|
21
|
+
%>
|
31
22
|
</div>
|
32
23
|
</div>
|
@@ -20,27 +20,4 @@ ActiveSupport.on_load(:active_record) do
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
24
|
-
if defined?(CompositePrimaryKeys)
|
25
|
-
# Apply patch until the fix is released:
|
26
|
-
# https://github.com/composite-primary-keys/composite_primary_keys/pull/572
|
27
|
-
CompositePrimaryKeys::CompositeKeys.class_eval do
|
28
|
-
alias_method :to_param, :to_s
|
29
|
-
end
|
30
|
-
|
31
|
-
CompositePrimaryKeys::CollectionAssociation.prepend(Module.new do
|
32
|
-
def ids_writer(ids)
|
33
|
-
if reflection.association_primary_key.is_a? Array
|
34
|
-
ids = CompositePrimaryKeys.normalize(Array(ids).reject(&:blank?), reflection.association_primary_key.size)
|
35
|
-
reflection.association_primary_key.each_with_index do |primary_key, i|
|
36
|
-
pk_type = klass.type_for_attribute(primary_key)
|
37
|
-
ids.each do |id|
|
38
|
-
id[i] = pk_type.cast(id[i]) if id.is_a? Array
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
super ids
|
43
|
-
end
|
44
|
-
end)
|
45
|
-
end
|
46
23
|
end
|
@@ -105,17 +105,20 @@ module RailsAdmin
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
+
def format_id(id)
|
109
|
+
id
|
110
|
+
end
|
111
|
+
|
112
|
+
def parse_id(id)
|
113
|
+
id
|
114
|
+
end
|
115
|
+
|
108
116
|
private
|
109
117
|
|
110
118
|
def initialize_active_record
|
111
119
|
@adapter = :active_record
|
112
|
-
|
113
|
-
|
114
|
-
extend Adapters::CompositePrimaryKeys
|
115
|
-
else
|
116
|
-
require 'rails_admin/adapters/active_record'
|
117
|
-
extend Adapters::ActiveRecord
|
118
|
-
end
|
120
|
+
require 'rails_admin/adapters/active_record'
|
121
|
+
extend Adapters::ActiveRecord
|
119
122
|
end
|
120
123
|
|
121
124
|
def initialize_mongoid
|
@@ -42,16 +42,29 @@ module RailsAdmin
|
|
42
42
|
def primary_key
|
43
43
|
return nil if polymorphic?
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
value =
|
46
|
+
case type
|
47
|
+
when :has_one
|
48
|
+
association.klass.primary_key
|
49
|
+
else
|
50
|
+
association.association_primary_key
|
51
|
+
end
|
52
|
+
|
53
|
+
if value.is_a? Array
|
54
|
+
:id
|
48
55
|
else
|
49
|
-
|
50
|
-
end
|
56
|
+
value.to_sym
|
57
|
+
end
|
51
58
|
end
|
52
59
|
|
53
60
|
def foreign_key
|
54
|
-
association.
|
61
|
+
if association.options[:query_constraints].present?
|
62
|
+
association.options[:query_constraints].map(&:to_sym)
|
63
|
+
elsif association.foreign_key.is_a?(Array)
|
64
|
+
association.foreign_key.map(&:to_sym)
|
65
|
+
else
|
66
|
+
association.foreign_key.to_sym
|
67
|
+
end
|
55
68
|
end
|
56
69
|
|
57
70
|
def foreign_key_nullable?
|
@@ -75,7 +88,11 @@ module RailsAdmin
|
|
75
88
|
when :has_one
|
76
89
|
:"#{name}_id"
|
77
90
|
else
|
78
|
-
foreign_key
|
91
|
+
if foreign_key.is_a?(Array)
|
92
|
+
:"#{name}_id"
|
93
|
+
else
|
94
|
+
foreign_key
|
95
|
+
end
|
79
96
|
end
|
80
97
|
end
|
81
98
|
|
@@ -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)
|
@@ -115,10 +115,42 @@ module RailsAdmin
|
|
115
115
|
true
|
116
116
|
end
|
117
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
|
+
|
118
138
|
private
|
119
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
|
+
|
120
148
|
def bulk_scope(scope, options)
|
121
|
-
|
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
|
122
154
|
end
|
123
155
|
|
124
156
|
def sort_scope(scope, options)
|
@@ -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
|
@@ -134,6 +134,12 @@ module RailsAdmin
|
|
134
134
|
bindings[:object].send(association.name)
|
135
135
|
end
|
136
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
|
+
|
137
143
|
# has many?
|
138
144
|
def multiple?
|
139
145
|
true
|
@@ -146,6 +152,16 @@ module RailsAdmin
|
|
146
152
|
def associated_model_limit
|
147
153
|
RailsAdmin.config.default_associated_collection_limit
|
148
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
|
149
165
|
end
|
150
166
|
end
|
151
167
|
end
|
@@ -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
|
@@ -51,11 +48,11 @@ module RailsAdmin
|
|
51
48
|
def resource_url(thumb = false)
|
52
49
|
return nil unless value
|
53
50
|
|
54
|
-
if thumb && value.
|
51
|
+
if thumb && value.representable?
|
55
52
|
thumb = thumb_method if thumb == true
|
56
|
-
|
53
|
+
representation = value.representation(thumb)
|
57
54
|
Rails.application.routes.url_helpers.rails_blob_representation_path(
|
58
|
-
|
55
|
+
representation.blob.signed_id, representation.variation.key, representation.blob.filename, only_path: true
|
59
56
|
)
|
60
57
|
else
|
61
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,54 +1,33 @@
|
|
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 :filter_operators do
|
14
|
-
%w[_discard like not_like is starts_with ends_with] + (required? ? [] : %w[_separator _present _blank])
|
15
|
-
end
|
16
|
-
|
17
|
-
register_instance_option :partial do
|
18
|
-
nested_form ? :form_nested_one : :form_filtering_select
|
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
13
|
register_instance_option :allowed_methods do
|
27
14
|
nested_form ? [method_name] : [name]
|
28
15
|
end
|
29
16
|
|
30
|
-
def selected_id
|
31
|
-
value.try(:id).try(:to_s)
|
32
|
-
end
|
33
|
-
|
34
|
-
def method_name
|
35
|
-
nested_form ? :"#{name}_attributes" : super
|
36
|
-
end
|
37
|
-
|
38
|
-
def multiple?
|
39
|
-
false
|
40
|
-
end
|
41
|
-
|
42
17
|
def associated_prepopulate_params
|
43
18
|
{associated_model_config.abstract_model.param_key => {association.foreign_key => bindings[:object].try(:id)}}
|
44
19
|
end
|
45
20
|
|
46
21
|
def parse_input(params)
|
47
|
-
return if nested_form
|
22
|
+
return super if nested_form
|
48
23
|
|
49
24
|
id = params.delete(method_name)
|
50
25
|
params[name] = associated_model_config.abstract_model.get(id) if id
|
51
26
|
end
|
27
|
+
|
28
|
+
def selected_id
|
29
|
+
format_key(value.try(:id)).try(:to_s)
|
30
|
+
end
|
52
31
|
end
|
53
32
|
end
|
54
33
|
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)
|
@@ -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
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsAdmin
|
4
|
+
module Extensions
|
5
|
+
module UrlForExtension
|
6
|
+
def url_for(options, *args)
|
7
|
+
case options[:id]
|
8
|
+
when Array
|
9
|
+
options[:id] = RailsAdmin.config.composite_keys_serializer.serialize(options[:id])
|
10
|
+
end
|
11
|
+
super options, *args
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsAdmin
|
4
|
+
module Support
|
5
|
+
module CompositeKeysSerializer
|
6
|
+
def self.serialize(keys)
|
7
|
+
keys.map { |key| key&.to_s&.gsub('_', '__') }.join('_')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.deserialize(string)
|
11
|
+
string.split('_').map { |key| key&.gsub('__', '_') }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/rails_admin/version.rb
CHANGED
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "rails_admin",
|
3
|
-
"version": "3.2.0-
|
3
|
+
"version": "3.2.0-rc",
|
4
4
|
"description": "RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data.",
|
5
5
|
"homepage": "https://github.com/railsadminteam/rails_admin",
|
6
6
|
"license": "MIT",
|
@@ -22,7 +22,7 @@
|
|
22
22
|
"bootstrap": "^5.1.3",
|
23
23
|
"flatpickr": "^4.6.9",
|
24
24
|
"jquery": "^3.6.0",
|
25
|
-
"jquery-ui": "^1.12.1"
|
25
|
+
"jquery-ui": "^1.12.1 <1.14.0"
|
26
26
|
},
|
27
27
|
"devDependencies": {
|
28
28
|
"prettier": "^2.4.1"
|
data/src/rails_admin/widgets.js
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_admin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.0.
|
4
|
+
version: 3.2.0.rc
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Michaels-Ober
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2024-
|
15
|
+
date: 2024-08-25 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activemodel-serializers-xml
|
@@ -220,8 +220,6 @@ files:
|
|
220
220
|
- lib/rails_admin/adapters/active_record/association.rb
|
221
221
|
- lib/rails_admin/adapters/active_record/object_extension.rb
|
222
222
|
- lib/rails_admin/adapters/active_record/property.rb
|
223
|
-
- lib/rails_admin/adapters/composite_primary_keys.rb
|
224
|
-
- lib/rails_admin/adapters/composite_primary_keys/association.rb
|
225
223
|
- lib/rails_admin/adapters/mongoid.rb
|
226
224
|
- lib/rails_admin/adapters/mongoid/association.rb
|
227
225
|
- lib/rails_admin/adapters/mongoid/bson.rb
|
@@ -247,6 +245,7 @@ files:
|
|
247
245
|
- lib/rails_admin/config/fields.rb
|
248
246
|
- lib/rails_admin/config/fields/association.rb
|
249
247
|
- lib/rails_admin/config/fields/base.rb
|
248
|
+
- lib/rails_admin/config/fields/collection_association.rb
|
250
249
|
- lib/rails_admin/config/fields/factories/action_text.rb
|
251
250
|
- lib/rails_admin/config/fields/factories/active_storage.rb
|
252
251
|
- lib/rails_admin/config/fields/factories/association.rb
|
@@ -258,6 +257,7 @@ files:
|
|
258
257
|
- lib/rails_admin/config/fields/factories/password.rb
|
259
258
|
- lib/rails_admin/config/fields/factories/shrine.rb
|
260
259
|
- lib/rails_admin/config/fields/group.rb
|
260
|
+
- lib/rails_admin/config/fields/singular_association.rb
|
261
261
|
- lib/rails_admin/config/fields/types.rb
|
262
262
|
- lib/rails_admin/config/fields/types/action_text.rb
|
263
263
|
- lib/rails_admin/config/fields/types/active_record_enum.rb
|
@@ -271,7 +271,6 @@ files:
|
|
271
271
|
- lib/rails_admin/config/fields/types/ck_editor.rb
|
272
272
|
- lib/rails_admin/config/fields/types/code_mirror.rb
|
273
273
|
- lib/rails_admin/config/fields/types/color.rb
|
274
|
-
- lib/rails_admin/config/fields/types/composite_keys_belongs_to_association.rb
|
275
274
|
- lib/rails_admin/config/fields/types/date.rb
|
276
275
|
- lib/rails_admin/config/fields/types/datetime.rb
|
277
276
|
- lib/rails_admin/config/fields/types/decimal.rb
|
@@ -333,6 +332,8 @@ files:
|
|
333
332
|
- lib/rails_admin/extensions/paper_trail/auditing_adapter.rb
|
334
333
|
- lib/rails_admin/extensions/pundit.rb
|
335
334
|
- lib/rails_admin/extensions/pundit/authorization_adapter.rb
|
335
|
+
- lib/rails_admin/extensions/url_for_extension.rb
|
336
|
+
- lib/rails_admin/support/composite_keys_serializer.rb
|
336
337
|
- lib/rails_admin/support/csv_converter.rb
|
337
338
|
- lib/rails_admin/support/datetime.rb
|
338
339
|
- lib/rails_admin/support/es_module_processor.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RailsAdmin
|
4
|
-
module Adapters
|
5
|
-
module CompositePrimaryKeys
|
6
|
-
class Association < RailsAdmin::Adapters::ActiveRecord::Association
|
7
|
-
def field_type
|
8
|
-
if type == :belongs_to && association.foreign_key.is_a?(Array)
|
9
|
-
:composite_keys_belongs_to_association
|
10
|
-
else
|
11
|
-
super
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def primary_key
|
16
|
-
return nil if polymorphic?
|
17
|
-
|
18
|
-
value = association.association_primary_key
|
19
|
-
|
20
|
-
if value.is_a? Array
|
21
|
-
:id
|
22
|
-
else
|
23
|
-
value.to_sym
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def foreign_key
|
28
|
-
if association.foreign_key.is_a? Array
|
29
|
-
association.foreign_key.map(&:to_sym)
|
30
|
-
else
|
31
|
-
super
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def key_accessor
|
36
|
-
if type == :belongs_to && foreign_key.is_a?(Array)
|
37
|
-
:"#{name}_id"
|
38
|
-
else
|
39
|
-
super
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_admin/adapters/active_record'
|
4
|
-
require 'rails_admin/adapters/composite_primary_keys/association'
|
5
|
-
|
6
|
-
module RailsAdmin
|
7
|
-
module Adapters
|
8
|
-
module CompositePrimaryKeys
|
9
|
-
include RailsAdmin::Adapters::ActiveRecord
|
10
|
-
|
11
|
-
def get(id, scope = scoped)
|
12
|
-
begin
|
13
|
-
object = scope.find(id)
|
14
|
-
rescue ::ActiveRecord::RecordNotFound
|
15
|
-
return nil
|
16
|
-
end
|
17
|
-
|
18
|
-
object.extend(RailsAdmin::Adapters::ActiveRecord::ObjectExtension)
|
19
|
-
end
|
20
|
-
|
21
|
-
def associations
|
22
|
-
model.reflect_on_all_associations.collect do |association|
|
23
|
-
RailsAdmin::Adapters::CompositePrimaryKeys::Association.new(association, model)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def bulk_scope(scope, options)
|
30
|
-
if primary_key.is_a? Array
|
31
|
-
options[:bulk_ids].map do |id|
|
32
|
-
scope.where(primary_key.zip(::CompositePrimaryKeys::CompositeKeys.parse(id)).to_h)
|
33
|
-
end.reduce(&:or)
|
34
|
-
else
|
35
|
-
super
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_admin/config/fields/types/belongs_to_association'
|
4
|
-
|
5
|
-
module RailsAdmin
|
6
|
-
module Config
|
7
|
-
module Fields
|
8
|
-
module Types
|
9
|
-
class CompositeKeysBelongsToAssociation < RailsAdmin::Config::Fields::Types::BelongsToAssociation
|
10
|
-
RailsAdmin::Config::Fields::Types.register(self)
|
11
|
-
|
12
|
-
register_instance_option :allowed_methods do
|
13
|
-
nested_form ? [method_name] : Array(association.foreign_key)
|
14
|
-
end
|
15
|
-
|
16
|
-
def selected_id
|
17
|
-
association.foreign_key.map { |attribute| bindings[:object].safe_send(attribute) }.to_composite_keys.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
def parse_input(params)
|
21
|
-
return unless params[method_name].present? && association.foreign_key.is_a?(Array) && !nested_form
|
22
|
-
|
23
|
-
association.foreign_key.zip(CompositePrimaryKeys::CompositeKeys.parse(params.delete(method_name))).each do |key, value|
|
24
|
-
params[key] = value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|