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,114 +0,0 @@
|
|
1
|
-
RSpec.describe Rmodel::Sequel::Repository do
|
2
|
-
include_context 'clean sequel database'
|
3
|
-
|
4
|
-
before do
|
5
|
-
create_database
|
6
|
-
stub_const('Thing', Struct.new(:id, :a, :b))
|
7
|
-
stub_const('ThingRepository', Class.new(Rmodel::Sequel::Repository))
|
8
|
-
end
|
9
|
-
|
10
|
-
subject do
|
11
|
-
factory = Rmodel::Sequel::SimpleFactory.new(Thing, :a, :b)
|
12
|
-
ThingRepository.new(sequel_conn, :things, factory)
|
13
|
-
end
|
14
|
-
|
15
|
-
before do
|
16
|
-
subject.insert(Thing.new(nil, 2, 3))
|
17
|
-
subject.insert(Thing.new(nil, 2, 4))
|
18
|
-
subject.insert(Thing.new(nil, 5, 6))
|
19
|
-
end
|
20
|
-
|
21
|
-
describe '.scope' do
|
22
|
-
context 'when a scope w/o arguments is defined' do
|
23
|
-
before do
|
24
|
-
ThingRepository.class_eval do
|
25
|
-
scope :a_equals_2 do
|
26
|
-
where(a: 2)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'works!' do
|
32
|
-
expect(subject.query.a_equals_2.count).to eq 2
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'returns an array of instances of the appropriate class' do
|
36
|
-
expect(subject.query.a_equals_2.first).to be_an_instance_of Thing
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'when a scope w/ arguments is defined' do
|
41
|
-
before do
|
42
|
-
ThingRepository.class_eval do
|
43
|
-
scope :a_equals do |n|
|
44
|
-
where(a: n)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'works!' do
|
50
|
-
expect(subject.query.a_equals(2).count).to eq 2
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'when two scopes are defined and chained' do
|
55
|
-
before do
|
56
|
-
ThingRepository.class_eval do
|
57
|
-
scope :a_equals do |n|
|
58
|
-
where(a: n)
|
59
|
-
end
|
60
|
-
|
61
|
-
scope :b_equals do |n|
|
62
|
-
where(b: n)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'works!' do
|
68
|
-
expect(subject.query.a_equals(2).b_equals(4).count).to eq 1
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'when an unknown scope is used' do
|
73
|
-
it 'raises the NoMethodError' do
|
74
|
-
expect {
|
75
|
-
subject.query.something
|
76
|
-
}.to raise_error NoMethodError
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe '.query' do
|
82
|
-
describe '#remove' do
|
83
|
-
context 'when no scope is given' do
|
84
|
-
it 'removes all objects' do
|
85
|
-
subject.query.remove
|
86
|
-
expect(subject.query.count).to eq 0
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when the scope filters 2 objects from 3' do
|
91
|
-
before do
|
92
|
-
ThingRepository.class_eval do
|
93
|
-
scope :a_equals_2 do
|
94
|
-
where(a: 2)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'removes 2 objects' do
|
100
|
-
subject.query.a_equals_2.remove
|
101
|
-
expect(subject.query.count).to eq 1
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def create_database
|
108
|
-
sequel_conn.create_table(:things) do
|
109
|
-
primary_key :id
|
110
|
-
Integer :a
|
111
|
-
Integer :b
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,118 +0,0 @@
|
|
1
|
-
RSpec.describe Rmodel::Sequel::Repository do
|
2
|
-
before do
|
3
|
-
stub_const('Thing', Struct.new(:id, :name))
|
4
|
-
stub_const('ThingRepository', Class.new(Rmodel::Sequel::Repository))
|
5
|
-
ThingRepository.send :attr_reader, :client, :table, :factory
|
6
|
-
end
|
7
|
-
let(:factory) { Rmodel::Sequel::SimpleFactory.new(Thing, :name) }
|
8
|
-
|
9
|
-
describe '.client(name)' do
|
10
|
-
conn_options = { adapter: 'sqlite', database: 'rmodel_test.sqlite3' }
|
11
|
-
|
12
|
-
subject { ThingRepository.new(nil, :things, factory) }
|
13
|
-
|
14
|
-
context 'when it is called with an existent name' do
|
15
|
-
before do
|
16
|
-
Rmodel.setup do
|
17
|
-
client :not_default, conn_options
|
18
|
-
end
|
19
|
-
|
20
|
-
ThingRepository.class_eval do
|
21
|
-
client :not_default
|
22
|
-
end
|
23
|
-
end
|
24
|
-
after { Rmodel::setup.clear }
|
25
|
-
|
26
|
-
it 'sets the appropriate #client' do
|
27
|
-
expect(subject.client).to be_a_kind_of Sequel::Database
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'when it is called with a non-existent name' do
|
32
|
-
before do
|
33
|
-
ThingRepository.class_eval do
|
34
|
-
client :not_default
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'makes #initialize raise the ArgumentError' do
|
39
|
-
expect { subject }.to raise_error ArgumentError
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'when it is not called' do
|
44
|
-
context 'when the :default client is set' do
|
45
|
-
before do
|
46
|
-
Rmodel.setup do
|
47
|
-
client :default, conn_options
|
48
|
-
end
|
49
|
-
end
|
50
|
-
after { Rmodel::setup.clear }
|
51
|
-
|
52
|
-
it 'sets #client to be default' do
|
53
|
-
expect(subject.client).to be_a_kind_of Sequel::Database
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'when the :default client is not set' do
|
58
|
-
it 'makes #initialize raise the ArgumentError' do
|
59
|
-
expect { subject }.to raise_error ArgumentError
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe '.table(name)' do
|
66
|
-
subject { ThingRepository.new(Object.new, nil, factory) }
|
67
|
-
|
68
|
-
context 'when the :people table is given' do
|
69
|
-
before do
|
70
|
-
ThingRepository.class_eval do
|
71
|
-
table :people
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'uses the :people' do
|
76
|
-
expect(subject.table).to eq :people
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'when no table is given' do
|
81
|
-
it 'gets the right name by convention' do
|
82
|
-
expect(subject.table).to eq :things
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
describe '.simple_factory(klass, attribute1, attribute2, ...)' do
|
88
|
-
subject { ThingRepository.new(Object.new, :things) }
|
89
|
-
|
90
|
-
context 'when it is called' do
|
91
|
-
before do
|
92
|
-
ThingRepository.class_eval do
|
93
|
-
simple_factory Thing, :name, :email
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'sets the appropriate #factory' do
|
98
|
-
expect(subject.factory).to be_an_instance_of Rmodel::Sequel::SimpleFactory
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'when it is not called' do
|
103
|
-
it 'make #initialize raise an error' do
|
104
|
-
expect { subject }.to raise_error ArgumentError
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
describe '#initialize(client, collection, factory)' do
|
110
|
-
context 'when all constructor arguments are passed' do
|
111
|
-
it 'works!' do
|
112
|
-
expect {
|
113
|
-
ThingRepository.new(Object.new, :users, factory)
|
114
|
-
}.not_to raise_error
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
RSpec.describe Rmodel::Sequel::SimpleFactory do
|
2
|
-
context 'when the User(id, name, email) class is defined' do
|
3
|
-
before { stub_const('User', Struct.new(:id, :name, :email)) }
|
4
|
-
|
5
|
-
subject { described_class.new(User, :name, :email) }
|
6
|
-
|
7
|
-
describe '#fromHash' do
|
8
|
-
context 'when the hash with id, name and email is given' do
|
9
|
-
let(:hash) { { id: 1, name: 'John', email: 'john@example.com' } }
|
10
|
-
let(:result) { subject.fromHash(hash) }
|
11
|
-
|
12
|
-
it 'returns an instance of User' do
|
13
|
-
expect(result).to be_an_instance_of User
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'sets the attributes correctly' do
|
17
|
-
expect(result.name).to eq 'John'
|
18
|
-
expect(result.email).to eq 'john@example.com'
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'sets the User#id correctly' do
|
22
|
-
expect(result.id).to eq 1
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '#toHash' do
|
28
|
-
let(:user) { User.new(1, 'John', 'john@example.com') }
|
29
|
-
context 'when id_included is false' do
|
30
|
-
let(:result) { subject.toHash(user, false) }
|
31
|
-
|
32
|
-
it 'returns an instance of Hash' do
|
33
|
-
expect(result).to be_an_instance_of Hash
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'sets the keys correctly' do
|
37
|
-
expect(result[:name]).to eq 'John'
|
38
|
-
expect(result[:email]).to eq 'john@example.com'
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'has no the "id" key' do
|
42
|
-
expect(result.has_key?(:id)).to be false
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context 'when id_included is true' do
|
47
|
-
let(:result) { subject.toHash(user, true) }
|
48
|
-
|
49
|
-
it 'sets the "id" key' do
|
50
|
-
expect(result[:id]).to eq 1
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/spec/rmodel/setup_spec.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
RSpec.describe Rmodel do
|
2
|
-
describe '.setup' do
|
3
|
-
before { Rmodel::Setup.instance.clear }
|
4
|
-
context 'when no block is passed' do
|
5
|
-
it 'returns Rmodel::Setup.instance' do
|
6
|
-
expect(Rmodel.setup).to equal Rmodel::Setup.instance
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
context 'when the block is passed' do
|
11
|
-
let(:clients_config) { Rmodel::Setup.instance.instance_variable_get('@clients_config') }
|
12
|
-
|
13
|
-
it 'returns Rmodel::Setup.instance' do
|
14
|
-
expect(Rmodel.setup).to equal Rmodel::Setup.instance
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'runs setup methods within the block' do
|
18
|
-
Rmodel.setup do
|
19
|
-
client :default, {}
|
20
|
-
end
|
21
|
-
expect(clients_config[:default]).to eq({})
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe Rmodel::Setup do
|
27
|
-
subject { Rmodel::Setup.instance }
|
28
|
-
let(:clients_config) { subject.instance_variable_get('@clients_config') }
|
29
|
-
|
30
|
-
describe '#new' do
|
31
|
-
it 'raises the NoMethodError' do
|
32
|
-
expect { Rmodel::Setup.new }.to raise_error NoMethodError
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#client(name, config)' do
|
37
|
-
it 'makes config available via #clients[name]' do
|
38
|
-
subject.client :default, { host: 'localhost' }
|
39
|
-
expect(clients_config[:default]).to eq( host: 'localhost' )
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#clear' do
|
44
|
-
context 'when one client is set' do
|
45
|
-
before { subject.client :default, { host: 'localhost' } }
|
46
|
-
|
47
|
-
it 'removes all clients' do
|
48
|
-
subject.clear
|
49
|
-
expect(clients_config).to be_empty
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
RSpec.shared_examples 'sugarable repository' do
|
2
|
-
before do
|
3
|
-
stub_const('Thing', Struct.new(:id, :name))
|
4
|
-
end
|
5
|
-
|
6
|
-
describe '#find!' do
|
7
|
-
context 'when an existent id is given' do
|
8
|
-
before { subject.insert(Thing.new(1)) }
|
9
|
-
|
10
|
-
it 'returns the right instance' do
|
11
|
-
expect(subject.find!(1)).not_to be_nil
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'when a non-existent id is given' do
|
16
|
-
it 'raises NotFound' do
|
17
|
-
expect {
|
18
|
-
subject.find!(1)
|
19
|
-
}.to raise_error Rmodel::NotFound
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe 'save' do
|
25
|
-
let(:thing) { Thing.new }
|
26
|
-
|
27
|
-
context 'when a new object is given' do
|
28
|
-
it 'gets inserted' do
|
29
|
-
subject.save(thing)
|
30
|
-
expect(subject.find(thing.id)).not_to be_nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when an existent object is given' do
|
35
|
-
before { subject.insert(thing) }
|
36
|
-
|
37
|
-
it 'gets updated' do
|
38
|
-
thing.name = 'chair'
|
39
|
-
subject.save(thing)
|
40
|
-
expect(subject.find(thing.id).name).to eq 'chair'
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
RSpec.shared_examples 'timestampable repository' do
|
2
|
-
context 'when the entity object has attributes created_at and updated_at' do
|
3
|
-
before do
|
4
|
-
stub_const('Thing', Struct.new(:id, :name, :created_at, :updated_at))
|
5
|
-
end
|
6
|
-
|
7
|
-
subject { repo_w_timestamps }
|
8
|
-
|
9
|
-
context 'when we insert(object)' do
|
10
|
-
context 'and the object.created_at is already set' do
|
11
|
-
let(:thing) { Thing.new(nil, 'chair', Time.now) }
|
12
|
-
|
13
|
-
it 'doesnt change the value of created_at' do
|
14
|
-
set_created_at = thing.created_at
|
15
|
-
subject.insert(thing)
|
16
|
-
expect(thing.created_at).to eq set_created_at
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'and the object.created_at is not set yet' do
|
21
|
-
let(:thing) { Thing.new(nil, 'chair') }
|
22
|
-
|
23
|
-
it 'sets the value of created_at' do
|
24
|
-
subject.insert(thing)
|
25
|
-
expect(thing.created_at).not_to be_nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'when we update(object)' do
|
31
|
-
let(:thing) { Thing.new(nil, 'chair') }
|
32
|
-
before { subject.insert(thing) }
|
33
|
-
|
34
|
-
it 'sets the value of created_at' do
|
35
|
-
thing.name = 'table'
|
36
|
-
subject.update(thing)
|
37
|
-
expect(thing.updated_at).not_to be_nil
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'when the entity has no attributes :created_at and updated_at' do
|
43
|
-
before do
|
44
|
-
stub_const('Thing', Struct.new(:id, :name))
|
45
|
-
end
|
46
|
-
|
47
|
-
let(:thing) { Thing.new(nil, 'chair') }
|
48
|
-
subject { repo_wo_timestamps }
|
49
|
-
|
50
|
-
context 'when we insert(object)' do
|
51
|
-
it 'does nothing special' do
|
52
|
-
subject.insert(thing)
|
53
|
-
expect(thing.respond_to?(:created_at)).to be false
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'when we update(object)' do
|
58
|
-
before { subject.insert(thing) }
|
59
|
-
|
60
|
-
it 'does nothing special' do
|
61
|
-
thing.name = 'table'
|
62
|
-
subject.update(thing)
|
63
|
-
expect(thing.respond_to?(:updated_at)).to be false
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|