Skip to content

Commit

Permalink
Improve schema support and added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gabynaiman committed Sep 23, 2016
1 parent f59c60f commit 638795a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 20 deletions.
2 changes: 1 addition & 1 deletion lib/rasti/db/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions lib/rasti/db/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -54,7 +55,7 @@ def to_s

private

attr_reader :collection_class, :dataset
attr_reader :collection_class, :dataset, :schema

end
end
Expand Down
28 changes: 16 additions & 12 deletions lib/rasti/db/relations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
74 changes: 74 additions & 0 deletions spec/collection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 3 additions & 3 deletions spec/minitest_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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
Expand Down

0 comments on commit 638795a

Please sign in to comment.