rails_admin 3.2.0.beta → 3.2.0.rc
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 +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
|