Skip to content

Commit e28fadb

Browse files
mshibuyaclaude
andcommitted
Fix enum fields losing class-level enumerations in the filters dropdown
enum_method asked bindings[:object].class whether it responds to "#{name}_enum". With no object bound that reads NilClass.respond_to?, which is always false, so a model defining the enumeration as a class method fell back to the attribute name. #enum then read the attribute off a throwaway record and returned nil, and filter_operators raised NoMethodError on nil. The filters dropdown renders each field with a view but no object (field.with(view: self) in index.html.erb), so every enum field on such a model crashed the index page. Fall back to the model itself when nothing is bound. Existing specs missed this because they all bind an object before asking. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 08b9a91 commit e28fadb

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

lib/rails_admin/config/fields/types/enum.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,16 @@ class Enum < RailsAdmin::Config::Fields::Base
2121
end
2222

2323
register_instance_option :enum_method do
24-
@enum_method ||= bindings[:object].class.respond_to?("#{name}_enum") || (bindings[:object] || abstract_model.dummy_record).respond_to?("#{name}_enum") ? "#{name}_enum" : name
24+
# Fall back to the model when no object is bound, which is how the
25+
# filters dropdown renders fields. Asking nil for its class used to
26+
# look the method up on NilClass, hiding class-level enumerations.
27+
@enum_method ||=
28+
if (bindings[:object]&.class || abstract_model.model).respond_to?("#{name}_enum") ||
29+
(bindings[:object] || abstract_model.dummy_record).respond_to?("#{name}_enum")
30+
"#{name}_enum"
31+
else
32+
name
33+
end
2534
end
2635

2736
register_instance_option :enum do

spec/rails_admin/config/fields/types/enum_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,37 @@ def color_enum
4545
end
4646
end
4747

48+
describe "when only the class responds to '\#{method}_enum'" do
49+
before do
50+
Team.singleton_class.class_eval do
51+
def manager_enum
52+
%w[Alice Bob]
53+
end
54+
end
55+
RailsAdmin.config Team do
56+
list do
57+
field :manager, :enum
58+
end
59+
end
60+
end
61+
62+
after do
63+
Team.singleton_class.send(:remove_method, :manager_enum)
64+
end
65+
66+
let(:field) { RailsAdmin.config(Team).list.fields.detect { |f| f.name == :manager } }
67+
68+
# The filters dropdown renders fields bound to a view but to no object,
69+
# so the enumeration has to resolve without one.
70+
it 'resolves the enumeration without a bound object' do
71+
expect(field.with(view: nil).enum).to eq %w[Alice Bob]
72+
end
73+
74+
it 'builds filter options without a bound object' do
75+
expect { field.with(view: nil).filter_options }.not_to raise_error
76+
end
77+
end
78+
4879
describe 'the enum instance method' do
4980
before do
5081
Team.class_eval do

0 commit comments

Comments
 (0)