rails_admin 3.1.4 → 3.2.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +27 -13
  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/main_helper.rb +1 -1
  8. data/app/views/layouts/rails_admin/_head.html.erb +7 -5
  9. data/app/views/rails_admin/main/_form_boolean.html.erb +2 -2
  10. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +1 -0
  11. data/app/views/rails_admin/main/_form_filtering_select.html.erb +2 -1
  12. data/app/views/rails_admin/main/_form_nested_many.html.erb +1 -1
  13. data/app/views/rails_admin/main/_form_nested_one.html.erb +1 -1
  14. data/app/views/rails_admin/main/delete.html.erb +1 -1
  15. data/lib/generators/rails_admin/importmap_formatter.rb +1 -1
  16. data/lib/generators/rails_admin/install_generator.rb +13 -1
  17. data/lib/generators/rails_admin/templates/rails_admin.vite.js +2 -0
  18. data/lib/rails_admin/abstract_model.rb +8 -0
  19. data/lib/rails_admin/adapters/active_record/association.rb +1 -1
  20. data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
  21. data/lib/rails_admin/adapters/active_record.rb +17 -3
  22. data/lib/rails_admin/adapters/mongoid/association.rb +1 -1
  23. data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
  24. data/lib/rails_admin/adapters/mongoid.rb +6 -3
  25. data/lib/rails_admin/config/fields/association.rb +24 -1
  26. data/lib/rails_admin/config/fields/base.rb +4 -4
  27. data/lib/rails_admin/config/fields/types/active_storage.rb +8 -0
  28. data/lib/rails_admin/config/fields/types/has_one_association.rb +11 -0
  29. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +9 -1
  30. data/lib/rails_admin/support/datetime.rb +1 -0
  31. data/lib/rails_admin/version.rb +3 -3
  32. data/package.json +1 -1
  33. data/src/rails_admin/abstract-select.js +30 -0
  34. data/src/rails_admin/base.js +4 -1
  35. data/src/rails_admin/filtering-multiselect.js +2 -4
  36. data/src/rails_admin/filtering-select.js +1 -4
  37. metadata +35 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5c339d2ccdf48b8a126925a718e54ad8532ee871a33fa22fb5ffb1c3a5ba4c1
4
- data.tar.gz: 24b7a110bea7b982955181511f8153ffdadc678ba9bb385bc5593e960d4b8aaa
3
+ metadata.gz: 6ad121e2654221b302244d3792229d2f7ef62e95ff35777196f8f885b945c475
4
+ data.tar.gz: 5f800d3097c56282ed4ec366bf55a2cb839f5bfa481567c16dcdf81684b02ad1
5
5
  SHA512:
6
- metadata.gz: ad40b7df17867ef7a1fb1a876439d0973c5cfbc6664425b99fa316a1585e22f1d3aca77c06c4482df1d0973c5deaf2823623fc1c359d4da5c59903b73172ac15
7
- data.tar.gz: 0baddc871248327616c90514329513150b0d903339f6cd3a1562b16600a00242e7f02b8c9d1a8ec81421d65cb5cf2550ee15abdafa2ba0f804f7d45e5d645812
6
+ metadata.gz: e8f2148f02b5b35e9f7f2ae6a8d635b2f10e9fa99370baa0f78d7bc0805880c6d02097b43b928f0abdcf123294910713e68ab87bc0be2c708d436b3eb425ce3c
7
+ data.tar.gz: d708dc50f78bbe22015721d49213d6991048022d4c6773f6168412ad025cb1a8125579bd9daabb20921f2c12bf8c8a846cdd914aa8fefdb8967e0ec8ec028008
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,23 @@ 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
24
  gem 'database_cleaner-mongoid', '>= 2.0', require: false
31
25
  gem 'dragonfly', '~> 1.0'
32
26
  gem 'factory_bot', '>= 4.2', '!= 6.4.5'
33
27
  gem 'generator_spec', '>= 0.8'
28
+ gem 'kt-paperclip'
34
29
  gem 'launchy', '>= 2.2'
35
30
  gem 'mini_magick', '>= 3.4'
36
31
  gem 'pundit'
37
32
  gem 'rack-cache', require: 'rack/cache'
38
33
  gem 'rspec-expectations', '!= 3.8.3'
39
- gem 'rspec-rails', '>= 2.14'
34
+ gem 'rspec-rails', '>= 4.0.0.beta2'
40
35
  gem 'rspec-retry'
41
36
  gem 'rubocop', ['~> 1.20', '!= 1.22.2'], require: false
42
37
  gem 'rubocop-performance', require: false
38
+ gem 'shrine', '~> 3.0'
43
39
  gem 'simplecov', '>= 0.9', require: false
44
40
  gem 'simplecov-lcov', require: false
45
41
  gem 'timecop', '>= 0.5'
@@ -48,4 +44,22 @@ group :test do
48
44
  gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
49
45
  end
50
46
 
47
+ group :active_record do
48
+ gem 'paper_trail', '>= 12.0'
49
+
50
+ platforms :ruby, :mswin, :mingw, :x64_mingw do
51
+ gem 'mysql2', '>= 0.3.14'
52
+ gem 'pg', '>= 1.0.0'
53
+ gem 'sqlite3', '~> 1.3'
54
+ end
55
+ end
56
+
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
+
51
65
  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)
@@ -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 %>
@@ -20,6 +20,7 @@
20
20
  xhr: xhr,
21
21
  :'edit-url' => (field.inline_edit && authorized?(:edit, config.abstract_model) ? edit_path(model_name: config.abstract_model.to_param, id: '__ID__') : ''),
22
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,
23
24
  sortable: !!field.orderable,
24
25
  removable: !!field.removable,
25
26
  cacheAll: !!field.associated_collection_cache_all,
@@ -12,7 +12,8 @@
12
12
 
13
13
  js_data = {
14
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)
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
16
17
  }
17
18
  %>
18
19
 
@@ -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,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>
@@ -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
@@ -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
@@ -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
@@ -72,6 +72,14 @@ module RailsAdmin
72
72
 
73
73
  delegate :primary_key, :table_name, to: :model, prefix: false
74
74
 
75
+ def quoted_table_name
76
+ model.quoted_table_name
77
+ end
78
+
79
+ def quote_column_name(name)
80
+ model.connection.quote_column_name(name)
81
+ end
82
+
75
83
  def encoding
76
84
  adapter =
77
85
  if ::ActiveRecord::Base.respond_to?(:connection_db_config)
@@ -201,6 +209,8 @@ module RailsAdmin
201
209
  case @type
202
210
  when :boolean
203
211
  boolean_unary_operators
212
+ when :uuid
213
+ uuid_unary_operators
204
214
  when :integer, :decimal, :float
205
215
  numeric_unary_operators
206
216
  else
@@ -230,6 +240,7 @@ module RailsAdmin
230
240
  )
231
241
  end
232
242
  alias_method :numeric_unary_operators, :boolean_unary_operators
243
+ alias_method :uuid_unary_operators, :boolean_unary_operators
233
244
 
234
245
  def range_filter(min, max)
235
246
  if min && max && min == max
@@ -255,9 +266,12 @@ module RailsAdmin
255
266
  end
256
267
 
257
268
  def build_statement_for_boolean
258
- return ["(#{@column} IS NULL OR #{@column} = ?)", false] if %w[false f 0].include?(@value)
259
-
260
- ["(#{@column} = ?)", true] if %w[true t 1].include?(@value)
269
+ case @value
270
+ when 'false', 'f', '0'
271
+ ["(#{@column} IS NULL OR #{@column} = ?)", false]
272
+ when 'true', 't', '1'
273
+ ["(#{@column} = ?)", true]
274
+ end
261
275
  end
262
276
 
263
277
  def column_for_value(value)
@@ -46,7 +46,7 @@ module RailsAdmin
46
46
 
47
47
  def klass
48
48
  if polymorphic? && %i[referenced_in belongs_to].include?(macro)
49
- polymorphic_parents(:mongoid, model.name, name) || []
49
+ polymorphic_parents(:mongoid, association.inverse_class_name, name) || []
50
50
  else
51
51
  association.klass
52
52
  end
@@ -20,11 +20,6 @@ module RailsAdmin
20
20
  send(name)&.save
21
21
  end
22
22
  end
23
- object.instance_eval <<-RUBY, __FILE__, __LINE__ + 1
24
- def #{name}_id=(item_id)
25
- self.#{name} = (#{association.klass}.find(item_id) rescue nil)
26
- end
27
- RUBY
28
23
  end
29
24
  end
30
25
  end
@@ -251,9 +251,12 @@ module RailsAdmin
251
251
  end
252
252
 
253
253
  def build_statement_for_boolean
254
- return {@column => false} if %w[false f 0].include?(@value)
255
-
256
- {@column => true} if %w[true t 1].include?(@value)
254
+ case @value
255
+ when 'false', 'f', '0'
256
+ {@column => false}
257
+ when 'true', 't', '1'
258
+ {@column => true}
259
+ end
257
260
  end
258
261
 
259
262
  def column_for_value(value)
@@ -56,7 +56,30 @@ module RailsAdmin
56
56
  # preload entire associated collection (per associated_collection_scope) on load
57
57
  # Be sure to set limit in associated_collection_scope if set is large
58
58
  register_instance_option :associated_collection_cache_all do
59
- @associated_collection_cache_all ||= (associated_model_config.abstract_model.count < associated_model_limit)
59
+ @associated_collection_cache_all ||= dynamically_scope_by.blank? && (associated_model_config.abstract_model.count < associated_model_limit)
60
+ end
61
+
62
+ # client-side dynamic scoping
63
+ register_instance_option :dynamically_scope_by do
64
+ nil
65
+ end
66
+
67
+ # parses #dynamically_scope_by and returns a Hash in the form of
68
+ # {[form field name in this model]: [field name in the associated model]}
69
+ def dynamic_scope_relationships
70
+ @dynamic_scope_relationships ||=
71
+ Array.wrap(dynamically_scope_by).flat_map do |field|
72
+ field.is_a?(Hash) ? field.to_a : [[field, field]]
73
+ end.map do |field_name, target_name| # rubocop:disable Style/MultilineBlockChain
74
+ field = section.fields.detect { |f| f.name == field_name }
75
+ raise "Field '#{field_name}' was given for #dynamically_scope_by but not found in '#{abstract_model.model_name}'" unless field
76
+
77
+ target_field = associated_model_config.list.fields.detect { |f| f.name == target_name }
78
+ raise "Field '#{field_name}' was given for #dynamically_scope_by but not found in '#{associated_model_config.abstract_model.model_name}'" unless target_field
79
+ raise "Field '#{field_name}' in '#{associated_model_config.abstract_model.model_name}' can't be used for dynamic scoping because it's not filterable" unless target_field.filterable
80
+
81
+ [field.method_name, target_name]
82
+ end.to_h
60
83
  end
61
84
 
62
85
  # determines whether association's elements can be removed
@@ -62,15 +62,15 @@ module RailsAdmin
62
62
 
63
63
  def sort_column
64
64
  if sortable == true
65
- "#{abstract_model.table_name}.#{name}"
65
+ "#{abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(name)}"
66
66
  elsif (sortable.is_a?(String) || sortable.is_a?(Symbol)) && sortable.to_s.include?('.') # just provide sortable, don't do anything smart
67
67
  sortable
68
68
  elsif sortable.is_a?(Hash) # just join sortable hash, don't do anything smart
69
69
  "#{sortable.keys.first}.#{sortable.values.first}"
70
- elsif association # use column on target table
71
- "#{associated_model_config.abstract_model.table_name}.#{sortable}"
70
+ elsif association? # use column on target table
71
+ "#{associated_model_config.abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(sortable)}"
72
72
  else # use described column in the field conf.
73
- "#{abstract_model.table_name}.#{sortable}"
73
+ "#{abstract_model.quoted_table_name}.#{abstract_model.quote_column_name(sortable)}"
74
74
  end
75
75
  end
76
76
 
@@ -40,6 +40,14 @@ module RailsAdmin
40
40
  )
41
41
  end
42
42
 
43
+ register_instance_option :searchable do
44
+ false
45
+ end
46
+
47
+ register_instance_option :sortable do
48
+ false
49
+ end
50
+
43
51
  def resource_url(thumb = false)
44
52
  return nil unless value
45
53
 
@@ -23,6 +23,10 @@ module RailsAdmin
23
23
  (o = value) && o.send(associated_model_config.object_label_method)
24
24
  end
25
25
 
26
+ register_instance_option :allowed_methods do
27
+ nested_form ? [method_name] : [name]
28
+ end
29
+
26
30
  def selected_id
27
31
  value.try(:id).try(:to_s)
28
32
  end
@@ -38,6 +42,13 @@ module RailsAdmin
38
42
  def associated_prepopulate_params
39
43
  {associated_model_config.abstract_model.param_key => {association.foreign_key => bindings[:object].try(:id)}}
40
44
  end
45
+
46
+ def parse_input(params)
47
+ return if nested_form
48
+
49
+ id = params.delete(method_name)
50
+ params[name] = associated_model_config.abstract_model.get(id) if id
51
+ end
41
52
  end
42
53
  end
43
54
  end
@@ -48,7 +48,7 @@ module RailsAdmin
48
48
  end
49
49
 
50
50
  register_instance_option :keep_method do
51
- method_name if ::ActiveStorage.replace_on_assign_to_many
51
+ method_name if ::ActiveStorage.gem_version >= Gem::Version.new('7.1') || ::ActiveStorage.replace_on_assign_to_many
52
52
  end
53
53
 
54
54
  register_instance_option :delete_method do
@@ -70,6 +70,14 @@ module RailsAdmin
70
70
  direct? && {data: {direct_upload_url: bindings[:view].main_app.rails_direct_uploads_url}} || {},
71
71
  )
72
72
  end
73
+
74
+ register_instance_option :searchable do
75
+ false
76
+ end
77
+
78
+ register_instance_option :sortable do
79
+ false
80
+ end
73
81
  end
74
82
  end
75
83
  end
@@ -21,6 +21,7 @@ module RailsAdmin
21
21
  '%-I' => 'h', # Hour of the day, 12-hour clock (1..12)
22
22
  '%k' => 'H', # Hour of the day, 24-hour clock (0..23)
23
23
  '%l' => 'h', # Hour of the day, 12-hour clock (1..12)
24
+ '%-l' => 'h', # Hour of the day, 12-hour clock (1..12)
24
25
  '%M' => 'i', # Minute of the hour (00..59)
25
26
  '%-M' => 'i', # Minute of the hour (00..59)
26
27
  '%m' => 'm', # Month of the year (01..12)
@@ -3,9 +3,9 @@
3
3
  module RailsAdmin
4
4
  class Version
5
5
  MAJOR = 3
6
- MINOR = 1
7
- PATCH = 4
8
- PRE = nil
6
+ MINOR = 2
7
+ PATCH = 0
8
+ PRE = 'beta'
9
9
 
10
10
  class << self
11
11
  # @return [String]
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rails_admin",
3
- "version": "3.1.4",
3
+ "version": "3.2.0-beta",
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",
@@ -0,0 +1,30 @@
1
+ import jQuery from "jquery";
2
+ import "jquery-ui/ui/widget.js";
3
+
4
+ (function ($) {
5
+ "use strict";
6
+
7
+ $.widget("ra.abstractSelect", {
8
+ options: {
9
+ createQuery: function (query) {
10
+ if ($.isEmptyObject(this.scopeBy)) {
11
+ return { query: query };
12
+ } else {
13
+ const filterQuery = {};
14
+ for (var field in this.scopeBy) {
15
+ const targetField = this.scopeBy[field];
16
+ const targetValue = $(`[name$="[${field}]"]`).val();
17
+ if (!filterQuery[targetField]) {
18
+ filterQuery[targetField] = [];
19
+ }
20
+ filterQuery[targetField].push(
21
+ targetValue ? { o: "is", v: targetValue } : { o: "_blank" }
22
+ );
23
+ }
24
+ return { query: query, f: filterQuery };
25
+ }
26
+ },
27
+ scopeBy: {},
28
+ },
29
+ });
30
+ })(jQuery);
@@ -17,6 +17,7 @@ import "jquery-ui/ui/widget.js";
17
17
  import "jquery-ui/ui/widgets/menu.js";
18
18
  import "jquery-ui/ui/widgets/mouse.js";
19
19
 
20
+ import "./abstract-select";
20
21
  import "./filter-box";
21
22
  import "./filtering-multiselect";
22
23
  import "./filtering-select";
@@ -26,4 +27,6 @@ import "./sidescroll";
26
27
  import "./ui";
27
28
  import "./widgets";
28
29
 
29
- Rails.start();
30
+ if (!window._rails_loaded) {
31
+ Rails.start();
32
+ }
@@ -1,13 +1,11 @@
1
1
  import jQuery from "jquery";
2
2
  import "jquery-ui/ui/widget.js";
3
3
  import I18n from "./i18n";
4
+
4
5
  (function ($) {
5
- $.widget("ra.filteringMultiselect", {
6
+ $.widget("ra.filteringMultiselect", $.ra.abstractSelect, {
6
7
  _cache: {},
7
8
  options: {
8
- createQuery: function (query) {
9
- return { query: query };
10
- },
11
9
  sortable: false,
12
10
  removable: true,
13
11
  regional: {
@@ -6,11 +6,8 @@ import I18n from "./i18n";
6
6
  (function ($) {
7
7
  "use strict";
8
8
 
9
- $.widget("ra.filteringSelect", {
9
+ $.widget("ra.filteringSelect", $.ra.abstractSelect, {
10
10
  options: {
11
- createQuery: function (query) {
12
- return { query: query };
13
- },
14
11
  minLength: 0,
15
12
  searchDelay: 200,
16
13
  remote_source: null,
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.1.4
4
+ version: 3.2.0.beta
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-07-09 00:00:00.000000000 Z
15
+ date: 2024-07-13 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activemodel-serializers-xml
@@ -28,6 +28,20 @@ dependencies:
28
28
  - - ">="
29
29
  - !ruby/object:Gem::Version
30
30
  version: '1.0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: csv
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
31
45
  - !ruby/object:Gem::Dependency
32
46
  name: kaminari
33
47
  requirement: !ruby/object:Gem::Requirement
@@ -86,16 +100,22 @@ dependencies:
86
100
  name: turbo-rails
87
101
  requirement: !ruby/object:Gem::Requirement
88
102
  requirements:
89
- - - "~>"
103
+ - - ">="
90
104
  - !ruby/object:Gem::Version
91
105
  version: '1.0'
106
+ - - "<"
107
+ - !ruby/object:Gem::Version
108
+ version: '3'
92
109
  type: :runtime
93
110
  prerelease: false
94
111
  version_requirements: !ruby/object:Gem::Requirement
95
112
  requirements:
96
- - - "~>"
113
+ - - ">="
97
114
  - !ruby/object:Gem::Version
98
115
  version: '1.0'
116
+ - - "<"
117
+ - !ruby/object:Gem::Version
118
+ version: '3'
99
119
  - !ruby/object:Gem::Dependency
100
120
  name: bundler
101
121
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +210,7 @@ files:
190
210
  - lib/generators/rails_admin/templates/initializer.erb
191
211
  - lib/generators/rails_admin/templates/rails_admin.js
192
212
  - lib/generators/rails_admin/templates/rails_admin.scss.erb
213
+ - lib/generators/rails_admin/templates/rails_admin.vite.js
193
214
  - lib/generators/rails_admin/templates/rails_admin.webpacker.js
194
215
  - lib/generators/rails_admin/utils.rb
195
216
  - lib/rails_admin.rb
@@ -319,6 +340,7 @@ files:
319
340
  - lib/rails_admin/version.rb
320
341
  - lib/tasks/rails_admin.rake
321
342
  - package.json
343
+ - src/rails_admin/abstract-select.js
322
344
  - src/rails_admin/base.js
323
345
  - src/rails_admin/filter-box.js
324
346
  - src/rails_admin/filtering-multiselect.js
@@ -447,12 +469,13 @@ homepage: https://github.com/railsadminteam/rails_admin
447
469
  licenses:
448
470
  - MIT
449
471
  metadata: {}
450
- post_install_message: "\n ### Upgrading RailsAdmin from 2.x.x to 3.x.x ###\n\n
451
- \ Due to introduction of Webpack/Webpacker support, some additional dependencies
452
- and configuration will be needed.\n Running `bin/rails g rails_admin:install`
453
- will suggest required changes, based on the current setup of your app.\n\n For
454
- a complete list of changes, see https://github.com/railsadminteam/rails_admin/blob/master/CHANGELOG.md\n
455
- \ "
472
+ post_install_message: |
473
+ ### Upgrading RailsAdmin from 2.x.x to 3.x.x ###
474
+
475
+ Due to introduction of Webpack/Webpacker support, some additional dependencies and configuration will be needed.
476
+ Running `bin/rails g rails_admin:install` will suggest required changes, based on the current setup of your app.
477
+
478
+ For a complete list of changes, see https://github.com/railsadminteam/rails_admin/blob/master/CHANGELOG.md
456
479
  rdoc_options: []
457
480
  require_paths:
458
481
  - lib
@@ -463,9 +486,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
463
486
  version: 2.6.0
464
487
  required_rubygems_version: !ruby/object:Gem::Requirement
465
488
  requirements:
466
- - - ">="
489
+ - - ">"
467
490
  - !ruby/object:Gem::Version
468
- version: 1.8.11
491
+ version: 1.3.1
469
492
  requirements: []
470
493
  rubygems_version: 3.4.10
471
494
  signing_key: