# frozen_string_literal: true require 'spec_helper' module Aws module Record describe 'SecondaryIndexes' do let(:klass) do Class.new do include(Aws::Record) set_table_name('TestTable') integer_attr(:forum_id, hash_key: true) integer_attr(:post_id, range_key: true) string_attr(:forum_name) string_attr(:post_title) integer_attr(:author_id, database_attribute_name: 'a_id') string_attr(:author_name, database_attribute_name: 'a_name') string_attr(:post_body) end end let(:api_requests) { [] } let(:stub_client) do requests = api_requests client = Aws::DynamoDB::Client.new(stub_responses: true) client.handle do |context| requests << context.params @handler.call(context) end client end context 'Local Secondary Index' do describe '#local_secondary_index' do it 'allows you to define a local secondary index on the model' do klass.local_secondary_index( :title, range_key: :post_title, projection: { projection_type: 'ALL' } ) expect(klass.local_secondary_indexes[:title]).not_to eq(nil) end it 'requires that a range key is provided' do expect { klass.local_secondary_index( :fail, projection: { projection_type: 'ALL' } ) }.to raise_error(ArgumentError) end it 'requires use of an attribute that exists in the model' do expect { klass.local_secondary_index( :fail, range_key: :missingno, projection: { projection_type: 'ALL' } ) }.to raise_error(ArgumentError) end end describe '#local_secondary_indexes_for_migration' do it 'correctly translates database names for migration' do klass.local_secondary_index( :author, range_key: :author_id, projection: { projection_type: 'ALL' } ) migration = klass.local_secondary_indexes_for_migration expect(migration.size).to eq(1) expect(migration.first).to eq( index_name: :author, key_schema: [ { key_type: 'HASH', attribute_name: 'forum_id' }, { key_type: 'RANGE', attribute_name: 'a_id' } ], projection: { projection_type: 'ALL' } ) end end end context 'Global Secondary Indexes' do describe '#global_secondary_index' do it 'allows you to define a global secondary index on the model' do klass.global_secondary_index( :author, hash_key: :forum_name, range_key: :author_name, projection: { projection_type: 'ALL' } ) expect(klass.global_secondary_indexes[:author]).not_to eq(nil) end it 'requires that a hash key is provided' do expect { klass.global_secondary_index( :fail, projection: { projection_type: 'ALL' } ) }.to raise_error(ArgumentError) end it 'requires that the hash key exists in the model' do expect { klass.global_secondary_index( :fail, hash_key: :missingno, projection: { projection_type: 'ALL' } ) }.to raise_error(ArgumentError) end it 'requires that the range key exists in the model' do expect { klass.global_secondary_index( :fail, hash_key: :forum_name, range_key: :missingno, projection: { projection_type: 'ALL' } ) }.to raise_error(ArgumentError) end end describe '#global_secondary_indexes_for_migration' do it 'correctly translates database names for migration' do klass.global_secondary_index( :author, hash_key: :forum_name, range_key: :author_name, projection: { projection_type: 'ALL' } ) migration = klass.global_secondary_indexes_for_migration expect(migration.size).to eq(1) expect(migration.first).to eq( index_name: :author, key_schema: [ { key_type: 'HASH', attribute_name: 'forum_name' }, { key_type: 'RANGE', attribute_name: 'a_name' } ], projection: { projection_type: 'ALL' } ) end end end end describe 'inheritance support' do let(:parent_model) do Class.new do include(Aws::Record) integer_attr(:id, hash_key: true) string_attr(:name, range_key: true) string_attr(:message) end end let(:child_model) do Class.new(parent_model) do include(Aws::Record) string_attr(:foo) string_attr(:bar) end end it 'should have child model inherit secondary indexes from parent model' do parent_model.local_secondary_index(:local_index, hash_key: :id, range_key: :message) parent_model.global_secondary_index(:global_index, hash_key: :name, range_key: :message) expect(child_model.local_secondary_indexes).to eq(parent_model.local_secondary_indexes) expect(child_model.global_secondary_indexes).to eq(parent_model.global_secondary_indexes) end it 'allows the child model override parent indexes' do parent_model.local_secondary_index(:local_index, hash_key: :id, range_key: :message) parent_model.global_secondary_index(:global_index, hash_key: :name, range_key: :message) child_model.local_secondary_index(:local_index, hash_key: :id, range_key: :foo) child_model.global_secondary_index(:global_index, hash_key: :bar, range_key: :foo) expect(child_model.local_secondary_indexes).to eq(local_index: { hash_key: :id, range_key: :foo }) expect(child_model.global_secondary_indexes).to eq(global_index: { hash_key: :bar, range_key: :foo }) end end end end