rom-sql 2.0.0.beta2 → 2.0.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +54 -0
- data/lib/rom/sql.rb +1 -1
- data/lib/rom/sql/attribute.rb +17 -18
- data/lib/rom/sql/errors.rb +3 -0
- data/lib/rom/sql/extensions/mysql.rb +1 -1
- data/lib/rom/sql/extensions/mysql/type_builder.rb +28 -0
- data/lib/rom/sql/extensions/postgres.rb +3 -1
- data/lib/rom/sql/extensions/postgres/commands.rb +30 -13
- data/lib/rom/sql/extensions/postgres/{attributes_inferrer.rb → type_builder.rb} +24 -28
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +39 -0
- data/lib/rom/sql/extensions/postgres/types.rb +24 -477
- data/lib/rom/sql/extensions/postgres/types/array.rb +163 -0
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +135 -0
- data/lib/rom/sql/extensions/postgres/types/json.rb +235 -0
- data/lib/rom/sql/extensions/postgres/types/network.rb +15 -0
- data/lib/rom/sql/extensions/sqlite.rb +1 -1
- data/lib/rom/sql/extensions/sqlite/{attributes_inferrer.rb → type_builder.rb} +5 -5
- data/lib/rom/sql/extensions/sqlite/types.rb +8 -3
- data/lib/rom/sql/foreign_key.rb +17 -0
- data/lib/rom/sql/function.rb +86 -8
- data/lib/rom/sql/gateway.rb +26 -26
- data/lib/rom/sql/index.rb +4 -0
- data/lib/rom/sql/migration.rb +3 -3
- data/lib/rom/sql/migration/inline_runner.rb +9 -83
- data/lib/rom/sql/migration/migrator.rb +35 -12
- data/lib/rom/sql/migration/recorder.rb +21 -0
- data/lib/rom/sql/migration/runner.rb +115 -0
- data/lib/rom/sql/migration/schema_diff.rb +108 -53
- data/lib/rom/sql/migration/writer.rb +61 -0
- data/lib/rom/sql/relation.rb +2 -1
- data/lib/rom/sql/relation/reading.rb +63 -3
- data/lib/rom/sql/relation/writing.rb +38 -0
- data/lib/rom/sql/schema.rb +9 -3
- data/lib/rom/sql/schema/attributes_inferrer.rb +3 -119
- data/lib/rom/sql/schema/inferrer.rb +99 -18
- data/lib/rom/sql/schema/type_builder.rb +94 -0
- data/lib/rom/sql/type_dsl.rb +30 -0
- data/lib/rom/sql/type_extensions.rb +11 -6
- data/lib/rom/sql/type_serializer.rb +46 -0
- data/lib/rom/sql/types.rb +12 -0
- data/lib/rom/sql/version.rb +1 -1
- metadata +26 -244
- data/.codeclimate.yml +0 -15
- data/.gitignore +0 -17
- data/.rspec +0 -3
- data/.travis.yml +0 -39
- data/.yardopts +0 -2
- data/Gemfile +0 -33
- data/Guardfile +0 -24
- data/LICENSE.txt +0 -22
- data/Rakefile +0 -19
- data/circle.yml +0 -10
- data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +0 -10
- data/lib/rom/sql/relation/sequel_api.rb +0 -133
- data/log/.gitkeep +0 -0
- data/rom-sql.gemspec +0 -29
- data/spec/extensions/postgres/attribute_spec.rb +0 -217
- data/spec/extensions/postgres/integration_spec.rb +0 -59
- data/spec/extensions/postgres/types_spec.rb +0 -252
- data/spec/extensions/sqlite/types_spec.rb +0 -11
- data/spec/fixtures/migrations/20150403090603_create_carrots.rb +0 -8
- data/spec/integration/associations/many_to_many/custom_fks_spec.rb +0 -76
- data/spec/integration/associations/many_to_many/from_view_spec.rb +0 -88
- data/spec/integration/associations/many_to_many_spec.rb +0 -162
- data/spec/integration/associations/many_to_one/custom_fks_spec.rb +0 -64
- data/spec/integration/associations/many_to_one/from_view_spec.rb +0 -84
- data/spec/integration/associations/many_to_one/self_ref_spec.rb +0 -53
- data/spec/integration/associations/many_to_one_spec.rb +0 -117
- data/spec/integration/associations/one_to_many/custom_fks_spec.rb +0 -54
- data/spec/integration/associations/one_to_many/from_view_spec.rb +0 -57
- data/spec/integration/associations/one_to_many/self_ref_spec.rb +0 -54
- data/spec/integration/associations/one_to_many_spec.rb +0 -86
- data/spec/integration/associations/one_to_one_spec.rb +0 -69
- data/spec/integration/associations/one_to_one_through_spec.rb +0 -92
- data/spec/integration/auto_migrations/errors_spec.rb +0 -31
- data/spec/integration/auto_migrations/indexes_spec.rb +0 -253
- data/spec/integration/auto_migrations/managing_columns_spec.rb +0 -156
- data/spec/integration/auto_migrations/postgres/column_types_spec.rb +0 -63
- data/spec/integration/combine_with_spec.rb +0 -43
- data/spec/integration/commands/create_spec.rb +0 -304
- data/spec/integration/commands/delete_spec.rb +0 -84
- data/spec/integration/commands/update_spec.rb +0 -90
- data/spec/integration/commands/upsert_spec.rb +0 -83
- data/spec/integration/gateway_spec.rb +0 -107
- data/spec/integration/migration_spec.rb +0 -55
- data/spec/integration/plugins/associates/many_to_many_spec.rb +0 -69
- data/spec/integration/plugins/associates_spec.rb +0 -250
- data/spec/integration/plugins/auto_restrictions_spec.rb +0 -74
- data/spec/integration/relation_schema_spec.rb +0 -271
- data/spec/integration/schema/call_spec.rb +0 -24
- data/spec/integration/schema/inferrer/mysql_spec.rb +0 -45
- data/spec/integration/schema/inferrer/postgres_spec.rb +0 -203
- data/spec/integration/schema/inferrer/sqlite_spec.rb +0 -37
- data/spec/integration/schema/inferrer_spec.rb +0 -390
- data/spec/integration/schema/prefix_spec.rb +0 -16
- data/spec/integration/schema/qualified_spec.rb +0 -16
- data/spec/integration/schema/rename_spec.rb +0 -21
- data/spec/integration/schema/view_spec.rb +0 -29
- data/spec/integration/sequel_api_spec.rb +0 -36
- data/spec/integration/setup_spec.rb +0 -26
- data/spec/integration/support/active_support_notifications_spec.rb +0 -24
- data/spec/integration/support/rails_log_subscriber_spec.rb +0 -30
- data/spec/integration/wrap_spec.rb +0 -91
- data/spec/shared/accounts.rb +0 -48
- data/spec/shared/database_setup.rb +0 -70
- data/spec/shared/notes.rb +0 -23
- data/spec/shared/posts.rb +0 -34
- data/spec/shared/puppies.rb +0 -15
- data/spec/shared/relations.rb +0 -8
- data/spec/shared/users.rb +0 -32
- data/spec/shared/users_and_tasks.rb +0 -50
- data/spec/spec_helper.rb +0 -122
- data/spec/support/env_helper.rb +0 -25
- data/spec/support/helpers.rb +0 -24
- data/spec/support/oracle/create_users.sql +0 -7
- data/spec/support/oracle/set_sys_passwords.sql +0 -2
- data/spec/support/test_configuration.rb +0 -16
- data/spec/unit/attribute_spec.rb +0 -104
- data/spec/unit/function_spec.rb +0 -48
- data/spec/unit/gateway_spec.rb +0 -70
- data/spec/unit/logger_spec.rb +0 -14
- data/spec/unit/migration_tasks_spec.rb +0 -111
- data/spec/unit/migrator_spec.rb +0 -25
- data/spec/unit/order_dsl_spec.rb +0 -43
- data/spec/unit/plugin/associates_spec.rb +0 -94
- data/spec/unit/plugin/pagination_spec.rb +0 -91
- data/spec/unit/plugin/timestamp_spec.rb +0 -117
- data/spec/unit/projection_dsl_spec.rb +0 -110
- data/spec/unit/relation/assoc_spec.rb +0 -87
- data/spec/unit/relation/associations_spec.rb +0 -27
- data/spec/unit/relation/avg_spec.rb +0 -11
- data/spec/unit/relation/by_pk_spec.rb +0 -62
- data/spec/unit/relation/dataset_spec.rb +0 -50
- data/spec/unit/relation/distinct_spec.rb +0 -15
- data/spec/unit/relation/exclude_spec.rb +0 -11
- data/spec/unit/relation/exist_predicate_spec.rb +0 -25
- data/spec/unit/relation/exists_spec.rb +0 -18
- data/spec/unit/relation/fetch_spec.rb +0 -21
- data/spec/unit/relation/group_spec.rb +0 -61
- data/spec/unit/relation/having_spec.rb +0 -22
- data/spec/unit/relation/inner_join_spec.rb +0 -158
- data/spec/unit/relation/inspect_spec.rb +0 -11
- data/spec/unit/relation/instrument_spec.rb +0 -45
- data/spec/unit/relation/invert_spec.rb +0 -11
- data/spec/unit/relation/left_join_spec.rb +0 -55
- data/spec/unit/relation/lock_spec.rb +0 -93
- data/spec/unit/relation/map_spec.rb +0 -16
- data/spec/unit/relation/max_spec.rb +0 -11
- data/spec/unit/relation/min_spec.rb +0 -11
- data/spec/unit/relation/order_spec.rb +0 -51
- data/spec/unit/relation/pluck_spec.rb +0 -11
- data/spec/unit/relation/prefix_spec.rb +0 -29
- data/spec/unit/relation/primary_key_spec.rb +0 -27
- data/spec/unit/relation/project_spec.rb +0 -24
- data/spec/unit/relation/qualified_columns_spec.rb +0 -30
- data/spec/unit/relation/qualified_spec.rb +0 -25
- data/spec/unit/relation/read_spec.rb +0 -25
- data/spec/unit/relation/rename_spec.rb +0 -23
- data/spec/unit/relation/right_join_spec.rb +0 -57
- data/spec/unit/relation/select_append_spec.rb +0 -21
- data/spec/unit/relation/select_spec.rb +0 -40
- data/spec/unit/relation/sum_spec.rb +0 -11
- data/spec/unit/relation/union_spec.rb +0 -19
- data/spec/unit/relation/unique_predicate_spec.rb +0 -18
- data/spec/unit/relation/where_spec.rb +0 -133
- data/spec/unit/restriction_dsl_spec.rb +0 -34
- data/spec/unit/schema_spec.rb +0 -25
- data/spec/unit/types_spec.rb +0 -65
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
require 'rom/sql/plugin/timestamps'
|
|
2
|
-
|
|
3
|
-
RSpec.describe 'Plugin / Timestamp' do
|
|
4
|
-
include_context 'users'
|
|
5
|
-
include_context 'notes'
|
|
6
|
-
|
|
7
|
-
with_adapters do
|
|
8
|
-
before do
|
|
9
|
-
conf.commands(:notes) do
|
|
10
|
-
define :create do
|
|
11
|
-
result :one
|
|
12
|
-
use :timestamps
|
|
13
|
-
timestamp :updated_at, :created_at
|
|
14
|
-
datestamp :written
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
define :create_many, type: :create do
|
|
18
|
-
result :many
|
|
19
|
-
use :timestamps
|
|
20
|
-
timestamp :updated_at, :created_at
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
define :update do
|
|
24
|
-
use :timestamps
|
|
25
|
-
timestamp :updated_at
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
define :create_with_user, type: :create do
|
|
29
|
-
result :one
|
|
30
|
-
use :timestamps
|
|
31
|
-
timestamp :updated_at, :created_at
|
|
32
|
-
|
|
33
|
-
before :assign_user
|
|
34
|
-
def assign_user(tuple, user)
|
|
35
|
-
tuple.merge(user_id: user[:id])
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
conf.commands(:users) do
|
|
41
|
-
define :create do
|
|
42
|
-
result :one
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "applies timestamps by default" do
|
|
48
|
-
time = DateTime.now
|
|
49
|
-
result = container.commands[:notes].create.call(text: "This is a test")
|
|
50
|
-
|
|
51
|
-
created = DateTime.parse(result[:created_at].to_s)
|
|
52
|
-
updated = DateTime.parse(result[:updated_at].to_s)
|
|
53
|
-
|
|
54
|
-
expect(created).to be_within(1).of(time)
|
|
55
|
-
expect(updated).to eq created
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it "applies datestamps by default" do
|
|
59
|
-
result = container.commands[:notes].create.call(text: "This is a test")
|
|
60
|
-
expect(Date.parse(result[:written].to_s)).to eq Date.today
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it "sets timestamps on multi-tuple inputs" do
|
|
64
|
-
time = DateTime.now
|
|
65
|
-
input = [{text: "note one"}, {text: "note two"}]
|
|
66
|
-
|
|
67
|
-
results = container.commands[:notes].create_many.call(input)
|
|
68
|
-
|
|
69
|
-
results.each do |result|
|
|
70
|
-
created = DateTime.parse(result[:created_at].to_s)
|
|
71
|
-
|
|
72
|
-
expect(created).to be_within(1).of(time)
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "only updates specified timestamps" do
|
|
77
|
-
initial = container.commands[:notes].create.call(text: "testing")
|
|
78
|
-
sleep 1 # Unfortunate, but unless I start injecting clocks into the
|
|
79
|
-
# command, this is needed to make sure the time actually changes
|
|
80
|
-
updated = container.commands[:notes].update.call(text: "updated test").first
|
|
81
|
-
|
|
82
|
-
expect(updated[:created_at]).to eq initial[:created_at]
|
|
83
|
-
expect(updated[:updated_at]).not_to eq initial[:updated_at]
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "allows overriding timestamps" do |ex|
|
|
87
|
-
tomorrow = (Time.now + (60 * 60 * 24))
|
|
88
|
-
|
|
89
|
-
container.commands[:notes].create.call(text: "testing")
|
|
90
|
-
updated = container.commands[:notes].update.call(text: "updated test", updated_at: tomorrow).first
|
|
91
|
-
|
|
92
|
-
if jruby? && sqlite?(ex)
|
|
93
|
-
expect(updated[:updated_at]).to eql(tomorrow.strftime('%Y-%m-%d %H:%M:%S.%6N'))
|
|
94
|
-
else
|
|
95
|
-
expect(updated[:updated_at].iso8601).to eql(tomorrow.iso8601)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "works with chained commands" do
|
|
100
|
-
create_user = container.commands[:users].create.curry(name: "John Doe")
|
|
101
|
-
create_note = container.commands[:notes].create_with_user.curry(text: "new note")
|
|
102
|
-
|
|
103
|
-
time = DateTime.now
|
|
104
|
-
command = create_user >> create_note
|
|
105
|
-
|
|
106
|
-
result = command.call
|
|
107
|
-
|
|
108
|
-
created = DateTime.parse(result[:created_at].to_s)
|
|
109
|
-
updated = DateTime.parse(result[:updated_at].to_s)
|
|
110
|
-
|
|
111
|
-
expect(result[:user_id]).not_to be_nil
|
|
112
|
-
expect(created).to be_within(1).of(time)
|
|
113
|
-
expect(updated).to eq created
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
end
|
|
117
|
-
end
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe ROM::SQL::ProjectionDSL, :postgres, helpers: true do
|
|
4
|
-
include_context 'database setup'
|
|
5
|
-
|
|
6
|
-
subject(:dsl) do
|
|
7
|
-
ROM::SQL::ProjectionDSL.new(schema)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
let(:schema) do
|
|
11
|
-
define_schema(:users, id: ROM::SQL::Types::Serial, name: ROM::SQL::Types::String, meta: ROM::SQL::Types::PG::JSONB)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
let(:ds) do
|
|
15
|
-
conn[:users]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
describe '#call' do
|
|
19
|
-
it 'evaluates the block and returns an array with attribute types' do
|
|
20
|
-
literals = dsl
|
|
21
|
-
.call { int::count(id).as(:count) }
|
|
22
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
23
|
-
|
|
24
|
-
expect(literals).to eql([%(COUNT("id") AS "count")])
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it 'supports chaining attribute db functions' do
|
|
28
|
-
literals = dsl
|
|
29
|
-
.call { meta.pg_jsonb.get_text("name").as(:name) }
|
|
30
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
31
|
-
|
|
32
|
-
expect(literals).to eql([%{("meta" ->> 'name') AS "name"}])
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it 'supports functions with args and chaining with other functions' do
|
|
36
|
-
literals = dsl
|
|
37
|
-
.call { int::count(id.qualified).distinct }
|
|
38
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
39
|
-
|
|
40
|
-
expect(literals).to eql([%(COUNT(DISTINCT "users"."id"))])
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it 'supports functions with args and chaining with other functions and an alias' do
|
|
44
|
-
literals = dsl
|
|
45
|
-
.call { int::count(id.qualified).distinct.as(:count) }
|
|
46
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
47
|
-
|
|
48
|
-
expect(literals).to eql([%(COUNT(DISTINCT "users"."id") AS "count")])
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
it 'supports functions with arg being an attribute' do
|
|
52
|
-
literals = dsl
|
|
53
|
-
.call { int::count(id).as(:count) }
|
|
54
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
55
|
-
|
|
56
|
-
expect(literals).to eql([%(COUNT("id") AS "count")])
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it 'supports functions with arg being a qualified attribute' do
|
|
60
|
-
literals = dsl
|
|
61
|
-
.call { int::count(id.qualified).as(:count) }
|
|
62
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
63
|
-
|
|
64
|
-
expect(literals).to eql([%(COUNT("users"."id") AS "count")])
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it 'supports selecting literal strings' do
|
|
68
|
-
literals = dsl
|
|
69
|
-
.call { `'event'`.as(:type) }
|
|
70
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
71
|
-
|
|
72
|
-
expect(literals).to eql([%('event' AS "type")])
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
it 'supports functions without return value' do
|
|
76
|
-
literals = dsl
|
|
77
|
-
.call { void::pg_advisory_lock(1).as(:lock) }
|
|
78
|
-
.map { |attr| attr.sql_literal(ds) }
|
|
79
|
-
|
|
80
|
-
expect(literals).to eql([%(PG_ADVISORY_LOCK(1) AS "lock")])
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
describe '#method_missing' do
|
|
85
|
-
it 'responds to methods matching attribute names' do
|
|
86
|
-
expect(dsl.id).to eql(schema[:id])
|
|
87
|
-
expect(dsl.name).to eql(schema[:name])
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
it 'responds to methods matching type identifiers' do
|
|
91
|
-
expect(dsl.int).to eql(ROM::SQL::Types::Int)
|
|
92
|
-
expect(dsl.string).to eql(ROM::SQL::Types::String)
|
|
93
|
-
expect(dsl.bool).to eql(ROM::SQL::Types::Bool)
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
it 'responds to methods matching type names' do
|
|
97
|
-
expect(dsl.DateTime).to eql(ROM::SQL::Types::DateTime)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it 'returns sql functions with return type specified' do
|
|
101
|
-
function = ROM::SQL::Function.new(ROM::SQL::Types::String).upper(schema[:name])
|
|
102
|
-
|
|
103
|
-
expect(dsl.string::upper(schema[:name])).to eql(function)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
it 'raises NoMethodError when there is no matching attribute or type' do
|
|
107
|
-
expect { dsl.not_here }.to raise_error(NoMethodError, /not_here/)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
RSpec.describe ROM::SQL::Relation do
|
|
4
|
-
include_context 'users and tasks'
|
|
5
|
-
|
|
6
|
-
context 'with has_many' do
|
|
7
|
-
subject(:users) { relations[:users] }
|
|
8
|
-
|
|
9
|
-
let(:tasks) { relations[:tasks] }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
conf.relation(:users) do
|
|
13
|
-
schema(infer: true) do
|
|
14
|
-
associations do
|
|
15
|
-
has_many :tasks
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
with_adapters do
|
|
22
|
-
it 'returns child tuples for a relation' do
|
|
23
|
-
expect(users.assoc(:tasks).where(name: 'Jane').to_a).
|
|
24
|
-
to eql([{ id: 2, user_id: 1, title: "Jane's task" }])
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
context 'with has_many-through' do
|
|
30
|
-
subject(:tasks) { relations[:tasks] }
|
|
31
|
-
|
|
32
|
-
before do
|
|
33
|
-
conf.relation(:task_tags) do
|
|
34
|
-
schema(infer: true) do
|
|
35
|
-
associations do
|
|
36
|
-
belongs_to :tasks
|
|
37
|
-
belongs_to :tags
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
conf.relation(:tasks) do
|
|
43
|
-
schema(infer: true) do
|
|
44
|
-
associations do
|
|
45
|
-
has_many :tags, through: :task_tags
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
conn[:tags].insert id: 2, name: 'whatevah'
|
|
51
|
-
conn[:task_tags].insert(tag_id: 2, task_id: 2)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
with_adapters do
|
|
55
|
-
it 'returns child tuples for a relation' do
|
|
56
|
-
expect(tasks.assoc(:tags).to_a).
|
|
57
|
-
to eql([{ id: 1, name: 'important', task_id: 1 }, { id: 2, name: 'whatevah', task_id: 2 }])
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it 'returns child tuples for a restricted relation' do
|
|
61
|
-
expect(tasks.assoc(:tags).where(title: "Jane's task").to_a).
|
|
62
|
-
to eql([{ id: 2, name: 'whatevah', task_id: 2 }])
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
context 'with belongs_to' do
|
|
68
|
-
subject(:tasks) { relations[:tasks] }
|
|
69
|
-
|
|
70
|
-
before do
|
|
71
|
-
conf.relation(:tasks) do
|
|
72
|
-
schema(infer: true) do
|
|
73
|
-
associations do
|
|
74
|
-
belongs_to :users, as: :user
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
with_adapters do
|
|
81
|
-
it 'returns parent tuples for a relation' do
|
|
82
|
-
expect(tasks.assoc(:user).where(title: "Jane's task").to_a).
|
|
83
|
-
to eql([{ id: 1, task_id: 2, name: 'Jane' }])
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
RSpec.describe ROM::Relation, '#associations' do
|
|
2
|
-
subject(:relation) { container.relations.users }
|
|
3
|
-
|
|
4
|
-
include_context 'users and tasks'
|
|
5
|
-
|
|
6
|
-
with_adapters do
|
|
7
|
-
context 'with schema' do
|
|
8
|
-
it 'returns configured primary key from the schema' do
|
|
9
|
-
conf.relation(:users) do
|
|
10
|
-
schema(infer: true) do
|
|
11
|
-
associations do
|
|
12
|
-
has_many :tasks
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
expect(relation.associations[:tasks]).to be(container.relations.users.schema.associations[:tasks])
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
context 'without schema' do
|
|
22
|
-
it 'returns an empty association set' do
|
|
23
|
-
expect(relation.associations.elements).to be_empty
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
RSpec.describe ROM::Relation, '#by_pk' do
|
|
2
|
-
include_context 'users and tasks'
|
|
3
|
-
|
|
4
|
-
with_adapters do
|
|
5
|
-
context 'with a single PK' do
|
|
6
|
-
subject(:relation) { relations[:users] }
|
|
7
|
-
|
|
8
|
-
it 'restricts a relation by its PK' do
|
|
9
|
-
expect(relation.by_pk(1).to_a).to eql([id: 1, name: 'Jane'])
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
it 'is available as a view' do
|
|
13
|
-
expect(relation.by_pk).to be_curried
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'qualifies pk attr' do
|
|
17
|
-
expect(relation.qualified.by_pk(1).select(:id).join(:tasks, user_id: :id).one).to eql(id: 1)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it 'works even when PK is not projected' do
|
|
21
|
-
expect(relation.select(:name).by_pk(1).to_a).to eql([name: 'Jane'])
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
context 'with a composite PK' do
|
|
26
|
-
subject(:relation) { relations[:task_tags] }
|
|
27
|
-
|
|
28
|
-
it 'restricts a relation by is PK' do
|
|
29
|
-
expect(relation.by_pk(1, 1).to_a).to eql([{ tag_id: 1, task_id: 1 }])
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 'works even when PK is not projected' do
|
|
33
|
-
expect(relation.by_pk(1, 1).select { `1`.as(:num) }.to_a).to eql([num: 1])
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
context 'without PK' do
|
|
38
|
-
subject(:relation) { relations[:people] }
|
|
39
|
-
|
|
40
|
-
before do
|
|
41
|
-
conn.drop_table?(:people)
|
|
42
|
-
|
|
43
|
-
conn.create_table(:people) do
|
|
44
|
-
column :name, String
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
conf.relation(:people) do
|
|
48
|
-
schema do
|
|
49
|
-
attribute :name, ROM::SQL::Types::String
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it 'raises a meaningful exception' do
|
|
55
|
-
expect { relation.by_pk(1) }.to \
|
|
56
|
-
raise_error(
|
|
57
|
-
ROM::SQL::MissingPrimaryKeyError,
|
|
58
|
-
'Missing primary key for :people')
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
RSpec.describe ROM::Relation, '#dataset' do
|
|
2
|
-
subject(:relation) { container.relations.users }
|
|
3
|
-
|
|
4
|
-
include_context 'users and tasks'
|
|
5
|
-
|
|
6
|
-
let(:dataset) { container.gateways[:default].dataset(:users) }
|
|
7
|
-
|
|
8
|
-
with_adapters do
|
|
9
|
-
context 'with schema' do
|
|
10
|
-
before do
|
|
11
|
-
conf.relation(:users) do
|
|
12
|
-
schema do
|
|
13
|
-
attribute :id, ROM::SQL::Types::Serial
|
|
14
|
-
attribute :name, ROM::SQL::Types::String
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it 'uses schema to infer default dataset' do
|
|
20
|
-
expect(relation.dataset.sql).
|
|
21
|
-
to eql(dataset.select(Sequel.qualify(:users, :id), Sequel.qualify(:users, :name)).order(Sequel.qualify(:users, :id)).sql)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
context 'with cherry-picked attributes in schema' do
|
|
26
|
-
before do
|
|
27
|
-
conf.relation(:users) do
|
|
28
|
-
schema do
|
|
29
|
-
attribute :id, ROM::SQL::Types::Serial
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it 'uses schema to infer default dataset' do
|
|
35
|
-
expect(relation.dataset.sql).
|
|
36
|
-
to eql(dataset.select(Sequel.qualify(:users, :id)).order(Sequel.qualify(:users, :id)).sql)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
context 'with inferred schema' do
|
|
41
|
-
before do
|
|
42
|
-
conf.relation(:users) { schema(infer: true) }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it 'selects all qualified columns and sorts by pk' do
|
|
46
|
-
expect(relation.dataset.sql).to eql(dataset.select(*relation.schema.qualified).order(Sequel.qualify(:users, :id)).sql)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|