From 7aebcb67b040bca353cd2e97a468c8ffe4594665 Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Mon, 30 Dec 2013 16:56:13 +0100 Subject: Fix the enums writer methods Previously, the writer methods would simply check whether the passed argument was the symbol representing the integer value of an enum field. Therefore, it was not possible to specify the numeric value itself but the dynamically defined scopes generate where clauses relying on this kind of values so a chained call to a method like `find_or_initialize_by` would trigger an `ArgumentError`. Reference #13530 --- activerecord/lib/active_record/enum.rb | 2 +- activerecord/test/cases/enum_test.rb | 11 ++++++++++- activerecord/test/schema/schema.rb | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 1d484f7c15..aebb061717 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -67,7 +67,7 @@ module ActiveRecord _enum_methods_module.module_eval do # def status=(value) self[:status] = STATUS[value] end define_method("#{name}=") { |value| - unless enum_values.has_key?(value) || value.blank? + unless enum_values.has_key?(value) || enum_values.has_value?(value) || value.blank? raise ArgumentError, "'#{value}' is not a valid #{name}" end self[name] = enum_values[value] diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb index 017edcb194..47e3dfc3ad 100644 --- a/activerecord/test/cases/enum_test.rb +++ b/activerecord/test/cases/enum_test.rb @@ -16,7 +16,7 @@ class EnumTest < ActiveRecord::TestCase assert @book.unread? end - test "query state with symbol" do + test "query state with strings" do assert_equal "proposed", @book.status assert_equal "unread", @book.read_status end @@ -78,4 +78,13 @@ class EnumTest < ActiveRecord::TestCase assert_equal 1, Book::STATUS["written"] assert_equal 2, Book::STATUS[:published] end + + test "first_or_initialize with enums' scopes" do + class Issue < ActiveRecord::Base + enum status: [:open, :closed] + end + + assert Issue.open.empty? + assert Issue.open.first_or_initialize + end end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index ac546fc296..9f504801af 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -327,6 +327,10 @@ ActiveRecord::Schema.define do t.string :color end + create_table :issues, force: true do |t| + t.integer :status + end + create_table :items, force: true do |t| t.column :name, :string end -- cgit v1.2.3 From 50060e969b422e6cd8f90181ac3d92f915a96f69 Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Mon, 30 Dec 2013 17:47:11 +0100 Subject: Improve enum documentation Add a mention about the automatic generation of scopes based on the allowed values of the field on the enum documentation. --- activerecord/lib/active_record/enum.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index aebb061717..c042a2f232 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -1,5 +1,6 @@ module ActiveRecord - # Declare an enum attribute where the values map to integers in the database, but can be queried by name. Example: + # Declare an enum attribute where the values map to integers in the database, + # but can be queried by name. Example: # # class Conversation < ActiveRecord::Base # enum status: [ :active, :archived ] @@ -23,6 +24,10 @@ module ActiveRecord # conversation.status.nil? # => true # conversation.status # => nil # + # Scopes based on the allowed values of the enum field will be provided + # as well. With the above example, it will create an +active+ and +archived+ + # scope. + # # You can set the default value from the database declaration, like: # # create_table :conversations do |t| -- cgit v1.2.3