diff --git a/CHANGELOG.md b/CHANGELOG.md index dec497ea..f8864a06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### enhancements * Add support for Rails 7.0.0.alpha. (by [@f-mer](https://github.com/f-mer)) +* Add support for negative shallow scopes. (by [@nashby](https://github.com/nashby)) ## 2.4.0 (December 12, 2020) diff --git a/lib/enumerize/scope/activerecord.rb b/lib/enumerize/scope/activerecord.rb index 8bf16720..bd090d26 100644 --- a/lib/enumerize/scope/activerecord.rb +++ b/lib/enumerize/scope/activerecord.rb @@ -42,6 +42,10 @@ def _define_activerecord_shallow_scopes!(attribute_name) define_singleton_method(value_obj) do where(attribute_name => value_obj.value) end + + define_singleton_method("not_#{value_obj}") do + where.not(attribute_name => value_obj.value) + end end end end diff --git a/lib/enumerize/scope/mongoid.rb b/lib/enumerize/scope/mongoid.rb index da1c6e6c..81d2f654 100644 --- a/lib/enumerize/scope/mongoid.rb +++ b/lib/enumerize/scope/mongoid.rb @@ -39,6 +39,10 @@ def _define_mongoid_shallow_scopes!(attribute_name) define_singleton_method(value_obj) do self.in(attribute_name => value_obj.value) end + + define_singleton_method("not_#{value_obj}") do + self.not_in(attribute_name => value_obj.value) + end end end end diff --git a/lib/enumerize/scope/sequel.rb b/lib/enumerize/scope/sequel.rb index f64b8ad4..59616dc4 100644 --- a/lib/enumerize/scope/sequel.rb +++ b/lib/enumerize/scope/sequel.rb @@ -45,6 +45,10 @@ def _define_sequel_shallow_scopes!(attribute_name) def_dataset_method(value_obj) do where(attribute_name => value_obj.value.to_s) end + + def_dataset_method("not_#{value_obj}") do + exclude(attribute_name => value_obj.value.to_s) + end end end end diff --git a/test/activerecord_test.rb b/test/activerecord_test.rb index 462969be..e3ba6ebb 100644 --- a/test/activerecord_test.rb +++ b/test/activerecord_test.rb @@ -375,8 +375,8 @@ def self.name it 'adds scope' do User.delete_all - user_1 = User.create!(status: :active, role: :admin) - user_2 = User.create!(status: :blocked) + user_1 = User.create!(sex: :female, skill: :noob, status: :active, role: :admin) + user_2 = User.create!(sex: :female, skill: :casual, status: :blocked) user_3 = User.create!(sex: :male, skill: :pro) expect(User.with_status(:active)).must_equal [user_1] @@ -388,6 +388,9 @@ def self.name expect(User.male).must_equal [user_3] expect(User.pro).must_equal [user_3] + + expect(User.not_male.to_set).must_equal [user_1, user_2].to_set + expect(User.not_pro.to_set).must_equal [user_1, user_2].to_set end it 'ignores not enumerized values that passed to the scope method' do diff --git a/test/mongoid_test.rb b/test/mongoid_test.rb index 8bcb56f6..dd21b2dc 100644 --- a/test/mongoid_test.rb +++ b/test/mongoid_test.rb @@ -119,8 +119,8 @@ class MongoidUser it 'adds scope' do model.delete_all - user_1 = model.create!(sex: :male, role: :admin) - user_2 = model.create!(sex: :female, role: :user) + user_1 = model.create!(sex: :male, skill: :noob, role: :admin, account_type: :basic) + user_2 = model.create!(sex: :female, skill: :noob, role: :user, account_type: :basic) user_3 = model.create!(skill: :pro, account_type: :premium) expect(model.with_sex(:male).to_a).must_equal [user_1] @@ -136,6 +136,9 @@ class MongoidUser expect(model.pro.to_a).must_equal [user_3] expect(model.premium.to_a).must_equal [user_3] + + expect(model.not_pro.to_set).must_equal [user_1, user_2].to_set + expect(model.not_premium.to_set).must_equal [user_1, user_2].to_set end it 'chains scopes' do diff --git a/test/sequel_test.rb b/test/sequel_test.rb index b857b547..140ad588 100644 --- a/test/sequel_test.rb +++ b/test/sequel_test.rb @@ -257,8 +257,8 @@ class SkipValidationsLambdaWithParamUser < Sequel::Model(:users) it 'adds scope' do User.filter{ true }.delete - user_1 = User.create(status: :active, role: :admin) - user_2 = User.create(status: :blocked) + user_1 = User.create(sex: :female, skill: :noob, status: :active, role: :admin) + user_2 = User.create(sex: :female, skill: :casual, status: :blocked) user_3 = User.create(sex: :male, skill: :pro) expect(User.with_status(:active).to_a).must_equal [user_1] @@ -271,6 +271,9 @@ class SkipValidationsLambdaWithParamUser < Sequel::Model(:users) expect(User.having_role(:admin).to_a).must_equal [user_1] expect(User.male.to_a).must_equal [user_3] expect(User.pro.to_a).must_equal [user_3] + + expect(User.not_male.to_set).must_equal [user_1, user_2].to_set + expect(User.not_pro.to_set).must_equal [user_1, user_2].to_set end it 'allows either key or value as valid' do