Skip to content

Commit 2fe1ca0

Browse files
authored
Merge pull request rails#53408 from kamipo/fix_enum_labels_as_kwargs
Fix enum labels to accepts as keyword arguments
2 parents 5cad1ef + 439298e commit 2fe1ca0

File tree

2 files changed

+68
-52
lines changed

2 files changed

+68
-52
lines changed

activerecord/lib/active_record/enum.rb

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -213,74 +213,79 @@ def assert_valid_value(value)
213213
attr_reader :name, :mapping
214214
end
215215

216-
def enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
217-
assert_valid_enum_definition_values(values)
218-
assert_valid_enum_options(options)
216+
def enum(name, values = nil, **options)
217+
values, options = options, {} unless values
218+
_enum(name, values, **options)
219+
end
219220

220-
# statuses = { }
221-
enum_values = ActiveSupport::HashWithIndifferentAccess.new
222-
name = name.to_s
221+
private
222+
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
223+
assert_valid_enum_definition_values(values)
224+
assert_valid_enum_options(options)
223225

224-
# def self.statuses() statuses end
225-
detect_enum_conflict!(name, name.pluralize, true)
226-
singleton_class.define_method(name.pluralize) { enum_values }
227-
defined_enums[name] = enum_values
226+
# statuses = { }
227+
enum_values = ActiveSupport::HashWithIndifferentAccess.new
228+
name = name.to_s
228229

229-
detect_enum_conflict!(name, name)
230-
detect_enum_conflict!(name, "#{name}=")
230+
# def self.statuses() statuses end
231+
detect_enum_conflict!(name, name.pluralize, true)
232+
singleton_class.define_method(name.pluralize) { enum_values }
233+
defined_enums[name] = enum_values
231234

232-
attribute(name, **options)
235+
detect_enum_conflict!(name, name)
236+
detect_enum_conflict!(name, "#{name}=")
233237

234-
decorate_attributes([name]) do |_name, subtype|
235-
if subtype == ActiveModel::Type.default_value
236-
raise "Undeclared attribute type for enum '#{name}' in #{self.name}. Enums must be" \
237-
" backed by a database column or declared with an explicit type" \
238-
" via `attribute`."
239-
end
238+
attribute(name, **options)
240239

241-
subtype = subtype.subtype if EnumType === subtype
242-
EnumType.new(name, enum_values, subtype, raise_on_invalid_values: !validate)
243-
end
240+
decorate_attributes([name]) do |_name, subtype|
241+
if subtype == ActiveModel::Type.default_value
242+
raise "Undeclared attribute type for enum '#{name}' in #{self.name}. Enums must be" \
243+
" backed by a database column or declared with an explicit type" \
244+
" via `attribute`."
245+
end
244246

245-
value_method_names = []
246-
_enum_methods_module.module_eval do
247-
prefix = if prefix
248-
prefix == true ? "#{name}_" : "#{prefix}_"
247+
subtype = subtype.subtype if EnumType === subtype
248+
EnumType.new(name, enum_values, subtype, raise_on_invalid_values: !validate)
249249
end
250250

251-
suffix = if suffix
252-
suffix == true ? "_#{name}" : "_#{suffix}"
253-
end
251+
value_method_names = []
252+
_enum_methods_module.module_eval do
253+
prefix = if prefix
254+
prefix == true ? "#{name}_" : "#{prefix}_"
255+
end
256+
257+
suffix = if suffix
258+
suffix == true ? "_#{name}" : "_#{suffix}"
259+
end
254260

255-
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
256-
pairs.each do |label, value|
257-
enum_values[label] = value
258-
label = label.to_s
261+
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
262+
pairs.each do |label, value|
263+
enum_values[label] = value
264+
label = label.to_s
259265

260-
value_method_name = "#{prefix}#{label}#{suffix}"
261-
value_method_names << value_method_name
262-
define_enum_methods(name, value_method_name, value, scopes, instance_methods)
266+
value_method_name = "#{prefix}#{label}#{suffix}"
267+
value_method_names << value_method_name
268+
define_enum_methods(name, value_method_name, value, scopes, instance_methods)
263269

264-
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
265-
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
270+
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
271+
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
266272

267-
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
268-
value_method_names << value_method_alias
269-
define_enum_methods(name, value_method_alias, value, scopes, instance_methods)
273+
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
274+
value_method_names << value_method_alias
275+
define_enum_methods(name, value_method_alias, value, scopes, instance_methods)
276+
end
270277
end
271278
end
272-
end
273-
detect_negative_enum_conditions!(value_method_names) if scopes
279+
detect_negative_enum_conditions!(value_method_names) if scopes
274280

275-
if validate
276-
validate = {} unless Hash === validate
277-
validates_inclusion_of name, in: enum_values.keys, **validate
278-
end
281+
if validate
282+
validate = {} unless Hash === validate
283+
validates_inclusion_of name, in: enum_values.keys, **validate
284+
end
279285

280-
enum_values.freeze
281-
end
286+
enum_values.freeze
287+
end
282288

283-
private
284289
def inherited(base)
285290
base.defined_enums = defined_enums.deep_dup
286291
super

activerecord/test/cases/enum_test.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ def self.name; "Book"; end
446446
end
447447
end
448448

449-
assert_match(/wrong number of arguments/, e.message)
449+
assert_match(/must not be empty\.$/, e.message)
450450

451451
e = assert_raises(ArgumentError) do
452452
Class.new(ActiveRecord::Base) do
@@ -892,10 +892,21 @@ def self.name; "Book"; end
892892
assert_respond_to book, :easy_to_read?
893893
end
894894

895+
test "enum labels as keyword arguments" do
896+
klass = Class.new(ActiveRecord::Base) do
897+
self.table_name = "books"
898+
enum :status, active: 0, archived: 1
899+
end
900+
901+
book = klass.new
902+
assert_predicate book, :active?
903+
assert_not_predicate book, :archived?
904+
end
905+
895906
test "option names can be used as label" do
896907
klass = Class.new(ActiveRecord::Base) do
897908
self.table_name = "books"
898-
enum :status, { default: 0, scopes: 1, prefix: 2, suffix: 3 }
909+
enum :status, default: 0, scopes: 1, prefix: 2, suffix: 3
899910
end
900911

901912
book = klass.new

0 commit comments

Comments
 (0)