From 638795af62e27aca6090d560b168f51e249f5779 Mon Sep 17 00:00:00 2001 From: Gabriel Naiman Date: Thu, 22 Sep 2016 23:04:28 -0300 Subject: [PATCH] Improve schema support and added tests --- lib/rasti/db/collection.rb | 2 +- lib/rasti/db/query.rb | 9 ++--- lib/rasti/db/relations.rb | 28 ++++++++------- spec/collection_spec.rb | 74 ++++++++++++++++++++++++++++++++++++++ spec/minitest_helper.rb | 6 ++-- 5 files changed, 99 insertions(+), 20 deletions(-) diff --git a/lib/rasti/db/collection.rb b/lib/rasti/db/collection.rb index f9dd6b3..a2da857 100644 --- a/lib/rasti/db/collection.rb +++ b/lib/rasti/db/collection.rb @@ -92,7 +92,7 @@ def first end def query(&block) - query = Query.new self.class, dataset + query = Query.new self.class, dataset, schema result = block.arity == 0 ? query.instance_eval(&block) : block.call(query, dataset) result.respond_to?(:all) ? result.all : result end diff --git a/lib/rasti/db/query.rb b/lib/rasti/db/query.rb index aa0bfd0..b213921 100644 --- a/lib/rasti/db/query.rb +++ b/lib/rasti/db/query.rb @@ -6,14 +6,15 @@ class Query include Enumerable - def initialize(collection_class, dataset) + def initialize(collection_class, dataset, schema=nil) @collection_class = collection_class @dataset = dataset + @schema = schema end CHAINED_METHODS.each do |method| define_method method do |*args, &block| - Query.new collection_class, dataset.send(method, *args, &block) + Query.new collection_class, dataset.send(method, *args, &block), schema end end @@ -42,7 +43,7 @@ def last def graph(*relations) rows = dataset.all - Relations.graph_to rows, relations, collection_class, dataset.db + Relations.graph_to rows, relations, collection_class, dataset.db, schema rows.map { |row| collection_class.model.new row } end @@ -54,7 +55,7 @@ def to_s private - attr_reader :collection_class, :dataset + attr_reader :collection_class, :dataset, :schema end end diff --git a/lib/rasti/db/relations.rb b/lib/rasti/db/relations.rb index 6334fe0..7c722a4 100644 --- a/lib/rasti/db/relations.rb +++ b/lib/rasti/db/relations.rb @@ -4,9 +4,11 @@ module Relations class << self - def graph_to(rows, relations, collection_class, db) + def graph_to(rows, relations, collection_class, db, schema=nil) + return if rows.empty? + parse(relations).each do |relation, nested_relations| - collection_class.relations[relation].graph_to rows, db, nested_relations + collection_class.relations[relation].graph_to rows, db, schema, nested_relations end end @@ -53,10 +55,10 @@ def foreign_key @foreign_key ||= @options[:foreign_key] || source_collection_class.implicit_foreign_key_name end - def graph_to(rows, db, relations=[]) + def graph_to(rows, db, schema=nil, relations=[]) pks = rows.map { |row| row[source_collection_class.primary_key] }.uniq - target_collection = target_collection_class.new db + target_collection = target_collection_class.new db, schema relation_rows = target_collection.query do |q| q = q.where foreign_key => pks @@ -78,10 +80,10 @@ def foreign_key @foreign_key ||= @options[:foreign_key] || target_collection_class.implicit_foreign_key_name end - def graph_to(rows, db, relations=[]) + def graph_to(rows, db, schema=nil, relations=[]) fks = rows.map { |row| row[foreign_key] }.uniq - target_collection = target_collection_class.new db + target_collection = target_collection_class.new db, schema relation_rows = target_collection.query do |q| q = q.where source_collection_class.primary_key => fks @@ -111,18 +113,20 @@ def relation_collection_name @relation_collection_name ||= @options[:relation_collection_name] || [source_collection_class.collection_name, target_collection_class.collection_name].sort.join('_').to_sym end - def graph_to(rows, db, relations=[]) + def graph_to(rows, db, schema=nil, relations=[]) pks = rows.map { |row| row[source_collection_class.primary_key] } - target_collection = target_collection_class.new db + target_collection = target_collection_class.new db, schema + + target_name = schema.nil? ? target_collection_class.collection_name : Sequel.qualify(schema, target_collection_class.collection_name) + relation_name = schema.nil? ? relation_collection_name : Sequel.qualify(schema, relation_collection_name) join_rows = target_collection.query do |q, ds| - ds.join(relation_collection_name, target_foreign_key => target_collection_class.primary_key) - .where("#{relation_collection_name}__#{source_foreign_key}".to_sym => pks) - .select(Sequel.lit("#{db.quote_identifier(target_collection_class.collection_name)}.*"), source_foreign_key) + ds.join(relation_name, target_foreign_key => target_collection_class.primary_key) + .where(Sequel.qualify(relation_name, source_foreign_key) => pks) end - Relations.graph_to join_rows, relations, target_collection_class, db + Relations.graph_to join_rows, relations, target_collection_class, db, schema relation_rows = join_rows.each_with_object(Hash.new { |h,k| h[k] = [] }) do |row, hash| hash[row[source_foreign_key]] << target_collection_class.model.new(row) diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb index 9dfafeb..6350757 100644 --- a/spec/collection_spec.rb +++ b/spec/collection_spec.rb @@ -148,4 +148,78 @@ end + describe 'Schemas' do + + let :stub_db do + stubs = Proc.new do |sql| + case sql + + when 'SELECT * FROM custom_schema.users', + 'SELECT * FROM custom_schema.users WHERE (id IN (2, 1))' + [ + {id: 1}, + {id: 2} + ] + + when 'SELECT * FROM custom_schema.posts', + 'SELECT * FROM custom_schema.posts WHERE (user_id IN (1, 2))' + [ + {id: 3, user_id: 1}, + {id: 4, user_id: 2} + ] + + when 'SELECT * FROM custom_schema.comments WHERE (post_id IN (3, 4))' + [ + {id: 5, user_id: 2, post_id: 3}, + {id: 6, user_id: 1, post_id: 3}, + {id: 7, user_id: 1, post_id: 4}, + {id: 8, user_id: 2, post_id: 4} + ] + + else + nil + end + end + + Sequel.mock fetch: stubs + end + + let(:stub_users) { Users.new stub_db, :custom_schema } + let(:stub_posts) { Posts.new stub_db, :custom_schema } + + it 'Insert' do + stub_users.insert name: 'User 1' + stub_db.sqls.must_equal ["INSERT INTO custom_schema.users (name) VALUES ('User 1')"] + end + + it 'Update' do + stub_users.update 1, name: 'Updated name' + stub_db.sqls.must_equal ["UPDATE custom_schema.users SET name = 'Updated name' WHERE (id = 1)"] + end + + it 'Delete' do + stub_users.delete 1 + stub_db.sqls.must_equal ['DELETE FROM custom_schema.users WHERE (id = 1)'] + end + + it 'Query' do + stub_users.query { where(id: [1,2]).limit(1).order(:name) } + stub_db.sqls.must_equal ['SELECT * FROM custom_schema.users WHERE (id IN (1, 2)) ORDER BY name LIMIT 1'] + end + + it 'Graph' do + stub_posts.query { graph :user, :categories, 'comments.user.posts.categories' } + stub_db.sqls.must_equal [ + 'SELECT * FROM custom_schema.posts', + 'SELECT * FROM custom_schema.users WHERE (id IN (1, 2))', + 'SELECT * FROM custom_schema.categories INNER JOIN custom_schema.categories_posts ON (custom_schema.categories_posts.category_id = custom_schema.categories.id) WHERE (custom_schema.categories_posts.post_id IN (3, 4))', + 'SELECT * FROM custom_schema.comments WHERE (post_id IN (3, 4))', + 'SELECT * FROM custom_schema.users WHERE (id IN (2, 1))', + 'SELECT * FROM custom_schema.posts WHERE (user_id IN (1, 2))', + 'SELECT * FROM custom_schema.categories INNER JOIN custom_schema.categories_posts ON (custom_schema.categories_posts.category_id = custom_schema.categories.id) WHERE (custom_schema.categories_posts.post_id IN (3, 4))' + ] + end + + end + end \ No newline at end of file diff --git a/spec/minitest_helper.rb b/spec/minitest_helper.rb index 4919544..ec148d3 100644 --- a/spec/minitest_helper.rb +++ b/spec/minitest_helper.rb @@ -33,6 +33,8 @@ class Categories < Rasti::DB::Collection class Minitest::Spec + DB_DRIVER = (RUBY_ENGINE == 'jruby') ? 'jdbc:sqlite::memory:' : {adapter: :sqlite} + let(:users) { Users.new db } let(:posts) { Posts.new db } @@ -42,9 +44,7 @@ class Minitest::Spec let(:categories) { Categories.new db } let :db do - driver = (RUBY_ENGINE == 'jruby') ? 'jdbc:sqlite::memory:' : {adapter: :sqlite} - - db = Sequel.connect driver + db = Sequel.connect DB_DRIVER db.create_table :users do primary_key :id