rmodel 0.4.0.dev → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|