rails_admin 3.1.4 → 3.2.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +19 -14
  3. data/README.md +2 -2
  4. data/app/assets/javascripts/rails_admin/application.js.erb +3 -2
  5. data/app/assets/stylesheets/rails_admin/application.scss.erb +1 -1
  6. data/app/controllers/rails_admin/main_controller.rb +5 -1
  7. data/app/helpers/rails_admin/application_helper.rb +4 -0
  8. data/app/helpers/rails_admin/form_builder.rb +2 -2
  9. data/app/helpers/rails_admin/main_helper.rb +1 -1
  10. data/app/views/layouts/rails_admin/_head.html.erb +7 -5
  11. data/app/views/rails_admin/main/_form_boolean.html.erb +2 -2
  12. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +5 -35
  13. data/app/views/rails_admin/main/_form_filtering_select.html.erb +6 -18
  14. data/app/views/rails_admin/main/_form_nested_many.html.erb +1 -1
  15. data/app/views/rails_admin/main/_form_nested_one.html.erb +1 -1
  16. data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +12 -21
  17. data/app/views/rails_admin/main/delete.html.erb +1 -1
  18. data/config/initializers/active_record_extensions.rb +0 -23
  19. data/lib/generators/rails_admin/importmap_formatter.rb +1 -1
  20. data/lib/generators/rails_admin/install_generator.rb +13 -1
  21. data/lib/generators/rails_admin/templates/rails_admin.vite.js +2 -0
  22. data/lib/rails_admin/abstract_model.rb +18 -7
  23. data/lib/rails_admin/adapters/active_record/association.rb +25 -8
  24. data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
  25. data/lib/rails_admin/adapters/active_record.rb +51 -5
  26. data/lib/rails_admin/adapters/mongoid/association.rb +1 -1
  27. data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
  28. data/lib/rails_admin/adapters/mongoid.rb +6 -3
  29. data/lib/rails_admin/config/actions/index.rb +5 -3
  30. data/lib/rails_admin/config/fields/association.rb +41 -2
  31. data/lib/rails_admin/config/fields/base.rb +4 -4
  32. data/lib/rails_admin/config/fields/collection_association.rb +90 -0
  33. data/lib/rails_admin/config/fields/singular_association.rb +59 -0
  34. data/lib/rails_admin/config/fields/types/active_storage.rb +12 -7
  35. data/lib/rails_admin/config/fields/types/all.rb +0 -1
  36. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +17 -20
  37. data/lib/rails_admin/config/fields/types/dragonfly.rb +0 -1
  38. data/lib/rails_admin/config/fields/types/file_upload.rb +7 -1
  39. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -2
  40. data/lib/rails_admin/config/fields/types/has_many_association.rb +2 -24
  41. data/lib/rails_admin/config/fields/types/has_one_association.rb +12 -22
  42. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +13 -8
  43. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +7 -1
  44. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +32 -9
  45. data/lib/rails_admin/config.rb +5 -0
  46. data/lib/rails_admin/engine.rb +5 -0
  47. data/lib/rails_admin/extensions/url_for_extension.rb +15 -0
  48. data/lib/rails_admin/support/composite_keys_serializer.rb +15 -0
  49. data/lib/rails_admin/support/datetime.rb +1 -0
  50. data/lib/rails_admin/version.rb +3 -3
  51. data/package.json +2 -2
  52. data/src/rails_admin/abstract-select.js +30 -0
  53. data/src/rails_admin/base.js +4 -1
  54. data/src/rails_admin/filtering-multiselect.js +2 -4
  55. data/src/rails_admin/filtering-select.js +1 -4
  56. data/src/rails_admin/widgets.js +1 -0
  57. metadata +39 -15
  58. data/lib/rails_admin/adapters/composite_primary_keys/association.rb +0 -45
  59. data/lib/rails_admin/adapters/composite_primary_keys.rb +0 -40
  60. 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: d5c339d2ccdf48b8a126925a718e54ad8532ee871a33fa22fb5ffb1c3a5ba4c1
4
- data.tar.gz: 24b7a110bea7b982955181511f8153ffdadc678ba9bb385bc5593e960d4b8aaa
3
+ metadata.gz: bb8262bbe1aab2c4d873c5a470ca69ff43800ba59d0f319d20039be36e34a640
4
+ data.tar.gz: 7dea99571de5a200d22096ee47881d0b114033eb8643d95af58041115cf66088
5
5
  SHA512:
6
- metadata.gz: ad40b7df17867ef7a1fb1a876439d0973c5cfbc6664425b99fa316a1585e22f1d3aca77c06c4482df1d0973c5deaf2823623fc1c359d4da5c59903b73172ac15
7
- data.tar.gz: 0baddc871248327616c90514329513150b0d903339f6cd3a1562b16600a00242e7f02b8c9d1a8ec81421d65cb5cf2550ee15abdafa2ba0f804f7d45e5d645812
6
+ metadata.gz: ddb8cabf32fa1023033bc51d8eb2ffa287a8981f7bd10dd862237f1aa5e1a8b84c8b2df64558e1a9bca6c306af42239e952988959fb26b2d68228f9bf828f62d
7
+ data.tar.gz: ee7a91df4279aa73f889c83c52bcd6e5bb64ae217e2e03aa92bcef08f084f0bef8ce1736405fe390d4c9e5651349cff9e5cc789b0cd7899dce4d911b4125ff05
data/Gemfile CHANGED
@@ -3,20 +3,14 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'appraisal', '>= 2.0'
6
- gem 'devise'
6
+ gem 'devise', '~> 4.7'
7
7
  gem 'net-smtp', require: false
8
8
  gem 'rails'
9
+ gem 'sassc-rails', '~> 2.1'
10
+ gem 'turbo-rails'
11
+ gem 'vite_rails', require: false
9
12
  gem 'webpacker', require: false
10
- gem 'webrick', '~> 1.7'
11
-
12
- group :active_record do
13
- gem 'paper_trail'
14
-
15
- platforms :ruby, :mswin, :mingw, :x64_mingw do
16
- gem 'mysql2', '>= 0.3.14'
17
- gem 'sqlite3', '~> 1.3'
18
- end
19
- end
13
+ gem 'webrick'
20
14
 
21
15
  group :development, :test do
22
16
  gem 'pry', '>= 0.9'
@@ -25,21 +19,22 @@ end
25
19
  group :test do
26
20
  gem 'cancancan', '~> 3.0'
27
21
  gem 'carrierwave', ['>= 2.0.0.rc', '< 3']
28
- gem 'cuprite'
22
+ gem 'cuprite', '!= 0.15.1'
29
23
  gem 'database_cleaner-active_record', '>= 2.0', require: false
30
- gem 'database_cleaner-mongoid', '>= 2.0', require: false
31
24
  gem 'dragonfly', '~> 1.0'
32
25
  gem 'factory_bot', '>= 4.2', '!= 6.4.5'
33
26
  gem 'generator_spec', '>= 0.8'
27
+ gem 'kt-paperclip'
34
28
  gem 'launchy', '>= 2.2'
35
29
  gem 'mini_magick', '>= 3.4'
36
30
  gem 'pundit'
37
31
  gem 'rack-cache', require: 'rack/cache'
38
32
  gem 'rspec-expectations', '!= 3.8.3'
39
- gem 'rspec-rails', '>= 2.14'
33
+ gem 'rspec-rails', '>= 4.0.0.beta2'
40
34
  gem 'rspec-retry'
41
35
  gem 'rubocop', ['~> 1.20', '!= 1.22.2'], require: false
42
36
  gem 'rubocop-performance', require: false
37
+ gem 'shrine', '~> 3.0'
43
38
  gem 'simplecov', '>= 0.9', require: false
44
39
  gem 'simplecov-lcov', require: false
45
40
  gem 'timecop', '>= 0.5'
@@ -48,4 +43,14 @@ group :test do
48
43
  gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
49
44
  end
50
45
 
46
+ group :active_record do
47
+ gem 'paper_trail', '>= 12.0'
48
+
49
+ platforms :ruby, :mswin, :mingw, :x64_mingw do
50
+ gem 'mysql2', '>= 0.3.14'
51
+ gem 'pg', '>= 1.0.0'
52
+ gem 'sqlite3', '~> 1.3'
53
+ end
54
+ end
55
+
51
56
  gemspec
data/README.md CHANGED
@@ -19,8 +19,8 @@ RailsAdmin is a Rails engine that provides an easy-to-use interface for managing
19
19
  - Check out [the docs][docs].
20
20
  - Try the [live demo][demo]. ([Source code][dummy_app])
21
21
 
22
- [demo]: http://rails-admin-tb.herokuapp.com/
23
- [dummy_app]: https://github.com/bbenezech/dummy_app
22
+ [demo]: https://rails-admin.fly.dev/admin/
23
+ [dummy_app]: https://github.com/railsadminteam/rails_admin/tree/master/spec/dummy_app
24
24
  [docs]: https://github.com/railsadminteam/rails_admin/wiki
25
25
 
26
26
  ## Features
@@ -9,6 +9,7 @@
9
9
  //= require 'rails_admin/popper'
10
10
  //= require 'rails_admin/bootstrap'
11
11
 
12
+ //= require 'rails_admin/abstract-select'
12
13
  //= require 'rails_admin/filter-box'
13
14
  //= require 'rails_admin/filtering-multiselect'
14
15
  //= require 'rails_admin/filtering-select'
@@ -20,10 +21,10 @@
20
21
  //= require 'rails_admin/ui'
21
22
  //= require 'rails_admin/custom/ui'
22
23
 
23
- <% if defined?(ActiveStorage) %>
24
+ <% if defined?(ActiveStorage::Engine) %>
24
25
  //= require activestorage
25
26
  <% end %>
26
- <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
27
+ <% if defined?(ActionText::Engine) && Rails.gem_version >= Gem::Version.new('7.0') %>
27
28
  //= require trix
28
29
  //= require actiontext
29
30
  <% end %>
@@ -30,6 +30,6 @@
30
30
  @import "rails_admin/styles/base/theming";
31
31
  @import "rails_admin/custom/theming";
32
32
 
33
- <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
33
+ <% if defined?(ActionText::Engine) && Rails.gem_version >= Gem::Version.new('7.0') %>
34
34
  @import "trix";
35
35
  <% end %>
@@ -56,7 +56,11 @@ module RailsAdmin
56
56
  end
57
57
 
58
58
  def back_or_index
59
- params[:return_to].presence && params[:return_to].include?(request.host) && (params[:return_to] != request.fullpath) ? params[:return_to] : index_path
59
+ allowed_return_to?(params[:return_to].to_s) ? params[:return_to] : index_path
60
+ end
61
+
62
+ def allowed_return_to?(url)
63
+ url != request.fullpath && url.start_with?(request.base_url, '/') && !url.start_with?('//')
60
64
  end
61
65
 
62
66
  def get_sort_hash(model_config)
@@ -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.to_s}
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
@@ -45,7 +45,7 @@ module RailsAdmin
45
45
  filter_for_field = duplet[1]
46
46
  filter_name = filter_for_field.keys.first
47
47
  filter_hash = filter_for_field.values.first
48
- unless (field = filterable_fields.find { |f| f.name == filter_name.to_sym })
48
+ unless (field = filterable_fields.find { |f| f.name == filter_name.to_sym }&.with({view: self}))
49
49
  raise "#{filter_name} is not currently filterable; filterable fields are #{filterable_fields.map(&:name).join(', ')}"
50
50
  end
51
51
 
@@ -1,7 +1,7 @@
1
- <meta content="IE=edge" http-equiv="X-UA-Compatible"/>
2
- <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
3
- <meta content="width=device-width, initial-scale=1" name="viewport; charset=utf-8"/>
4
- <meta content="NONE,NOARCHIVE" name="robots"/>
1
+ <meta content="IE=edge" http-equiv="X-UA-Compatible">
2
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
3
+ <meta content="width=device-width, initial-scale=1" name="viewport; charset=utf-8">
4
+ <meta content="NONE,NOARCHIVE" name="robots">
5
5
  <%= csrf_meta_tag %>
6
6
  <% case RailsAdmin::config.asset_source
7
7
  when :webpacker %>
@@ -12,6 +12,8 @@
12
12
  <%= stylesheet_link_tag "rails_admin/application.css", media: :all, data: {'turbo-track': 'reload'} %>
13
13
  <%= javascript_include_tag "rails_admin/application.js", defer: true, data: {'turbo-track': 'reload'} %>
14
14
  <% end %>
15
+ <% when :vite %>
16
+ <%= vite_javascript_tag "rails_admin", defer: true, data: {'turbo-track': 'reload'} %>
15
17
  <% when :webpack %>
16
18
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
17
19
  <%= javascript_include_tag "rails_admin.js", defer: true, data: {'turbo-track': 'reload'} %>
@@ -26,4 +28,4 @@
26
28
  <%= javascript_import_module_tag 'rails_admin' %>
27
29
  <% else
28
30
  raise "Unknown asset_source: #{RailsAdmin::config.asset_source}"
29
- end %>
31
+ end %>
@@ -2,9 +2,9 @@
2
2
  <div class="btn-group" role="group">
3
3
  <% {'1': [true, 'btn-outline-success'], '0': [false, 'btn-outline-danger'], '': [nil, 'btn-outline-secondary']}.each do |text, (value, btn_class)| %>
4
4
  <%= form.radio_button field.method_name, text, field.html_attributes.reverse_merge({ checked: field.form_value == value, required: field.required, class: 'btn-check' }) %>
5
- <label for="<%= form.object_name %>_<%= field.method_name %>_<%= text %>" class="<%= field.css_classes[value] %> btn <%= btn_class %>">
5
+ <%= form.label "#{field.method_name}_#{text}", class: "#{field.css_classes[value]} btn #{btn_class}" do %>
6
6
  <%= field.labels[value].html_safe %>
7
- </label>
7
+ <% end %>
8
8
  <% end %>
9
9
  </div>
10
10
  <% else %>
@@ -1,44 +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
- sortable: !!field.orderable,
24
- removable: !!field.removable,
25
- cacheAll: !!field.associated_collection_cache_all,
26
- regional: {
27
- add: t('admin.misc.add_new'),
28
- chooseAll: t('admin.misc.chose_all'),
29
- clearAll: t('admin.misc.clear_all'),
30
- down: t('admin.misc.down'),
31
- remove: t('admin.misc.remove'),
32
- search: t('admin.misc.search'),
33
- up: t('admin.misc.up')
34
- }
35
- }
36
3
  %>
4
+
37
5
  <div class="row">
38
6
  <div class="col-auto">
39
7
  <input name="<%= form.dom_name(field) %>" type="hidden" />
40
- <% selected_ids = (hdv = field.form_default_value).nil? ? selected_ids : hdv %>
41
- <%= form.select field.method_name, collection, { selected: selected_ids, object: form.object }, field.html_attributes.reverse_merge({data: { filteringmultiselect: true, options: js_data.to_json }, multiple: true}) %>
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
+ %>
42
12
  </div>
43
13
  <% if authorized?(:new, config.abstract_model) && field.inline_add %>
44
14
  <div class="col-sm-4 modal-actions">
@@ -1,33 +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
- }
17
3
  %>
18
4
 
19
5
  <div class="row">
20
6
  <div class="col-sm-4">
21
- <% selected_id = (hdv = field.form_default_value).nil? ? field.selected_id : hdv %>
22
- <%= form.select field.method_name, collection, { selected: selected_id, include_blank: true }, field.html_attributes.reverse_merge({ data: { filteringselect: true, options: js_data.to_json }, placeholder: t('admin.misc.search') }) %>
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
+ %>
23
11
  </div>
24
12
  <div class="col-sm-8 mt-2 mt-md-0 modal-actions">
25
13
  <% if authorized?(:new, config.abstract_model) && field.inline_add %>
26
14
  <% path_hash = { model_name: config.abstract_model.to_param, modal: true }.merge!(field.associated_prepopulate_params) %>
27
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" %>
28
16
  <% end %>
29
- <% if edit_url.present? && field.inline_edit %>
30
- <%= link_to "<i class=\"fas fa-pencil-alt\"></i> ".html_safe + wording_for(:link, :edit, config.abstract_model), '#', data: { link: edit_url }, class: "btn btn-info update ms-2#{' disabled' if field.value.nil?}" %>
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?}" %>
31
19
  <% end %>
32
20
  </div>
33
21
  </div>
@@ -3,7 +3,7 @@
3
3
  <a class="<%= (field.active? ? 'active' : '') %> btn btn-info toggler" data-bs-target="<%= form.jquery_namespace(field) %> .collapse" data-bs-toggle="collapse" role="button">
4
4
  <i class="fas"></i>
5
5
  </a>
6
- <% unless field.nested_form[:update_only] || !field.inline_add %>
6
+ <% if field.inline_add %>
7
7
  <%= form.link_to_add "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".html_safe, field.name, { class: 'btn btn-info' } %>
8
8
  <% end %>
9
9
  </div>
@@ -4,7 +4,7 @@
4
4
  <a class="<%= (field.active? ? 'active' : '') %> btn btn-info toggler" data-bs-target="<%= form.jquery_namespace(field) %> .collapse" data-bs-toggle="collapse" role="button">
5
5
  <i class="fas"></i>
6
6
  </a>
7
- <% unless field.nested_form[:update_only] || !field.inline_add %>
7
+ <% if field.inline_add %>
8
8
  <%= form.link_to_add "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".html_safe, field.name, { class: 'btn btn-info', :'data-add-label' => "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".gsub("\n", "") } %>
9
9
  <% end %>
10
10
  </div>
@@ -1,32 +1,23 @@
1
1
  <%
2
- type_collection = field.polymorphic_type_collection
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
- <% js_data.each do |model, value| %>
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
- <%= form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-select", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }, style: "float: left; margin-right: 10px;" %>
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
- <%= form.select field.method_name, collection, {include_blank: true, selected: selected.try(:id)}, class: "form-control", data: { filteringselect: true, options: js_data[selected_type.try(:downcase)] || default_options }, placeholder: 'Search' %>
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>
@@ -1,6 +1,6 @@
1
1
  <h4>
2
2
  <%= t("admin.form.are_you_sure_you_want_to_delete_the_object", model_name: @abstract_model.pretty_name.downcase) %>
3
- &ldquo;<strong><%= @model_config.with(object: @object).object_label %></strong>&rdquo;
3
+ <q><strong><%= @model_config.with(object: @object).object_label %></strong></q>
4
4
  <%= t("admin.form.all_of_the_following_related_items_will_be_deleted") %>
5
5
  </h4>
6
6
  <ul>
@@ -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
@@ -6,7 +6,7 @@ module RailsAdmin
6
6
  class ImportmapFormatter
7
7
  attr_reader :packager
8
8
 
9
- def initialize(path = 'confing/importmap.rails_admin.rb')
9
+ def initialize(path = 'config/importmap.rails_admin.rb')
10
10
  @packager = Importmap::Packager.new(path)
11
11
  end
12
12
 
@@ -10,7 +10,7 @@ module RailsAdmin
10
10
  include Generators::Utils::InstanceMethods
11
11
 
12
12
  argument :_namespace, type: :string, required: false, desc: 'RailsAdmin url namespace'
13
- class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, webpack, sprockets, importmap]'
13
+ class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, webpack, sprockets, importmap, vite]'
14
14
  desc 'RailsAdmin installation generator'
15
15
 
16
16
  def install
@@ -33,6 +33,8 @@ module RailsAdmin
33
33
  configure_for_importmap
34
34
  when 'webpacker'
35
35
  configure_for_webpacker5
36
+ when 'vite'
37
+ configure_for_vite
36
38
  when 'sprockets'
37
39
  configure_for_sprockets
38
40
  else
@@ -51,6 +53,8 @@ module RailsAdmin
51
53
  'webpack'
52
54
  elsif Rails.root.join('config/importmap.rb').exist?
53
55
  'importmap'
56
+ elsif defined?(ViteRuby)
57
+ 'vite'
54
58
  else
55
59
  'sprockets'
56
60
  end
@@ -68,6 +72,14 @@ module RailsAdmin
68
72
  add_package_json_field('resolutions', {'rails_admin/@fortawesome/fontawesome-free' => '^5.15.0'})
69
73
  end
70
74
 
75
+ def configure_for_vite
76
+ vite_source_code_dir = ViteRuby.config.source_code_dir
77
+ run "yarn add rails_admin@#{RailsAdmin::Version.js} sass"
78
+ template('rails_admin.vite.js', File.join(vite_source_code_dir, 'entrypoints', 'rails_admin.js'))
79
+ @fa_font_path = '@fortawesome/fontawesome-free/webfonts'
80
+ template('rails_admin.scss.erb', File.join(vite_source_code_dir, 'stylesheets', 'rails_admin.scss'))
81
+ end
82
+
71
83
  def configure_for_webpack
72
84
  run "yarn add rails_admin@#{RailsAdmin::Version.js}"
73
85
  template 'rails_admin.js', 'app/javascript/rails_admin.js'
@@ -0,0 +1,2 @@
1
+ import "~/stylesheets/rails_admin.scss";
2
+ import "rails_admin/src/rails_admin/base";
@@ -60,6 +60,14 @@ module RailsAdmin
60
60
  @model_name.constantize
61
61
  end
62
62
 
63
+ def quoted_table_name
64
+ table_name
65
+ end
66
+
67
+ def quote_column_name(name)
68
+ name
69
+ end
70
+
63
71
  def to_s
64
72
  model.to_s
65
73
  end
@@ -97,17 +105,20 @@ module RailsAdmin
97
105
  end
98
106
  end
99
107
 
108
+ def format_id(id)
109
+ id
110
+ end
111
+
112
+ def parse_id(id)
113
+ id
114
+ end
115
+
100
116
  private
101
117
 
102
118
  def initialize_active_record
103
119
  @adapter = :active_record
104
- if defined?(::CompositePrimaryKeys)
105
- require 'rails_admin/adapters/composite_primary_keys'
106
- extend Adapters::CompositePrimaryKeys
107
- else
108
- require 'rails_admin/adapters/active_record'
109
- extend Adapters::ActiveRecord
110
- end
120
+ require 'rails_admin/adapters/active_record'
121
+ extend Adapters::ActiveRecord
111
122
  end
112
123
 
113
124
  def initialize_mongoid
@@ -33,7 +33,7 @@ module RailsAdmin
33
33
 
34
34
  def klass
35
35
  if options[:polymorphic]
36
- polymorphic_parents(:active_record, model.name.to_s, name) || []
36
+ polymorphic_parents(:active_record, association.active_record.name.to_s, name) || []
37
37
  else
38
38
  association.klass
39
39
  end
@@ -42,16 +42,29 @@ module RailsAdmin
42
42
  def primary_key
43
43
  return nil if polymorphic?
44
44
 
45
- case type
46
- when :has_one
47
- association.klass.primary_key
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
- association.association_primary_key
50
- end.try(:to_sym)
56
+ value.to_sym
57
+ end
51
58
  end
52
59
 
53
60
  def foreign_key
54
- association.foreign_key.to_sym
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
 
@@ -4,24 +4,6 @@ module RailsAdmin
4
4
  module Adapters
5
5
  module ActiveRecord
6
6
  module ObjectExtension
7
- def self.extended(object)
8
- object.class.reflect_on_all_associations.each do |association|
9
- association = Association.new(association, object.class)
10
- case association.type
11
- when :has_one
12
- object.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
13
- def #{association.name}_id
14
- self.#{association.name}&.id
15
- end
16
-
17
- def #{association.name}_id=(item_id)
18
- self.#{association.name} = (#{association.klass}.find(item_id) rescue nil)
19
- end
20
- RUBY
21
- end
22
- end
23
- end
24
-
25
7
  def assign_attributes(attributes)
26
8
  super if attributes
27
9
  end