diff --git a/lib/lotus/model/adapters/memory/query.rb b/lib/lotus/model/adapters/memory/query.rb index 24994c1e..196944c7 100644 --- a/lib/lotus/model/adapters/memory/query.rb +++ b/lib/lotus/model/adapters/memory/query.rb @@ -22,6 +22,14 @@ def where(condition) alias_method :and, :where alias_method :or, :where + def exclude(condition) + column, value = *Array(condition).flatten + conditions.push(Proc.new{ reject! {|r| r.fetch(column) == value} }) + self + end + + alias_method :not, :exclude + def order(column) conditions.push(Proc.new{ sort_by{|r| r.fetch(column)} }) self @@ -90,14 +98,11 @@ def range(column) private def run - # TODO cleanup - result = if conditions.any? - conditions.map do |condition| - @collection.all.instance_exec(&condition) - end - else - @collection.all - end + result = @collection.all.dup + + result = conditions.map do |condition| + result.instance_exec(&condition) + end if conditions.any? modifiers.map do |modifier| result.instance_exec(&modifier) diff --git a/lib/lotus/model/adapters/sql/query.rb b/lib/lotus/model/adapters/sql/query.rb index fdf81f97..f2076dad 100644 --- a/lib/lotus/model/adapters/sql/query.rb +++ b/lib/lotus/model/adapters/sql/query.rb @@ -25,6 +25,13 @@ def where(condition) alias_method :and, :where + def exclude(condition) + conditions.push([:exclude, condition]) + self + end + + alias_method :not, :exclude + def limit(number) conditions.push([:limit, number]) self diff --git a/test/model/adapters/memory_adapter_test.rb b/test/model/adapters/memory_adapter_test.rb index 5211b885..37819ca7 100644 --- a/test/model/adapters/memory_adapter_test.rb +++ b/test/model/adapters/memory_adapter_test.rb @@ -303,6 +303,64 @@ end end + describe 'exclude' do + describe 'with an empty collection' do + it 'returns an empty result set' do + result = @adapter.query(collection) do + exclude(id: 23) + end.all + + result.must_be_empty + end + end + + describe 'with a filled collection' do + before do + @adapter.create(collection, user1) + @adapter.create(collection, user2) + @adapter.create(collection, user3) + end + + let(:user3) { TestUser.new(name: 'S', age: 2) } + + it 'returns selected records' do + id = user1.id + + query = Proc.new { + exclude(id: id) + } + + result = @adapter.query(collection, &query).all + result.must_equal [user2, user3] + end + + it 'can use multiple exclude conditions' do + id = user1.id + name = user2.name + + query = Proc.new { + exclude(id: id).exclude(name: name) + } + + $debug = true + result = @adapter.query(collection, &query).all + result.must_equal [user3] + end + + it 'can use multiple exclude conditions with "not" alias' do + id = user1.id + name = user2.name + + query = Proc.new { + self.not(id: id).not(name: name) + } + + result = @adapter.query(collection, &query).all + result.must_equal [user3] + end + end + end + describe 'or' do describe 'with an empty collection' do it 'returns an empty result set' do diff --git a/test/model/adapters/sql_adapter_test.rb b/test/model/adapters/sql_adapter_test.rb index fcb8b7a1..5f51792c 100644 --- a/test/model/adapters/sql_adapter_test.rb +++ b/test/model/adapters/sql_adapter_test.rb @@ -294,6 +294,63 @@ end end + describe 'exclude' do + describe 'with an empty collection' do + it 'returns an empty result set' do + result = @adapter.query(collection) do + exclude(id: 23) + end.all + + result.must_be_empty + end + end + + describe 'with a filled collection' do + before do + @adapter.create(collection, user1) + @adapter.create(collection, user2) + @adapter.create(collection, user3) + end + + let(:user3) { TestUser.new(name: 'S', age: 2) } + + it 'returns selected records' do + id = user1.id + + query = Proc.new { + exclude(id: id) + } + + result = @adapter.query(collection, &query).all + result.must_equal [user2, user3] + end + + it 'can use multiple exclude conditions' do + id = user1.id + name = user2.name + + query = Proc.new { + exclude(id: id).exclude(name: name) + } + + result = @adapter.query(collection, &query).all + result.must_equal [user3] + end + + it 'can use multiple exclude conditions with "not" alias' do + id = user1.id + name = user2.name + + query = Proc.new { + self.not(id: id).not(name: name) + } + + result = @adapter.query(collection, &query).all + result.must_equal [user3] + end + end + end + describe 'or' do describe 'with an empty collection' do it 'returns an empty result set' do