From 04400e2dd7364e54156f714807889ab6de5b04ff Mon Sep 17 00:00:00 2001 From: Raymond Wright Date: Wed, 19 Mar 2025 10:51:54 +0000 Subject: [PATCH] Add belongs_to optional/required support to required? As of Active Record 7.1.0.beta1, the presence validation added by a belongs_to association can now have an associated lambda. This lambda is just to check whether the column has changed to save redundant validations, so we can ignore it. --- lib/rails_admin/adapters/active_record.rb | 4 ++++ lib/rails_admin/adapters/mongoid.rb | 4 ++++ lib/rails_admin/config/fields/base.rb | 9 +++++++- spec/rails_admin/config/fields/base_spec.rb | 24 +++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/rails_admin/adapters/active_record.rb b/lib/rails_admin/adapters/active_record.rb index e179280e7..889fb39e3 100644 --- a/lib/rails_admin/adapters/active_record.rb +++ b/lib/rails_admin/adapters/active_record.rb @@ -135,6 +135,10 @@ def parse_id(id) end end + def belongs_to_required_by_default + model.belongs_to_required_by_default + end + private def primary_key_scope(scope, id) diff --git a/lib/rails_admin/adapters/mongoid.rb b/lib/rails_admin/adapters/mongoid.rb index 52a3870af..eb5904e96 100644 --- a/lib/rails_admin/adapters/mongoid.rb +++ b/lib/rails_admin/adapters/mongoid.rb @@ -112,6 +112,10 @@ def adapter_supports_joins? false end + def belongs_to_required_by_default + ::Mongoid.belongs_to_required_by_default + end + private def build_statement(column, type, value, operator) diff --git a/lib/rails_admin/config/fields/base.rb b/lib/rails_admin/config/fields/base.rb index 184bc499d..0835efd01 100644 --- a/lib/rails_admin/config/fields/base.rb +++ b/lib/rails_admin/config/fields/base.rb @@ -216,11 +216,18 @@ def filter_options end (@required ||= {})[context] ||= !!([name] + children_fields).uniq.detect do |column_name| - abstract_model.model.validators_on(column_name).detect do |v| + model = abstract_model.model + model.validators_on(column_name).detect do |v| !(v.options[:allow_nil] || v.options[:allow_blank]) && %i[presence numericality attachment_presence].include?(v.kind) && (v.options[:on] == context || v.options[:on].blank?) && (v.options[:if].blank? && v.options[:unless].blank?) + end || model.reflect_on_all_associations(:belongs_to).detect do |a| + next unless a.name == column_name + + required = a.options[:required] if a.options.key?(:required) + required = !a.options[:optional] if a.options.key?(:optional) && required.nil? + required.nil? ? abstract_model.belongs_to_required_by_default : required end end end diff --git a/spec/rails_admin/config/fields/base_spec.rb b/spec/rails_admin/config/fields/base_spec.rb index 195b17d03..1dfb1dc36 100644 --- a/spec/rails_admin/config/fields/base_spec.rb +++ b/spec/rails_admin/config/fields/base_spec.rb @@ -86,9 +86,15 @@ class RelTest < Tableless column :league_id, :integer column :division_id, :integer, nil, false column :player_id, :integer + column :team_id, :integer + column :draft_id, :integer + column :image_id, :integer belongs_to :league, optional: true belongs_to :division, optional: true belongs_to :player, optional: true + belongs_to :team, optional: false + belongs_to :draft, required: true + belongs_to :image, required: false validates_numericality_of(:player_id, only_integer: true) end @fields = RailsAdmin.config(RelTest).create.fields @@ -111,6 +117,24 @@ class RelTest < Tableless expect(@fields.detect { |f| f.name == :player }.required?).to be_truthy end end + + describe 'for belongs_to association with optional: false' do + it 'is required' do + expect(@fields.detect { |f| f.name == :team }.required?).to be_truthy + end + end + + describe 'for belongs_to association with required: true' do + it 'is required' do + expect(@fields.detect { |f| f.name == :draft }.required?).to be_truthy + end + end + + describe 'for belongs_to association with required: false' do + it 'is optional' do + expect(@fields.detect { |f| f.name == :image }.required?).to be_falsey + end + end end end