spec/unit/relation_spec.rb in rom-sql-0.7.0 vs spec/unit/relation_spec.rb in rom-sql-0.8.0
- old
+ new
@@ -4,197 +4,269 @@
include_context 'users and tasks'
let(:users) { container.relations.users }
let(:tasks) { container.relations.tasks }
- before do
- configuration.relation(:users) do
- def sorted
- order(:id)
- end
- end
+ context 'with schema', adapter: :sqlite do
+ let(:uri) { SQLITE_DB_URI }
- configuration.relation(:tasks)
- end
+ before do
+ conf.relation(:users) do
+ schema do
+ attribute :id, ROM::SQL::Types::Serial
+ attribute :name, ROM::SQL::Types::String
+ end
- describe '#dataset' do
- it 'selects all qualified columns and sorts by pk' do
- expect(users.dataset).to eql(
- users.select(*users.columns).order(:users__id).dataset
- )
+ def sorted
+ order(:id)
+ end
+ end
+
+ conf.relation(:tasks)
end
- end
- describe '#sum' do
- it 'delegates to dataset and return value' do
- expect(users.dataset).to receive(:sum).with(:id).and_call_original
- expect(users.sum(:id)).to eql(1)
+ describe '#dataset' do
+ it 'uses schema to infer default dataset' do
+ expect(container.relations[:users].dataset).to eql(
+ container.gateways[:default].dataset(:users).select(:id, :name).order(:users__id)
+ )
+ end
end
end
- describe '#min' do
- it 'delegates to dataset and return value' do
- users.insert id: 2, name: 'Oskar'
+ with_adapters do
+ context 'without schema' do
+ before do
+ conf.relation(:users) do
+ def sorted
+ order(:id)
+ end
+ end
- expect(users.dataset).to receive(:min).with(:id).and_call_original
- expect(users.min(:id)).to eql(1)
- end
- end
+ conf.relation(:tasks)
+ end
- describe '#max' do
- it 'delegates to dataset and return value' do
- users.insert id: 2, name: 'Oskar'
+ describe '#associations' do
+ it 'returns an empty association set' do
+ expect(users.associations.elements).to be_empty
+ end
+ end
- expect(users.dataset).to receive(:max).with(:id).and_call_original
- expect(users.max(:id)).to eql(2)
- end
- end
+ describe '#dataset' do
+ it 'selects all qualified columns and sorts by pk' do
+ expect(users.dataset).to eql(
+ users.select(*users.columns).order(:users__id).dataset
+ )
+ end
+ end
- describe '#avg' do
- it 'delegates to dataset and return value' do
- users.insert id: 2, name: 'Oskar'
+ describe '#primary_key' do
+ it 'returns :id by default' do
+ expect(users.primary_key).to be(:id)
+ end
- expect(users.dataset).to receive(:avg).with(:id).and_call_original
- expect(users.avg(:id)).to eql(1.5)
- end
- end
+ it 'returns configured primary key from the schema' do
+ conf.relation(:other_users) do
+ schema(:users) do
+ attribute :name, ROM::SQL::Types::String.meta(primary_key: true)
+ end
+ end
- describe '#distinct' do
- it 'delegates to dataset and returns a new relation' do
- expect(users.dataset).to receive(:distinct).with(:name).and_call_original
- expect(users.distinct(:name)).to_not eq(users)
- end
- end
+ expect(container.relations[:other_users].primary_key).to be(:name)
+ end
+ end
- describe '#exclude' do
- it 'delegates to dataset and returns a new relation' do
- expect(users.dataset)
- .to receive(:exclude).with(name: 'Piotr').and_call_original
- expect(users.exclude(name: 'Piotr')).to_not eq(users)
- end
- end
+ describe '#sum' do
+ it 'returns a sum' do
+ expect(users.sum(:id)).to eql(3)
+ end
+ end
- describe '#invert' do
- it 'delegates to dataset and returns a new relation' do
- expect(users.dataset).to receive(:invert).and_call_original
- expect(users.invert).to_not eq(users)
- end
- end
+ describe '#min' do
+ it 'returns a min' do
+ expect(users.min(:id)).to eql(1)
+ end
+ end
- describe '#map' do
- it 'yields tuples' do
- result = users.map { |tuple| tuple[:name] }
- expect(result).to eql(%w(Piotr))
- end
- end
+ describe '#max' do
+ it 'delegates to dataset and return value' do
+ expect(users.max(:id)).to eql(2)
+ end
+ end
- describe '#inner_join' do
- it 'joins relations using inner join' do
- conn[:users].insert(id: 2, name: 'Jane')
+ describe '#avg' do
+ it 'delegates to dataset and return value' do
+ expect(users.avg(:id)).to eql(1.5)
+ end
+ end
- result = users.inner_join(:tasks, user_id: :id).select(:name, :title)
+ describe '#distinct' do
+ it 'delegates to dataset and returns a new relation' do
+ expect(users.dataset).to receive(:distinct).with(:name).and_call_original
+ expect(users.distinct(:name)).to_not eq(users)
+ end
+ end
- expect(result.to_a).to match_array([
- { name: 'Piotr', title: 'Finish ROM' }
- ])
- end
+ describe '#exclude' do
+ it 'delegates to dataset and returns a new relation' do
+ expect(users.dataset)
+ .to receive(:exclude).with(name: 'Jane').and_call_original
+ expect(users.exclude(name: 'Jane')).to_not eq(users)
+ end
+ end
- it 'raises error when column names are ambiguous' do
- expect {
- users.inner_join(:tasks, user_id: :id).to_a
- }.to raise_error(Sequel::DatabaseError, /column reference "id" is ambiguous/)
- end
- end
+ describe '#invert' do
+ it 'delegates to dataset and returns a new relation' do
+ expect(users.dataset).to receive(:invert).and_call_original
+ expect(users.invert).to_not eq(users)
+ end
+ end
- describe '#left_join' do
- it 'joins relations using left outer join' do
- conn[:users].insert(id: 2, name: 'Jane')
+ describe '#map' do
+ it 'yields tuples' do
+ result = users.map { |tuple| tuple[:name] }
+ expect(result).to eql(%w(Jane Joe))
+ end
- result = users.left_join(:tasks, user_id: :id).select(:name, :title)
+ it 'plucks value' do
+ expect(users.map(:name)).to eql(%w(Jane Joe))
+ end
+ end
- expect(result.to_a).to match_array([
- { name: 'Piotr', title: 'Finish ROM' },
- { name: 'Jane', title: nil }
- ])
- end
- end
+ describe '#inner_join' do
+ it 'joins relations using inner join' do
+ result = users.inner_join(:tasks, user_id: :id).select(:name, :title)
- describe '#project' do
- it 'projects the dataset using new column names' do
- projected = users.sorted.project(:name)
+ expect(result.to_a).to eql([
+ { name: 'Jane', title: "Jane's task" },
+ { name: 'Joe', title: "Joe's task" }
+ ])
+ end
- expect(projected.header).to match_array([:name])
- expect(projected.to_a).to eql([{ name: 'Piotr' }])
- end
- end
+ it 'raises error when column names are ambiguous' do
+ expect {
+ users.inner_join(:tasks, user_id: :id).to_a
+ }.to raise_error(Sequel::DatabaseError, /is ambiguous/)
+ end
+ end
- describe '#rename' do
- it 'projects the dataset using new column names' do
- renamed = users.sorted.rename(id: :user_id, name: :user_name)
+ describe '#left_join' do
+ it 'joins relations using left outer join' do
+ result = users.left_join(:tasks, user_id: :id).select(:name, :title)
- expect(renamed.to_a).to eql([{ user_id: 1, user_name: 'Piotr' }])
- end
- end
+ expect(result.to_a).to match_array([
+ { name: 'Joe', title: "Joe's task" },
+ { name: 'Jane', title: "Jane's task" }
+ ])
+ end
+ end
- describe '#prefix' do
- it 'projects the dataset using new column names' do
- prefixed = users.sorted.prefix(:user)
+ describe '#project' do
+ it 'projects the dataset using new column names' do
+ projected = users.sorted.project(:name)
- expect(prefixed.to_a).to eql([{ user_id: 1, user_name: 'Piotr' }])
- end
+ expect(projected.header).to match_array([:name])
+ expect(projected.first).to eql(name: 'Jane')
+ end
+ end
- it 'uses singularized table name as the default prefix' do
- prefixed = users.sorted.prefix
+ describe '#rename' do
+ it 'projects the dataset using new column names' do
+ renamed = users.sorted.rename(id: :user_id, name: :user_name)
- expect(prefixed.to_a).to eql([{ user_id: 1, user_name: 'Piotr' }])
- end
- end
+ expect(renamed.first).to eql(user_id: 1, user_name: 'Jane')
+ end
+ end
- describe '#qualified_columns' do
- it 'returns qualified column names' do
- columns = users.sorted.prefix(:user).qualified_columns
+ describe '#prefix' do
+ it 'projects the dataset using new column names' do
+ prefixed = users.sorted.prefix(:user)
- expect(columns).to eql([:users__id___user_id, :users__name___user_name])
- end
+ expect(prefixed.first).to eql(user_id: 1, user_name: 'Jane')
+ end
- it 'returns projected qualified column names' do
- columns = users.sorted.project(:id).prefix(:user).qualified_columns
+ it 'uses singularized table name as the default prefix' do
+ prefixed = users.sorted.prefix
- expect(columns).to eql([:users__id___user_id])
- end
- end
+ expect(prefixed.first).to eql(user_id: 1, user_name: 'Jane')
+ end
+ end
- describe '#inspect' do
- it 'includes dataset' do
- expect(users.inspect).to include('dataset')
- end
- end
+ describe '#qualified_columns' do
+ it 'returns qualified column names' do
+ columns = users.sorted.prefix(:user).qualified_columns
- describe '#unique?' do
- before { tasks.delete }
+ expect(columns).to eql([:users__id___user_id, :users__name___user_name])
+ end
- it 'returns true when there is only one tuple matching criteria' do
- expect(tasks.unique?(title: 'Task One')).to be(true)
- end
+ it 'returns projected qualified column names' do
+ columns = users.sorted.project(:id).prefix(:user).qualified_columns
- it 'returns true when there are more than one tuple matching criteria' do
- tasks.insert(title: 'Task One')
- expect(tasks.unique?(title: 'Task One')).to be(false)
- end
- end
+ expect(columns).to eql([:users__id___user_id])
+ end
+ end
- describe '#union' do
- let(:relation1) { users.where(id: 1).select(:id, :name) }
- let(:relation2) { users.where(id: 2).select(:id, :name) }
+ describe '#inspect' do
+ it 'includes dataset' do
+ expect(users.inspect).to include('dataset')
+ end
+ end
- it 'unions two relations and returns a new relation' do
- conn[:users].insert(id: 2, name: 'Jane')
+ describe '#unique?' do
+ before { tasks.delete }
- result = relation1.union(relation2)
+ it 'returns true when there is only one tuple matching criteria' do
+ expect(tasks.unique?(title: 'Task One')).to be(true)
+ end
- expect(result.to_a).to match_array([
- { id: 1, name: 'Piotr' },
- { id: 2, name: 'Jane' }
- ])
+ it 'returns true when there are more than one tuple matching criteria' do
+ tasks.insert(title: 'Task One')
+ expect(tasks.unique?(title: 'Task One')).to be(false)
+ end
+ end
+
+ describe '#union' do
+ let(:relation1) { users.where(id: 1).select(:id, :name) }
+ let(:relation2) { users.where(id: 2).select(:id, :name) }
+
+ it 'unions two relations and returns a new relation' do
+ result = relation1.union(relation2)
+
+ expect(result.to_a).to match_array([
+ { id: 1, name: 'Jane' },
+ { id: 2, name: 'Joe' }
+ ])
+ end
+ end
+
+ describe '#pluck' do
+ it 'returns a list of values from a specific column' do
+ expect(users.pluck(:id)).to eql([1, 2])
+ end
+ end
+
+ describe '#by_pk' do
+ it 'restricts a relation by its PK' do
+ expect(users.by_pk(1).to_a).to eql([id: 1, name: 'Jane'])
+ end
+
+ it 'is available as a view' do
+ expect(users.by_pk).to be_curried
+ end
+ end
+
+ describe '#fetch' do
+ it 'returns a single tuple identified by the pk' do
+ expect(users.fetch(1)).to eql(id: 1, name: 'Jane')
+ end
+
+ it 'raises when tuple was not found' do
+ expect { users.fetch(535315412) }.to raise_error(ROM::TupleCountMismatchError)
+ end
+
+ it 'raises when more tuples were returned' do
+ expect { users.fetch([1, 2]) }.to raise_error(ROM::TupleCountMismatchError)
+ end
+ end
end
end
end