aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2019-02-26 12:47:27 -0800
committerGitHub <noreply@github.com>2019-02-26 12:47:27 -0800
commit55a7051a5a2935c0ced79afc5c81ef7db9e0dd73 (patch)
treec2deb2905a5887641b953474125ecf74395c4c7b /activerecord
parent3ee0dabb8443c636bf3b51ef051b4b94ee2af460 (diff)
downloadrails-55a7051a5a2935c0ced79afc5c81ef7db9e0dd73.tar.gz
rails-55a7051a5a2935c0ced79afc5c81ef7db9e0dd73.tar.bz2
rails-55a7051a5a2935c0ced79afc5c81ef7db9e0dd73.zip
Add negative scopes for all enum values (#35381)
Add negative scopes for all enum values
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md14
-rw-r--r--activerecord/lib/active_record/enum.rb6
-rw-r--r--activerecord/test/cases/enum_test.rb5
3 files changed, 25 insertions, 0 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 4323c57b9e..ce1f1102d5 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,17 @@
+* Add negative scopes for all enum values.
+
+ Example:
+
+ class Post < ActiveRecord::Base
+ enum status: %i[ drafted active trashed ]
+ end
+
+ Post.not_drafted # => where.not(status: :drafted)
+ Post.not_active # => where.not(status: :active)
+ Post.not_trashed # => where.not(status: :trashed)
+
+ *DHH*
+
* Fix different `count` calculation when using `size` with manual `select` with DISTINCT.
Fixes #35214.
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index e6dba66a08..8077630aeb 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -31,7 +31,9 @@ module ActiveRecord
# as well. With the above example:
#
# Conversation.active
+ # Conversation.not_active
# Conversation.archived
+ # Conversation.not_archived
#
# Of course, you can also query them directly if the scopes don't fit your
# needs:
@@ -196,9 +198,13 @@ module ActiveRecord
define_method("#{value_method_name}!") { update!(attr => value) }
# scope :active, -> { where(status: 0) }
+ # scope :not_active, -> { where.not(status: 0) }
if enum_scopes != false
klass.send(:detect_enum_conflict!, name, value_method_name, true)
klass.scope value_method_name, -> { where(attr => value) }
+
+ klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
+ klass.scope "not_#{value_method_name}", -> { where.not(attr => value) }
end
end
end
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index 8a0f6f6df1..1423efcf95 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -43,6 +43,11 @@ class EnumTest < ActiveRecord::TestCase
assert_equal books(:ddd), Book.forgotten.first
assert_equal books(:rfr), authors(:david).unpublished_books.first
end
+
+ test "find via negative scope" do
+ assert Book.not_published.exclude?(@book)
+ assert Book.not_proposed.include?(@book)
+ end
test "find via where with values" do
published, written = Book.statuses[:published], Book.statuses[:written]