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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +4 -0
  4. data/.travis.yml +4 -3
  5. data/README.md +119 -153
  6. data/Rakefile +1 -2
  7. data/examples/mongo_embedded.rb +27 -21
  8. data/examples/scopes.rb +28 -0
  9. data/examples/sql_repository.rb +14 -26
  10. data/examples/timestamps.rb +7 -10
  11. data/examples/webapp/models/task.rb +9 -0
  12. data/examples/webapp/repositories/task_repository.rb +14 -0
  13. data/examples/webapp/server.rb +25 -0
  14. data/examples/webapp/support/mappers.rb +11 -0
  15. data/examples/webapp/support/repositories.rb +12 -0
  16. data/examples/webapp/support/sources.rb +13 -0
  17. data/examples/webapp/views/index.erb +20 -0
  18. data/lib/rmodel.rb +11 -8
  19. data/lib/rmodel/array_mapper.rb +23 -0
  20. data/lib/rmodel/base_mapper.rb +56 -0
  21. data/lib/rmodel/dummy_mapper.rb +15 -0
  22. data/lib/rmodel/mongo/mapper.rb +11 -0
  23. data/lib/rmodel/mongo/source.rb +50 -0
  24. data/lib/rmodel/repository.rb +36 -0
  25. data/lib/rmodel/repository_ext/scopable.rb +44 -0
  26. data/lib/rmodel/repository_ext/sugarable.rb +35 -0
  27. data/lib/rmodel/repository_ext/timestampable.rb +29 -0
  28. data/lib/rmodel/scope.rb +31 -0
  29. data/lib/rmodel/sequel/mapper.rb +6 -0
  30. data/lib/rmodel/sequel/source.rb +43 -0
  31. data/lib/rmodel/uni_hash.rb +16 -0
  32. data/lib/rmodel/version.rb +1 -1
  33. data/rmodel.gemspec +9 -3
  34. data/spec/rmodel/array_mapper_spec.rb +43 -0
  35. data/spec/rmodel/mongo/mapper_spec.rb +154 -0
  36. data/spec/rmodel/mongo/repository_spec.rb +16 -37
  37. data/spec/rmodel/mongo/source_spec.rb +113 -0
  38. data/spec/rmodel/sequel/mapper_spec.rb +57 -0
  39. data/spec/rmodel/sequel/repository_spec.rb +27 -38
  40. data/spec/rmodel/sequel/source_spec.rb +121 -0
  41. data/spec/shared/base_mapper.rb +39 -0
  42. data/spec/shared/clean_moped.rb +6 -2
  43. data/spec/shared/clean_sequel.rb +1 -1
  44. data/spec/shared/{repository_ext → repository}/crud.rb +20 -14
  45. data/spec/shared/repository/initialization.rb +39 -0
  46. data/spec/shared/repository/scopable.rb +137 -0
  47. data/spec/shared/repository/sugarable.rb +67 -0
  48. data/spec/shared/repository/timestampable.rb +137 -0
  49. data/spec/spec_helper.rb +17 -18
  50. metadata +120 -54
  51. data/examples/advanced_creation_of_repository.rb +0 -15
  52. data/examples/user.rb +0 -48
  53. data/lib/rmodel/base/repository.rb +0 -12
  54. data/lib/rmodel/base/repository_ext/sugarable.rb +0 -17
  55. data/lib/rmodel/base/repository_ext/timestampable.rb +0 -19
  56. data/lib/rmodel/mongo/repository.rb +0 -62
  57. data/lib/rmodel/mongo/repository_ext/query.rb +0 -34
  58. data/lib/rmodel/mongo/repository_ext/queryable.rb +0 -34
  59. data/lib/rmodel/mongo/setup.rb +0 -17
  60. data/lib/rmodel/mongo/simple_factory.rb +0 -78
  61. data/lib/rmodel/sequel/repository.rb +0 -61
  62. data/lib/rmodel/sequel/repository_ext/query.rb +0 -34
  63. data/lib/rmodel/sequel/repository_ext/queryable.rb +0 -30
  64. data/lib/rmodel/sequel/setup.rb +0 -12
  65. data/lib/rmodel/sequel/simple_factory.rb +0 -28
  66. data/lib/rmodel/setup.rb +0 -34
  67. data/spec/rmodel/mongo/repository_ext/queryable_spec.rb +0 -103
  68. data/spec/rmodel/mongo/repository_initialize_spec.rb +0 -174
  69. data/spec/rmodel/mongo/simple_factory_spec.rb +0 -195
  70. data/spec/rmodel/sequel/repository_ext/queryable_spec.rb +0 -114
  71. data/spec/rmodel/sequel/repository_initialize_spec.rb +0 -118
  72. data/spec/rmodel/sequel/simple_factory_spec.rb +0 -55
  73. data/spec/rmodel/setup_spec.rb +0 -54
  74. data/spec/shared/repository_ext/sugarable.rb +0 -44
  75. 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
@@ -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