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
 
    
        data/spec/shared/clean_moped.rb
    CHANGED
    
    | 
         @@ -1,10 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            RSpec.shared_context 'clean mongo database' do
         
     | 
| 
       2 
     | 
    
         
            -
              let(:mongo_session) {  
     | 
| 
      
 2 
     | 
    
         
            +
              let(:mongo_session) { create_connection }
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
              before(:all) do
         
     | 
| 
       5 
5 
     | 
    
         
             
                Mongo::Logger.logger.level = Logger::ERROR
         
     | 
| 
       6 
     | 
    
         
            -
                mongo_session =  
     | 
| 
      
 6 
     | 
    
         
            +
                mongo_session = create_connection
         
     | 
| 
       7 
7 
     | 
    
         
             
                mongo_session.database.drop
         
     | 
| 
       8 
8 
     | 
    
         
             
              end
         
     | 
| 
       9 
9 
     | 
    
         
             
              after { mongo_session.database.drop }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def create_connection
         
     | 
| 
      
 12 
     | 
    
         
            +
                Mongo::Client.new(['127.0.0.1:27017'], database: 'rmodel_test')
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
       10 
14 
     | 
    
         
             
            end
         
     | 
    
        data/spec/shared/clean_sequel.rb
    CHANGED
    
    
| 
         @@ -1,10 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            RSpec.shared_examples 'repository crud' do
         
     | 
| 
       2 
     | 
    
         
            -
              before  
     | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
      
 2 
     | 
    
         
            +
              before { stub_const('Thing', Struct.new(:id, :name)) }
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              let(:mapper) { mapper_klass.new(Thing).define_attributes(:name) }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              subject { Rmodel::Repository.new(source, mapper) }
         
     | 
| 
       5 
7 
     | 
    
         | 
| 
       6 
8 
     | 
    
         
             
              describe '#find' do
         
     | 
| 
       7 
     | 
    
         
            -
                before {  
     | 
| 
      
 9 
     | 
    
         
            +
                before { subject.insert_one(Thing.new(1, 'chair')) }
         
     | 
| 
       8 
10 
     | 
    
         | 
| 
       9 
11 
     | 
    
         
             
                context 'when an existent id is given' do
         
     | 
| 
       10 
12 
     | 
    
         
             
                  it 'returns the instance of correct type' do
         
     | 
| 
         @@ -23,36 +25,39 @@ RSpec.shared_examples 'repository crud' do 
     | 
|
| 
       23 
25 
     | 
    
         
             
                end
         
     | 
| 
       24 
26 
     | 
    
         
             
              end
         
     | 
| 
       25 
27 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
              describe '# 
     | 
| 
      
 28 
     | 
    
         
            +
              describe '#insert_one(object)' do
         
     | 
| 
       27 
29 
     | 
    
         
             
                context 'when the id is not provided' do
         
     | 
| 
       28 
30 
     | 
    
         
             
                  let(:thing) { Thing.new(nil, 'chair') }
         
     | 
| 
       29 
31 
     | 
    
         | 
| 
      
 32 
     | 
    
         
            +
                  before { subject.insert_one(thing) }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       30 
34 
     | 
    
         
             
                  it 'sets the id before insert' do
         
     | 
| 
       31 
     | 
    
         
            -
                    subject.insert(thing)
         
     | 
| 
       32 
35 
     | 
    
         
             
                    expect(thing.id).not_to be_nil
         
     | 
| 
       33 
36 
     | 
    
         
             
                  end
         
     | 
| 
       34 
37 
     | 
    
         | 
| 
       35 
38 
     | 
    
         
             
                  it 'persists the object' do
         
     | 
| 
       36 
     | 
    
         
            -
                    subject.insert(thing)
         
     | 
| 
       37 
39 
     | 
    
         
             
                    expect(subject.find(thing.id).name).to eq 'chair'
         
     | 
| 
       38 
40 
     | 
    
         
             
                  end
         
     | 
| 
       39 
41 
     | 
    
         
             
                end
         
     | 
| 
       40 
42 
     | 
    
         | 
| 
       41 
43 
     | 
    
         
             
                context 'when the id is provided' do
         
     | 
| 
       42 
     | 
    
         
            -
                  let(:thing) { Thing.new(1000 
     | 
| 
      
 44 
     | 
    
         
            +
                  let(:thing) { Thing.new(1000) }
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
       44 
46 
     | 
    
         
             
                  it 'uses the existent id' do
         
     | 
| 
       45 
     | 
    
         
            -
                    subject. 
     | 
| 
      
 47 
     | 
    
         
            +
                    subject.insert_one(thing)
         
     | 
| 
       46 
48 
     | 
    
         
             
                    expect(thing.id).to eq 1000
         
     | 
| 
       47 
49 
     | 
    
         
             
                  end
         
     | 
| 
       48 
50 
     | 
    
         
             
                end
         
     | 
| 
       49 
51 
     | 
    
         | 
| 
       50 
52 
     | 
    
         
             
                context 'when the given id already exists' do
         
     | 
| 
       51 
53 
     | 
    
         
             
                  let(:thing) { Thing.new }
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  before { subject.insert_one(thing) }
         
     | 
| 
       53 
56 
     | 
    
         | 
| 
       54 
57 
     | 
    
         
             
                  it 'raises the error' do
         
     | 
| 
       55 
     | 
    
         
            -
                    expect  
     | 
| 
      
 58 
     | 
    
         
            +
                    expect do
         
     | 
| 
      
 59 
     | 
    
         
            +
                      subject.insert_one(thing)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end.to raise_error unique_constraint_error
         
     | 
| 
       56 
61 
     | 
    
         
             
                  end
         
     | 
| 
       57 
62 
     | 
    
         
             
                end
         
     | 
| 
       58 
63 
     | 
    
         
             
              end
         
     | 
| 
         @@ -71,12 +76,13 @@ RSpec.shared_examples 'repository crud' do 
     | 
|
| 
       71 
76 
     | 
    
         
             
                end
         
     | 
| 
       72 
77 
     | 
    
         
             
              end
         
     | 
| 
       73 
78 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
              describe '# 
     | 
| 
      
 79 
     | 
    
         
            +
              describe '#destroy' do
         
     | 
| 
       75 
80 
     | 
    
         
             
                let(:thing) { Thing.new }
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       76 
82 
     | 
    
         
             
                before { subject.insert(thing) }
         
     | 
| 
       77 
83 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                it ' 
     | 
| 
       79 
     | 
    
         
            -
                  subject. 
     | 
| 
      
 84 
     | 
    
         
            +
                it 'destroys the record' do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  subject.destroy(thing)
         
     | 
| 
       80 
86 
     | 
    
         
             
                  expect(subject.find(thing.id)).to be_nil
         
     | 
| 
       81 
87 
     | 
    
         
             
                end
         
     | 
| 
       82 
88 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec.shared_examples 'initialization' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              before do
         
     | 
| 
      
 3 
     | 
    
         
            +
                stub_const 'Thing', Struct.new(:id, :name)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                stub_const 'ThingRepository', Class.new(Rmodel::Repository)
         
     | 
| 
      
 6 
     | 
    
         
            +
                class ThingRepository
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :source, :mapper
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              let(:source) { Object.new }
         
     | 
| 
      
 12 
     | 
    
         
            +
              let(:mapper) { mapper_klass.new(Thing).define_attributes(:name) }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              describe '#initialize(source, collection, mapper)' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                context 'when all constructor arguments are passed' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  it 'works!' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    expect do
         
     | 
| 
      
 18 
     | 
    
         
            +
                      ThingRepository.new(source, mapper)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end.not_to raise_error
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                context 'when source is nil' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  it 'raises the error' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                    expect do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      ThingRepository.new(nil, mapper)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end.to raise_error(ArgumentError)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                context 'when mapper is nil' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  it 'raises the error' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect do
         
     | 
| 
      
 34 
     | 
    
         
            +
                      ThingRepository.new(source, nil)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end.to raise_error(ArgumentError)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,137 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec.shared_examples 'scopable repository' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              before do
         
     | 
| 
      
 3 
     | 
    
         
            +
                stub_const 'Thing', Struct.new(:id, :a, :b)
         
     | 
| 
      
 4 
     | 
    
         
            +
                stub_const 'ThingRepository', Class.new(Rmodel::Repository)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # Use the same scope syntax for Mongo and Sequel
         
     | 
| 
      
 7 
     | 
    
         
            +
                class ThingRepository
         
     | 
| 
      
 8 
     | 
    
         
            +
                  scope :a_equals_2 do
         
     | 
| 
      
 9 
     | 
    
         
            +
                    where(a: 2)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  scope :a_equals do |n|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    where(a: n)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  scope :b_equals do |n|
         
     | 
| 
      
 17 
     | 
    
         
            +
                    where(b: n)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              let(:mapper) { mapper_klass.new(Thing).define_attributes(:a, :b) }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              subject { ThingRepository.new(source, mapper) }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              before do
         
     | 
| 
      
 27 
     | 
    
         
            +
                create_database if defined?(create_database)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                subject.insert(Thing.new(nil, 2, 3))
         
     | 
| 
      
 30 
     | 
    
         
            +
                subject.insert(Thing.new(nil, 2, 4))
         
     | 
| 
      
 31 
     | 
    
         
            +
                subject.insert(Thing.new(nil, 5, 6))
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              describe '.scope' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                context 'when a scope w/o arguments is defined' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                  it 'works!' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                    expect(subject.fetch.a_equals_2.count).to eq 2
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  it 'returns an array of instances of the appropriate class' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                    expect(subject.fetch.a_equals_2.first).to be_an_instance_of Thing
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                context 'when a scope w/ arguments is defined' do
         
     | 
| 
      
 46 
     | 
    
         
            +
                  it 'works!' do
         
     | 
| 
      
 47 
     | 
    
         
            +
                    expect(subject.fetch.a_equals(2).count).to eq 2
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                context 'when two scopes are defined and chained' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  it 'works!' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    expect(subject.fetch.a_equals(2).b_equals(4).count).to eq 1
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                context 'when an unknown scope is used' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  it 'raises the NoMethodError' do
         
     | 
| 
      
 59 
     | 
    
         
            +
                    expect { subject.fetch.something }.to raise_error NoMethodError
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              describe '#fetch' do
         
     | 
| 
      
 65 
     | 
    
         
            +
                describe '#delete_all' do
         
     | 
| 
      
 66 
     | 
    
         
            +
                  context 'when no scope is given' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                    it 'removes all objects' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                      subject.fetch.delete_all
         
     | 
| 
      
 69 
     | 
    
         
            +
                      expect(subject.fetch.count).to eq 0
         
     | 
| 
      
 70 
     | 
    
         
            +
                    end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  context 'when the scope filters 2 objects from 3' do
         
     | 
| 
      
 74 
     | 
    
         
            +
                    it 'removes 2 objects' do
         
     | 
| 
      
 75 
     | 
    
         
            +
                      subject.fetch.a_equals_2.delete_all
         
     | 
| 
      
 76 
     | 
    
         
            +
                      expect(subject.fetch.count).to eq 1
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                describe '#destroy_all' do
         
     | 
| 
      
 82 
     | 
    
         
            +
                  context 'when no scope is given' do
         
     | 
| 
      
 83 
     | 
    
         
            +
                    it 'destroys all objects' do
         
     | 
| 
      
 84 
     | 
    
         
            +
                      subject.fetch.destroy_all
         
     | 
| 
      
 85 
     | 
    
         
            +
                      expect(subject.fetch.count).to eq 0
         
     | 
| 
      
 86 
     | 
    
         
            +
                    end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    it 'calls #destroy for each object' do
         
     | 
| 
      
 89 
     | 
    
         
            +
                      expect(subject).to receive(:destroy).exactly(3).times
         
     | 
| 
      
 90 
     | 
    
         
            +
                      subject.fetch.destroy_all
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  context 'when the scope filters 2 objects from 3' do
         
     | 
| 
      
 95 
     | 
    
         
            +
                    it 'destroys 2 objects' do
         
     | 
| 
      
 96 
     | 
    
         
            +
                      subject.fetch.a_equals_2.destroy_all
         
     | 
| 
      
 97 
     | 
    
         
            +
                      expect(subject.fetch.count).to eq 1
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    it 'calls #destroy for each object' do
         
     | 
| 
      
 101 
     | 
    
         
            +
                      expect(subject).to receive(:destroy).exactly(2).times
         
     | 
| 
      
 102 
     | 
    
         
            +
                      subject.fetch.a_equals_2.destroy_all
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
              end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
              describe '#all' do
         
     | 
| 
      
 109 
     | 
    
         
            +
                it 'gets all objects' do
         
     | 
| 
      
 110 
     | 
    
         
            +
                  objects = subject.all
         
     | 
| 
      
 111 
     | 
    
         
            +
                  expect(objects.length).to eq 3
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              describe '#delete_all' do
         
     | 
| 
      
 116 
     | 
    
         
            +
                context 'when no scope is given' do
         
     | 
| 
      
 117 
     | 
    
         
            +
                  it 'deletes all objects' do
         
     | 
| 
      
 118 
     | 
    
         
            +
                    subject.delete_all
         
     | 
| 
      
 119 
     | 
    
         
            +
                    expect(subject.fetch.count).to eq 0
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              describe '#destroy_all' do
         
     | 
| 
      
 125 
     | 
    
         
            +
                context 'when no scope is given' do
         
     | 
| 
      
 126 
     | 
    
         
            +
                  it 'deletes all objects' do
         
     | 
| 
      
 127 
     | 
    
         
            +
                    subject.destroy_all
         
     | 
| 
      
 128 
     | 
    
         
            +
                    expect(subject.fetch.count).to eq 0
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  it 'calls #destroy for each object' do
         
     | 
| 
      
 132 
     | 
    
         
            +
                    expect(subject).to receive(:destroy).exactly(3).times
         
     | 
| 
      
 133 
     | 
    
         
            +
                    subject.destroy_all
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec.shared_examples 'sugarable repository' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              before { stub_const('Thing', Struct.new(:id, :name)) }
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              let(:mapper) { mapper_klass.new(Thing).define_attributes(:name) }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              subject { Rmodel::Repository.new(source, mapper) }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              describe '#find!(id)' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                context 'when an existent id is given' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  before { subject.insert(Thing.new(1)) }
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  it 'returns the right instance' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                    expect(subject.find!(1)).not_to be_nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                context 'when a non-existent id is given' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  it 'raises NotFound' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    expect { subject.find!(1) }.to raise_error Rmodel::NotFound
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              describe '#insert(object1, object2, ...)' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                context 'when one object is provided' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                  it 'inserts one object' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                    subject.insert(Thing.new)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    expect(subject.fetch.count).to eq 1
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                context 'when an array of objects is provided' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  it 'inserts all objects' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                    subject.insert([Thing.new, Thing.new])
         
     | 
| 
      
 35 
     | 
    
         
            +
                    expect(subject.fetch.count).to eq 2
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                context 'when objects are provided as many arguments' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  it 'inserts all objects' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                    subject.insert(Thing.new, Thing.new)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    expect(subject.fetch.count).to eq 2
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              describe 'save' do
         
     | 
| 
      
 48 
     | 
    
         
            +
                let(:thing) { Thing.new }
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                context 'when a new object is given' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  it 'gets inserted' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                    subject.save(thing)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    expect(subject.find(thing.id)).not_to be_nil
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                context 'when an existent object is given' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  before { subject.insert(thing) }
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  it 'gets updated' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                    thing.name = 'chair'
         
     | 
| 
      
 62 
     | 
    
         
            +
                    subject.save(thing)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    expect(subject.find(thing.id).name).to eq 'chair'
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,137 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec.shared_examples 'timestampable repository' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              let(:mapper) { mapper_klass.new(Thing).define_attribute(:name) }
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              subject { Rmodel::Repository.new(source, mapper) }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              context 'when the entity object has timestamp attributes' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                before do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  stub_const('Thing', Struct.new(:id, :name, :created_at, :updated_at))
         
     | 
| 
      
 9 
     | 
    
         
            +
                  mapper.define_attributes(:created_at, :updated_at)
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                context 'when we insert(object)' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  context 'and created_at is already set' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                    let(:thing) { Thing.new(nil, 'chair', Time.now) }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    it "doesn't change the value of created_at" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                      set_created_at = thing.created_at
         
     | 
| 
      
 18 
     | 
    
         
            +
                      subject.insert(thing)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      expect(thing.created_at).to eq set_created_at
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  context 'and created_at is not set yet' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    let(:thing) { Thing.new }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    before { subject.insert(thing) }
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    it 'sets the value of created_at' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                      expect(thing.created_at).not_to be_nil
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    it 'saves created_at in the database' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                      expect(subject.find(thing.id).created_at).not_to be_nil
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                context 'when we update(object)' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                  let(:thing) { Thing.new }
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 42 
     | 
    
         
            +
                    subject.insert(thing)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    thing.name = 'chair'
         
     | 
| 
      
 44 
     | 
    
         
            +
                    subject.update(thing)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  it 'sets the value of updated_at' do
         
     | 
| 
      
 48 
     | 
    
         
            +
                    expect(thing.updated_at).not_to be_nil
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  it 'saves the updated_at in a database' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                    expect(subject.find(thing.id).updated_at).not_to be_nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                context 'when the Time.current method exists' do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  let(:thing) { Thing.new }
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 60 
     | 
    
         
            +
                    stub_const 'Time', Time
         
     | 
| 
      
 61 
     | 
    
         
            +
                    def Time.current
         
     | 
| 
      
 62 
     | 
    
         
            +
                      now
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
                    allow(Time).to receive(:current)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  context 'on insert' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                    before { subject.insert(thing) }
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    it 'calls Time.current' do
         
     | 
| 
      
 71 
     | 
    
         
            +
                      expect(Time).to have_received(:current)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                  context 'on update' do
         
     | 
| 
      
 76 
     | 
    
         
            +
                    before do
         
     | 
| 
      
 77 
     | 
    
         
            +
                      subject.insert(thing)
         
     | 
| 
      
 78 
     | 
    
         
            +
                      subject.update(thing)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                    it 'calls Time.current' do
         
     | 
| 
      
 82 
     | 
    
         
            +
                      expect(Time).to have_received(:current).twice
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              context 'when the entity has no attributes created_at and updated_at' do
         
     | 
| 
      
 89 
     | 
    
         
            +
                before { stub_const 'Thing', Struct.new(:id, :name) }
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                let(:thing) { Thing.new }
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                it "doesn't raise errors" do
         
     | 
| 
      
 94 
     | 
    
         
            +
                  expect do
         
     | 
| 
      
 95 
     | 
    
         
            +
                    subject.insert(thing)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    thing.name = 'chair'
         
     | 
| 
      
 97 
     | 
    
         
            +
                    subject.update(thing)
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end.not_to raise_error
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              context 'when the repo class is inherited' do
         
     | 
| 
      
 103 
     | 
    
         
            +
                before do
         
     | 
| 
      
 104 
     | 
    
         
            +
                  stub_const('Thing', Struct.new(:id, :name, :created_at, :updated_at))
         
     | 
| 
      
 105 
     | 
    
         
            +
                  mapper.define_attributes(:created_at, :updated_at)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  stub_const 'ThingRepository', Class.new(Rmodel::Repository)
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                subject { ThingRepository.new(source, mapper) }
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                context 'on insert' do
         
     | 
| 
      
 112 
     | 
    
         
            +
                  let(:thing) { Thing.new }
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                  before { subject.insert(thing) }
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  it 'sets the created_at' do
         
     | 
| 
      
 117 
     | 
    
         
            +
                    found = subject.find(thing.id)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    expect(found.created_at).not_to be_nil
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                context 'on update' do
         
     | 
| 
      
 123 
     | 
    
         
            +
                  let(:thing) { Thing.new }
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 126 
     | 
    
         
            +
                    subject.insert(thing)
         
     | 
| 
      
 127 
     | 
    
         
            +
                    thing.name = 'chair'
         
     | 
| 
      
 128 
     | 
    
         
            +
                    subject.update(thing)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  it 'sets the updated_at' do
         
     | 
| 
      
 132 
     | 
    
         
            +
                    found = subject.find(thing.id)
         
     | 
| 
      
 133 
     | 
    
         
            +
                    expect(found.updated_at).not_to be_nil
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
            end
         
     |