diff --git a/lib/couchbase-orm/relation.rb b/lib/couchbase-orm/relation.rb index 4b414700..140040ff 100644 --- a/lib/couchbase-orm/relation.rb +++ b/lib/couchbase-orm/relation.rb @@ -128,6 +128,14 @@ def all CouchbaseOrm_Relation.new(**initializer_arguments) end + def scoping + scopes = (Thread.current[@model.name] ||= []) + scopes.push(self) + result = yield + scopes.pop + result + end + private def build_limit @@ -171,31 +179,25 @@ def build_update(**cond) end.join(", ") end + def method_missing(method, *args, &block) + if @model.respond_to?(method) + scoping { + @model.public_send(method, *args, &block) + } + else + super + end + end end module ClassMethods - def where(**conds) - CouchbaseOrm_Relation.new(model: self, where: conds) - end - - def not(**conds) - CouchbaseOrm_Relation.new(model: self, where: conds, _not: true) - end - - def order(*ordersl, **ordersh) - order = ordersh.reverse_merge(ordersl.map{ |o| [o, :asc] }.to_h) - CouchbaseOrm_Relation.new(model: self, order: order) - end - - def limit(limit) - CouchbaseOrm_Relation.new(model: self, limit: limit) - end - - def all - CouchbaseOrm_Relation.new(model: self) + def relation + Thread.current[self.name]&.last || CouchbaseOrm_Relation.new(model: self) end delegate :ids, :delete_all, :count, :empty?, :filter, :reduce, :find_by, to: :all + + delegate :where, :not, :order, :limit, :all, to: :relation end end end diff --git a/spec/relation_spec.rb b/spec/relation_spec.rb index 55a6b5c9..cb41bf53 100644 --- a/spec/relation_spec.rb +++ b/spec/relation_spec.rb @@ -8,6 +8,14 @@ class RelationModel < CouchbaseOrm::Base attribute :last_name, :string attribute :active, :boolean attribute :age, :integer + + def self.adult + where(age: {_gte: 18}) + end + + def self.active + where(active: true) + end end describe CouchbaseOrm::Relation do @@ -215,7 +223,6 @@ class RelationModel < CouchbaseOrm::Base expect(RelationModel.order(:age).pluck(:age, :active)).to match_array([[10, true], [20, true], [30, false]]) end - it "should query true boolean" do m1 = RelationModel.create!(active: true) _m2 = RelationModel.create!(active: false) @@ -300,5 +307,28 @@ class RelationModel < CouchbaseOrm::Base expect(m3.reload.age).to eq(50) expect(m4.reload.age).to eq(40) end + + describe "scopes" do + it "should chain scopes" do + _m1 = RelationModel.create!(age: 10, active: true) + _m2 = RelationModel.create!(age: 20, active: false) + m3 = RelationModel.create!(age: 30, active: true) + m4 = RelationModel.create!(age: 40, active: true) + + expect(RelationModel.all.adult.all.active.all).to match_array([m3, m4]) + expect(RelationModel.where(active: true).adult).to match_array([m3, m4]) + end + + it "should be scoped only in current thread" do + m1 = RelationModel.create!(active: true) + m2 = RelationModel.create!(active: false) + RelationModel.active.scoping do + expect(RelationModel.all).to match_array([m1]) + Thread.start do + expect(RelationModel.all).to match_array([m1, m2]) + end.join + end + end + end end