diff --git a/lib/rasti/db/collection.rb b/lib/rasti/db/collection.rb index 36f5028..fbf61a0 100644 --- a/lib/rasti/db/collection.rb +++ b/lib/rasti/db/collection.rb @@ -28,6 +28,10 @@ def relations @relations ||= {} end + def queries + @queries ||= {} + end + def implicit_collection_name underscore(demodulize(name)).to_sym end @@ -62,6 +66,14 @@ def many_to_many(name, options={}) relations[name] = Relations::ManyToMany.new name, self, options end + def query(name, &block) + queries[name] = block + + define_method name do |*args| + Query.new(self.class, dataset, schema).instance_exec *args, &block + end + end + end def initialize(db, schema=nil) diff --git a/lib/rasti/db/query.rb b/lib/rasti/db/query.rb index b213921..cf369b0 100644 --- a/lib/rasti/db/query.rb +++ b/lib/rasti/db/query.rb @@ -55,6 +55,18 @@ def to_s private + def method_missing(method, *args, &block) + if collection_class.queries.key?(method) + instance_exec *args, &collection_class.queries[method] + else + super + end + end + + def respond_to_missing?(method, include_private=false) + collection_class.queries.key?(method) || super + end + attr_reader :collection_class, :dataset, :schema end diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb index 6c511aa..6eef560 100644 --- a/spec/collection_spec.rb +++ b/spec/collection_spec.rb @@ -188,6 +188,29 @@ models.must_equal [2,1].map { |i| User.new(id: i, name: "User #{i}") } end + describe 'Named queries' do + + before do + 1.upto(2) { |i| db[:users].insert name: "User #{i}" } + 1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' } + 4.upto(5) { |i| db[:posts].insert user_id: 2, title: "Post #{i}", body: '...' } + end + + it 'Global' do + posts.created_by(1).map(&:id).must_equal [1,2,3] + posts.created_by(2).map(&:id).must_equal [4,5] + end + + it 'Chained' do + posts.created_by(1).entitled('Post 1').map(&:id).must_equal [1] + end + + it 'Chained into query' do + posts.query { created_by(2).entitled('Post 4').map(&:id) }.must_equal [4] + end + + end + it 'Graph' do 1.upto(3) do |i| db[:users].insert name: "User #{i}" diff --git a/spec/minitest_helper.rb b/spec/minitest_helper.rb index d7e1ba7..7cb5fc3 100644 --- a/spec/minitest_helper.rb +++ b/spec/minitest_helper.rb @@ -20,6 +20,9 @@ class Posts < Rasti::DB::Collection many_to_one :user many_to_many :categories one_to_many :comments + + query(:created_by) { |user_id| where user_id: user_id } + query(:entitled) { |title| where title: title } end class Comments < Rasti::DB::Collection diff --git a/spec/query_spec.rb b/spec/query_spec.rb index 5df69b4..22c784c 100644 --- a/spec/query_spec.rb +++ b/spec/query_spec.rb @@ -80,4 +80,18 @@ users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#' end + describe 'Named queries' do + + it 'Respond to' do + posts_query.must_respond_to :created_by + posts_query.wont_respond_to :by_user + end + + it 'Safe method missing' do + posts_query.created_by(1).first.must_equal Post.new(db[:posts][user_id: 1]) + proc { posts_query.by_user(1) }.must_raise NoMethodError + end + + end + end \ No newline at end of file