rails_admin 3.1.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +20 -15
  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 +10 -7
  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/app/views/rails_admin/main/index.html.erb +2 -2
  19. data/config/initializers/active_record_extensions.rb +0 -23
  20. data/lib/generators/rails_admin/importmap_formatter.rb +1 -1
  21. data/lib/generators/rails_admin/install_generator.rb +13 -1
  22. data/lib/generators/rails_admin/templates/rails_admin.vite.js +2 -0
  23. data/lib/rails_admin/abstract_model.rb +18 -7
  24. data/lib/rails_admin/adapters/active_record/association.rb +27 -10
  25. data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
  26. data/lib/rails_admin/adapters/active_record.rb +52 -5
  27. data/lib/rails_admin/adapters/active_record.rb.bak +348 -0
  28. data/lib/rails_admin/adapters/mongoid/association.rb +3 -3
  29. data/lib/rails_admin/adapters/mongoid/bson.rb +1 -0
  30. data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
  31. data/lib/rails_admin/adapters/mongoid.rb +8 -3
  32. data/lib/rails_admin/config/actions/index.rb +5 -3
  33. data/lib/rails_admin/config/fields/association.rb +41 -2
  34. data/lib/rails_admin/config/fields/base.rb +5 -5
  35. data/lib/rails_admin/config/fields/collection_association.rb +90 -0
  36. data/lib/rails_admin/config/fields/factories/active_storage.rb +2 -2
  37. data/lib/rails_admin/config/fields/factories/carrierwave.rb +1 -1
  38. data/lib/rails_admin/config/fields/factories/dragonfly.rb +1 -1
  39. data/lib/rails_admin/config/fields/factories/paperclip.rb +1 -1
  40. data/lib/rails_admin/config/fields/factories/shrine.rb +1 -1
  41. data/lib/rails_admin/config/fields/singular_association.rb +59 -0
  42. data/lib/rails_admin/config/fields/types/active_storage.rb +12 -7
  43. data/lib/rails_admin/config/fields/types/all.rb +0 -1
  44. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +17 -20
  45. data/lib/rails_admin/config/fields/types/dragonfly.rb +0 -1
  46. data/lib/rails_admin/config/fields/types/file_upload.rb +7 -1
  47. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -2
  48. data/lib/rails_admin/config/fields/types/has_many_association.rb +2 -24
  49. data/lib/rails_admin/config/fields/types/has_one_association.rb +12 -22
  50. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +13 -8
  51. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +7 -1
  52. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +32 -9
  53. data/lib/rails_admin/config.rb +5 -0
  54. data/lib/rails_admin/engine.rb +5 -0
  55. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +1 -1
  56. data/lib/rails_admin/extensions/url_for_extension.rb +15 -0
  57. data/lib/rails_admin/support/composite_keys_serializer.rb +15 -0
  58. data/lib/rails_admin/support/datetime.rb +1 -0
  59. data/lib/rails_admin/version.rb +2 -2
  60. data/package.json +2 -2
  61. data/src/rails_admin/abstract-select.js +30 -0
  62. data/src/rails_admin/base.js +4 -1
  63. data/src/rails_admin/filtering-multiselect.js +2 -4
  64. data/src/rails_admin/filtering-select.js +2 -4
  65. metadata +41 -16
  66. data/lib/rails_admin/adapters/composite_primary_keys/association.rb +0 -45
  67. data/lib/rails_admin/adapters/composite_primary_keys.rb +0 -40
  68. 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: 30d6fc9f03e406c3d6fa8dd301e3eef853896b37cac25945932c0d419a7976be
4
- data.tar.gz: 508731ccf0a76e22863b6734ea577810cace41acc9c88ab8211b09a7bdf4a74e
3
+ metadata.gz: 88dd830859396863dc21eab6dec1f7a63f1461e15b73a72affe62a9a869bf1c2
4
+ data.tar.gz: 71fd4db63b36b2b74963811c83fb1daed9a58df33a5f5d23aa4491895217fa43
5
5
  SHA512:
6
- metadata.gz: 16acc5f74fa950492490ed2a20e589368bf67f5d614b8c729aec7308240d0c8e1b7e92531408681a169b1670cd11dbb0cc500ac69517755f5fb7b5e84447a4ad
7
- data.tar.gz: 06bf86fd3219b28249f42503f0de0a053b4c528a995c06096d2c44f9250cc8383ba32709d31d43b022608d177531754fcf4bde2dff82ad55beb9a5ba4517928e
6
+ metadata.gz: 162243c834a4170045a43debd41e8d87ba27c81130770243cbd659af4077f46e2c8557667638c40608de9d0f765cebfd415556f4fd610cd884968837a8d28fc6
7
+ data.tar.gz: cec35b0c4b4ab71d967ac933b7eb15f51170742ce978996f913873c4f180d069bb680682eb658f571c4641ff351217d9f8c7744b998e5f3d8933636cb1b40f64
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
- gem 'factory_bot', '>= 4.2'
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.0'
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,8 @@
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
+ <meta content="false" name="turbo-prefetch">
5
6
  <%= csrf_meta_tag %>
6
7
  <% case RailsAdmin::config.asset_source
7
8
  when :webpacker %>
@@ -12,6 +13,8 @@
12
13
  <%= stylesheet_link_tag "rails_admin/application.css", media: :all, data: {'turbo-track': 'reload'} %>
13
14
  <%= javascript_include_tag "rails_admin/application.js", defer: true, data: {'turbo-track': 'reload'} %>
14
15
  <% end %>
16
+ <% when :vite %>
17
+ <%= vite_javascript_tag "rails_admin", defer: true, data: {'turbo-track': 'reload'} %>
15
18
  <% when :webpack %>
16
19
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
17
20
  <%= javascript_include_tag "rails_admin.js", defer: true, data: {'turbo-track': 'reload'} %>
@@ -19,11 +22,11 @@
19
22
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
20
23
  <%= javascript_inline_importmap_tag(RailsAdmin::Engine.importmap.to_json(resolver: self)) %>
21
24
  <%= javascript_importmap_module_preload_tags(RailsAdmin::Engine.importmap) %>
22
- <%= javascript_importmap_shim_nonce_configuration_tag %>
23
- <%= javascript_importmap_shim_tag %>
25
+ <%= javascript_importmap_shim_nonce_configuration_tag if respond_to? :javascript_importmap_shim_nonce_configuration_tag %>
26
+ <%= javascript_importmap_shim_tag if respond_to? :javascript_importmap_shim_tag %>
24
27
  <%= # Preload jQuery and make it global, unless jQuery UI fails to initialize
25
28
  tag.script "import jQuery from 'jquery'; window.jQuery = jQuery;".html_safe, type: "module" %>
26
29
  <%= javascript_import_module_tag 'rails_admin' %>
27
30
  <% else
28
31
  raise "Unknown asset_source: #{RailsAdmin::config.asset_source}"
29
- end %>
32
+ 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>
@@ -133,9 +133,9 @@
133
133
  <% end %>
134
134
  <% properties.map{ |property| property.bind(:object, object) }.each do |property| %>
135
135
  <% value = property.pretty_value %>
136
- <td class="<%= [property.sticky? && 'sticky', property.css_class, property.type_css_class].select(&:present?).join(' ') %>" title="<%= strip_tags(value.to_s) %>">
136
+ <%= content_tag(:td, class: [property.sticky? && 'sticky', property.css_class, property.type_css_class].select(&:present?), title: strip_tags(value.to_s)) do %>
137
137
  <%= value %>
138
- </td>
138
+ <% end %>
139
139
  <% end %>
140
140
  <td class="last links ra-sidescroll-frozen">
141
141
  <ul class="nav d-inline list-inline">
@@ -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?
@@ -71,11 +84,15 @@ module RailsAdmin
71
84
  def key_accessor
72
85
  case type
73
86
  when :has_many, :has_and_belongs_to_many
74
- "#{name.to_s.singularize}_ids".to_sym
87
+ :"#{name.to_s.singularize}_ids"
75
88
  when :has_one
76
- "#{name}_id".to_sym
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