rmodel 0.4.0.dev → 1.0.0
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/.gitignore +1 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +4 -3
- data/README.md +119 -153
- data/Rakefile +1 -2
- data/examples/mongo_embedded.rb +27 -21
- data/examples/scopes.rb +28 -0
- data/examples/sql_repository.rb +14 -26
- data/examples/timestamps.rb +7 -10
- data/examples/webapp/models/task.rb +9 -0
- data/examples/webapp/repositories/task_repository.rb +14 -0
- data/examples/webapp/server.rb +25 -0
- data/examples/webapp/support/mappers.rb +11 -0
- data/examples/webapp/support/repositories.rb +12 -0
- data/examples/webapp/support/sources.rb +13 -0
- data/examples/webapp/views/index.erb +20 -0
- data/lib/rmodel.rb +11 -8
- data/lib/rmodel/array_mapper.rb +23 -0
- data/lib/rmodel/base_mapper.rb +56 -0
- data/lib/rmodel/dummy_mapper.rb +15 -0
- data/lib/rmodel/mongo/mapper.rb +11 -0
- data/lib/rmodel/mongo/source.rb +50 -0
- data/lib/rmodel/repository.rb +36 -0
- data/lib/rmodel/repository_ext/scopable.rb +44 -0
- data/lib/rmodel/repository_ext/sugarable.rb +35 -0
- data/lib/rmodel/repository_ext/timestampable.rb +29 -0
- data/lib/rmodel/scope.rb +31 -0
- data/lib/rmodel/sequel/mapper.rb +6 -0
- data/lib/rmodel/sequel/source.rb +43 -0
- data/lib/rmodel/uni_hash.rb +16 -0
- data/lib/rmodel/version.rb +1 -1
- data/rmodel.gemspec +9 -3
- data/spec/rmodel/array_mapper_spec.rb +43 -0
- data/spec/rmodel/mongo/mapper_spec.rb +154 -0
- data/spec/rmodel/mongo/repository_spec.rb +16 -37
- data/spec/rmodel/mongo/source_spec.rb +113 -0
- data/spec/rmodel/sequel/mapper_spec.rb +57 -0
- data/spec/rmodel/sequel/repository_spec.rb +27 -38
- data/spec/rmodel/sequel/source_spec.rb +121 -0
- data/spec/shared/base_mapper.rb +39 -0
- data/spec/shared/clean_moped.rb +6 -2
- data/spec/shared/clean_sequel.rb +1 -1
- data/spec/shared/{repository_ext → repository}/crud.rb +20 -14
- data/spec/shared/repository/initialization.rb +39 -0
- data/spec/shared/repository/scopable.rb +137 -0
- data/spec/shared/repository/sugarable.rb +67 -0
- data/spec/shared/repository/timestampable.rb +137 -0
- data/spec/spec_helper.rb +17 -18
- metadata +120 -54
- data/examples/advanced_creation_of_repository.rb +0 -15
- data/examples/user.rb +0 -48
- data/lib/rmodel/base/repository.rb +0 -12
- data/lib/rmodel/base/repository_ext/sugarable.rb +0 -17
- data/lib/rmodel/base/repository_ext/timestampable.rb +0 -19
- data/lib/rmodel/mongo/repository.rb +0 -62
- data/lib/rmodel/mongo/repository_ext/query.rb +0 -34
- data/lib/rmodel/mongo/repository_ext/queryable.rb +0 -34
- data/lib/rmodel/mongo/setup.rb +0 -17
- data/lib/rmodel/mongo/simple_factory.rb +0 -78
- data/lib/rmodel/sequel/repository.rb +0 -61
- data/lib/rmodel/sequel/repository_ext/query.rb +0 -34
- data/lib/rmodel/sequel/repository_ext/queryable.rb +0 -30
- data/lib/rmodel/sequel/setup.rb +0 -12
- data/lib/rmodel/sequel/simple_factory.rb +0 -28
- data/lib/rmodel/setup.rb +0 -34
- data/spec/rmodel/mongo/repository_ext/queryable_spec.rb +0 -103
- data/spec/rmodel/mongo/repository_initialize_spec.rb +0 -174
- data/spec/rmodel/mongo/simple_factory_spec.rb +0 -195
- data/spec/rmodel/sequel/repository_ext/queryable_spec.rb +0 -114
- data/spec/rmodel/sequel/repository_initialize_spec.rb +0 -118
- data/spec/rmodel/sequel/simple_factory_spec.rb +0 -55
- data/spec/rmodel/setup_spec.rb +0 -54
- data/spec/shared/repository_ext/sugarable.rb +0 -44
- data/spec/shared/repository_ext/timestampable.rb +0 -67
| @@ -1,50 +1,29 @@ | |
| 1 | 
            -
            RSpec.describe  | 
| 2 | 
            -
               | 
| 3 | 
            -
                include_context 'clean mongo database'
         | 
| 1 | 
            +
            RSpec.describe 'Repository with MongoDB' do
         | 
| 2 | 
            +
              include_context 'clean mongo database'
         | 
| 4 3 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
                 | 
| 4 | 
            +
              shared_examples 'definitions' do
         | 
| 5 | 
            +
                let(:source) { Rmodel::Mongo::Source.new(mongo_session, :things) }
         | 
| 6 | 
            +
                let(:mapper_klass) { Rmodel::Mongo::Mapper }
         | 
| 7 | 
            +
              end
         | 
| 8 8 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
                 | 
| 9 | 
            +
              it_behaves_like 'repository crud' do
         | 
| 10 | 
            +
                include_context 'definitions'
         | 
| 11 11 | 
             
                let(:unique_constraint_error) { Mongo::Error::OperationFailure }
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def insert_record(id, columns)
         | 
| 14 | 
            -
                  record = columns.dup
         | 
| 15 | 
            -
                  record['_id'] = id
         | 
| 16 | 
            -
                  mongo_session[:things].insert_one(record)
         | 
| 17 | 
            -
                end
         | 
| 18 12 | 
             
              end
         | 
| 19 13 |  | 
| 20 14 | 
             
              it_behaves_like 'sugarable repository' do
         | 
| 21 | 
            -
                include_context ' | 
| 22 | 
            -
             | 
| 23 | 
            -
                before do
         | 
| 24 | 
            -
                  stub_const('ThingRepository', Class.new(Rmodel::Mongo::Repository))
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                subject do
         | 
| 28 | 
            -
                  factory = Rmodel::Mongo::SimpleFactory.new(Thing, :name)
         | 
| 29 | 
            -
                  ThingRepository.new(mongo_session, :things, factory)
         | 
| 30 | 
            -
                end
         | 
| 15 | 
            +
                include_context 'definitions'
         | 
| 31 16 | 
             
              end
         | 
| 32 17 |  | 
| 33 18 | 
             
              it_behaves_like 'timestampable repository' do
         | 
| 34 | 
            -
                include_context ' | 
| 35 | 
            -
             | 
| 36 | 
            -
                before do
         | 
| 37 | 
            -
                  stub_const('ThingRepository', Class.new(Rmodel::Mongo::Repository))
         | 
| 38 | 
            -
                end
         | 
| 19 | 
            +
                include_context 'definitions'
         | 
| 20 | 
            +
              end
         | 
| 39 21 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                end
         | 
| 22 | 
            +
              it_behaves_like 'initialization' do
         | 
| 23 | 
            +
                include_context 'definitions'
         | 
| 24 | 
            +
              end
         | 
| 44 25 |  | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
                  ThingRepository.new(mongo_session, :things, factory)
         | 
| 48 | 
            -
                end
         | 
| 26 | 
            +
              it_behaves_like 'scopable repository' do
         | 
| 27 | 
            +
                include_context 'definitions'
         | 
| 49 28 | 
             
              end
         | 
| 50 29 | 
             
            end
         | 
| @@ -0,0 +1,113 @@ | |
| 1 | 
            +
            RSpec.describe Rmodel::Mongo::Source do
         | 
| 2 | 
            +
              include_context 'clean mongo database'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              subject { Rmodel::Mongo::Source.new(mongo_session, :things) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              describe '#initialize(connection, collection)'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe 'find(id)' do
         | 
| 9 | 
            +
                context 'when an existent id is given' do
         | 
| 10 | 
            +
                  before do
         | 
| 11 | 
            +
                    mongo_session[:things].insert_one('_id' => 1, 'name' => 'chair')
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  it 'returns the doc' do
         | 
| 15 | 
            +
                    doc = subject.find(1)
         | 
| 16 | 
            +
                    expect(doc['name']).to eq 'chair'
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                context 'when a non-existent id is given' do
         | 
| 21 | 
            +
                  it 'returns nil' do
         | 
| 22 | 
            +
                    expect(subject.find(1)).to be_nil
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe 'insert(doc)' do
         | 
| 28 | 
            +
                context 'when the _id is not set' do
         | 
| 29 | 
            +
                  let(:inserted_id) { subject.insert('name' => 'chair') }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  it 'returns the new _id' do
         | 
| 32 | 
            +
                    expect(inserted_id).not_to be_nil
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  it 'saves the doc' do
         | 
| 36 | 
            +
                    found = mongo_session[:things].find('_id' => inserted_id).first
         | 
| 37 | 
            +
                    expect(found['name']).to eq 'chair'
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                context 'when the _id is set' do
         | 
| 42 | 
            +
                  context 'when the _id is already occupied' do
         | 
| 43 | 
            +
                    before do
         | 
| 44 | 
            +
                      mongo_session[:things].insert_one('_id' => 1)
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    it 'throws the error' do
         | 
| 48 | 
            +
                      expect do
         | 
| 49 | 
            +
                        subject.insert('_id' => 1)
         | 
| 50 | 
            +
                      end.to raise_error Mongo::Error::OperationFailure
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  context 'when the _id is not occupied' do
         | 
| 55 | 
            +
                    it 'returns the same id' do
         | 
| 56 | 
            +
                      id = subject.insert('_id' => 1)
         | 
| 57 | 
            +
                      expect(id).to eq 1
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
              describe 'update(id, doc)' do
         | 
| 64 | 
            +
                before do
         | 
| 65 | 
            +
                  subject.insert('_id' => 1, 'name' => 'chair')
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                it 'updates the doc' do
         | 
| 69 | 
            +
                  subject.update(1, 'name' => 'table')
         | 
| 70 | 
            +
                  expect(subject.find(1)['name']).to eq 'table'
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              describe 'delete(id)' do
         | 
| 75 | 
            +
                before do
         | 
| 76 | 
            +
                  subject.insert('_id' => 1)
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                it 'deletes the doc' do
         | 
| 80 | 
            +
                  subject.delete(1)
         | 
| 81 | 
            +
                  expect(subject.find(1)).to be_nil
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              describe 'build_query' do
         | 
| 86 | 
            +
                it 'returns the object what includes methods of Origin::Queryable' do
         | 
| 87 | 
            +
                  expect(subject.build_query).to respond_to :aliases, :where, :group
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              describe 'exec_query(query)' do
         | 
| 92 | 
            +
                before do
         | 
| 93 | 
            +
                  3.times { subject.insert({}) }
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                it 'returns docs' do
         | 
| 97 | 
            +
                  docs = subject.exec_query(subject.build_query)
         | 
| 98 | 
            +
                  expect(docs.to_a.length).to eq 3
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
              end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              describe 'delete_by_query(query)' do
         | 
| 103 | 
            +
                before do
         | 
| 104 | 
            +
                  3.times { subject.insert({}) }
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                it 'deletes docs' do
         | 
| 108 | 
            +
                  subject.delete_by_query(subject.build_query)
         | 
| 109 | 
            +
                  found = subject.exec_query(subject.build_query)
         | 
| 110 | 
            +
                  expect(found.to_a).to be_empty
         | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
              end
         | 
| 113 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            RSpec.describe Rmodel::Sequel::Mapper do
         | 
| 2 | 
            +
              before do
         | 
| 3 | 
            +
                stub_const 'User', Struct.new(:id, :name, :age)
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              subject { described_class.new(User).define_attributes(:name, :age) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              describe '#deserialize(hash)' do
         | 
| 9 | 
            +
                it 'returns an instance of the appropriate class' do
         | 
| 10 | 
            +
                  expect(subject.deserialize({})).to be_an_instance_of User
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                it 'sets the attributes correctly' do
         | 
| 14 | 
            +
                  object = subject.deserialize(name: 'John', age: 20)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  expect(object.name).to eq 'John'
         | 
| 17 | 
            +
                  expect(object.age).to eq 20
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                context 'when _id is given' do
         | 
| 21 | 
            +
                  it 'sets the #id correctly' do
         | 
| 22 | 
            +
                    object = subject.deserialize(id: 1)
         | 
| 23 | 
            +
                    expect(object.id).to eq 1
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              describe '#serialize(object, id_included)' do
         | 
| 29 | 
            +
                it 'returns an instance of Hash' do
         | 
| 30 | 
            +
                  hash = subject.serialize(User.new(1, 'John', 20), true)
         | 
| 31 | 
            +
                  expect(hash).to be_an_instance_of Hash
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                it 'sets the keys correctly' do
         | 
| 35 | 
            +
                  hash = subject.serialize(User.new(1, 'John', 20), true)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  expect(hash[:name]).to eq 'John'
         | 
| 38 | 
            +
                  expect(hash[:age]).to eq 20
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                context 'when id_included = true' do
         | 
| 42 | 
            +
                  it 'sets the id' do
         | 
| 43 | 
            +
                    hash = subject.serialize(User.new(1), true)
         | 
| 44 | 
            +
                    expect(hash[:id]).to eq 1
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                context 'when id_included = false' do
         | 
| 49 | 
            +
                  it 'doesnt set the id' do
         | 
| 50 | 
            +
                    hash = subject.serialize(User.new(1), false)
         | 
| 51 | 
            +
                    expect(hash.key?(:id)).to be false
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              it_behaves_like 'base mapper'
         | 
| 57 | 
            +
            end
         | 
| @@ -1,53 +1,42 @@ | |
| 1 | 
            -
            RSpec.describe  | 
| 2 | 
            -
               | 
| 3 | 
            -
                include_examples 'clean sequel database'
         | 
| 1 | 
            +
            RSpec.describe 'Repository with Sequel' do
         | 
| 2 | 
            +
              include_examples 'clean sequel database'
         | 
| 4 3 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 4 | 
            +
              shared_examples 'definitions' do
         | 
| 5 | 
            +
                let(:source) { Rmodel::Sequel::Source.new(sequel_conn, :things) }
         | 
| 6 | 
            +
                let(:mapper_klass) { Rmodel::Sequel::Mapper }
         | 
| 7 | 
            +
              end
         | 
| 9 8 |  | 
| 10 | 
            -
             | 
| 11 | 
            -
                 | 
| 12 | 
            -
                let(:unique_constraint_error) { Sequel::UniqueConstraintViolation }
         | 
| 9 | 
            +
              it_behaves_like 'repository crud' do
         | 
| 10 | 
            +
                before { create_database }
         | 
| 13 11 |  | 
| 14 | 
            -
                 | 
| 15 | 
            -
             | 
| 16 | 
            -
                  record[:id] = id
         | 
| 17 | 
            -
                  sequel_conn[:things].insert(record)
         | 
| 18 | 
            -
                end
         | 
| 12 | 
            +
                include_context 'definitions'
         | 
| 13 | 
            +
                let(:unique_constraint_error) { Sequel::UniqueConstraintViolation }
         | 
| 19 14 | 
             
              end
         | 
| 20 15 |  | 
| 21 16 | 
             
              it_behaves_like 'sugarable repository' do
         | 
| 22 | 
            -
                 | 
| 23 | 
            -
             | 
| 24 | 
            -
                before do
         | 
| 25 | 
            -
                  create_database
         | 
| 26 | 
            -
                  stub_const('ThingRepository', Class.new(Rmodel::Sequel::Repository))
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                subject do
         | 
| 30 | 
            -
                  factory = Rmodel::Sequel::SimpleFactory.new(Thing, :name)
         | 
| 31 | 
            -
                  ThingRepository.new(sequel_conn, :things, factory)
         | 
| 32 | 
            -
                end
         | 
| 17 | 
            +
                before { create_database }
         | 
| 18 | 
            +
                include_context 'definitions'
         | 
| 33 19 | 
             
              end
         | 
| 34 20 |  | 
| 35 21 | 
             
              it_behaves_like 'timestampable repository' do
         | 
| 36 | 
            -
                 | 
| 22 | 
            +
                before { create_database(true) }
         | 
| 23 | 
            +
                include_context 'definitions'
         | 
| 24 | 
            +
              end
         | 
| 37 25 |  | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 26 | 
            +
              it_behaves_like 'initialization' do
         | 
| 27 | 
            +
                before { create_database(true) }
         | 
| 28 | 
            +
                include_context 'definitions'
         | 
| 29 | 
            +
              end
         | 
| 42 30 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
                  ThingRepository.new(sequel_conn, :things, factory)
         | 
| 46 | 
            -
                end
         | 
| 31 | 
            +
              it_behaves_like 'scopable repository' do
         | 
| 32 | 
            +
                include_context 'definitions'
         | 
| 47 33 |  | 
| 48 | 
            -
                 | 
| 49 | 
            -
                   | 
| 50 | 
            -
             | 
| 34 | 
            +
                def create_database
         | 
| 35 | 
            +
                  sequel_conn.create_table(:things) do
         | 
| 36 | 
            +
                    primary_key :id
         | 
| 37 | 
            +
                    Integer :a
         | 
| 38 | 
            +
                    Integer :b
         | 
| 39 | 
            +
                  end
         | 
| 51 40 | 
             
                end
         | 
| 52 41 | 
             
              end
         | 
| 53 42 |  | 
| @@ -0,0 +1,121 @@ | |
| 1 | 
            +
            RSpec.describe Rmodel::Sequel::Source do
         | 
| 2 | 
            +
              include_context 'clean sequel database'
         | 
| 3 | 
            +
              before { create_database }
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              subject { Rmodel::Sequel::Source.new(sequel_conn, :things) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              describe '#initialize(connection, table)'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              describe 'find(id)' do
         | 
| 10 | 
            +
                context 'when an existent id is given' do
         | 
| 11 | 
            +
                  before do
         | 
| 12 | 
            +
                    sequel_conn[:things].insert(id: 1, name: 'chair')
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  it 'returns the tuple' do
         | 
| 16 | 
            +
                    tuple = subject.find(1)
         | 
| 17 | 
            +
                    expect(tuple[:name]).to eq 'chair'
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                context 'when a non-existent id is given' do
         | 
| 22 | 
            +
                  it 'returns nil' do
         | 
| 23 | 
            +
                    expect(subject.find(1)).to be_nil
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              describe 'insert(tuple)' do
         | 
| 29 | 
            +
                context 'when the id is not set' do
         | 
| 30 | 
            +
                  let(:inserted_id) { subject.insert(name: 'chair') }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  it 'returns the new id' do
         | 
| 33 | 
            +
                    expect(inserted_id).not_to be_nil
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  it 'saves the tuple' do
         | 
| 37 | 
            +
                    found = sequel_conn[:things].where(id: inserted_id).first
         | 
| 38 | 
            +
                    expect(found[:name]).to eq 'chair'
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                context 'when the id is set' do
         | 
| 43 | 
            +
                  context 'when the id is already occupied' do
         | 
| 44 | 
            +
                    before do
         | 
| 45 | 
            +
                      sequel_conn[:things].insert(id: 1)
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    it 'throws the error' do
         | 
| 49 | 
            +
                      expect do
         | 
| 50 | 
            +
                        subject.insert(id: 1)
         | 
| 51 | 
            +
                      end.to raise_error Sequel::UniqueConstraintViolation
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  context 'when the id is not occupied' do
         | 
| 56 | 
            +
                    it 'returns the same id' do
         | 
| 57 | 
            +
                      id = subject.insert(id: 1)
         | 
| 58 | 
            +
                      expect(id).to eq 1
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              describe 'update(id, doc)' do
         | 
| 65 | 
            +
                before do
         | 
| 66 | 
            +
                  subject.insert(id: 1, name: 'chair')
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                it 'updates the doc' do
         | 
| 70 | 
            +
                  subject.update(1, name: 'table')
         | 
| 71 | 
            +
                  expect(subject.find(1)[:name]).to eq 'table'
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              describe 'delete(id)' do
         | 
| 76 | 
            +
                before do
         | 
| 77 | 
            +
                  subject.insert(id: 1)
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                it 'deletes the doc' do
         | 
| 81 | 
            +
                  subject.delete(1)
         | 
| 82 | 
            +
                  expect(subject.find(1)).to be_nil
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
              describe 'build_query' do
         | 
| 87 | 
            +
                it 'returns the instance of Sequel::Dataset' do
         | 
| 88 | 
            +
                  expect(subject.build_query).to be_a_kind_of Sequel::Dataset
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              describe 'exec_query(query)' do
         | 
| 93 | 
            +
                before do
         | 
| 94 | 
            +
                  3.times { subject.insert({}) }
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                it 'returns tuples' do
         | 
| 98 | 
            +
                  docs = subject.exec_query(subject.build_query)
         | 
| 99 | 
            +
                  expect(docs.to_a.length).to eq 3
         | 
| 100 | 
            +
                end
         | 
| 101 | 
            +
              end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
              describe 'delete_by_query(query)' do
         | 
| 104 | 
            +
                before do
         | 
| 105 | 
            +
                  3.times { subject.insert({}) }
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                it 'deletes tuples' do
         | 
| 109 | 
            +
                  subject.delete_by_query(subject.build_query)
         | 
| 110 | 
            +
                  found = subject.exec_query(subject.build_query)
         | 
| 111 | 
            +
                  expect(found.to_a).to be_empty
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              def create_database
         | 
| 116 | 
            +
                sequel_conn.create_table(:things) do
         | 
| 117 | 
            +
                  primary_key :id
         | 
| 118 | 
            +
                  String :name
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require 'active_support/hash_with_indifferent_access'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.shared_examples 'base mapper' do
         | 
| 4 | 
            +
              describe '#initialize' do
         | 
| 5 | 
            +
                context 'when the Thing model is given' do
         | 
| 6 | 
            +
                  before { stub_const 'Thing', Class.new }
         | 
| 7 | 
            +
                  subject { described_class.new(Thing) }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  it 'creates instances of Thing' do
         | 
| 10 | 
            +
                    expect(subject.deserialize({})).to be_instance_of Thing
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe '#define_timestamps' do
         | 
| 16 | 
            +
                context 'on serialization' do
         | 
| 17 | 
            +
                  before do
         | 
| 18 | 
            +
                    stub_const 'Thing', Struct.new(:created_at, :updated_at)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  subject { described_class.new(Thing).define_timestamps }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  let(:thing) { Thing.new(Time.now, Time.now) }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  let(:serialized) do
         | 
| 26 | 
            +
                    hash = subject.serialize(thing, false)
         | 
| 27 | 
            +
                    ActiveSupport::HashWithIndifferentAccess.new(hash)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  it 'adds created_at to a hash' do
         | 
| 31 | 
            +
                    expect(serialized).to have_key(:created_at)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  it 'adds updated_at to a hash' do
         | 
| 35 | 
            +
                    expect(serialized).to have_key(:updated_at)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         |