sequel_mapper 0.0.1 → 0.0.3

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/.ruby-version +1 -1
  3. data/CODE_OF_CONDUCT.md +28 -0
  4. data/Gemfile.lock +32 -2
  5. data/MissingFeatures.md +64 -0
  6. data/README.md +141 -72
  7. data/Rakefile +29 -0
  8. data/TODO.md +16 -11
  9. data/features/env.rb +57 -0
  10. data/features/example.feature +121 -0
  11. data/features/step_definitions/example_steps.rb +46 -0
  12. data/lib/sequel_mapper.rb +6 -2
  13. data/lib/sequel_mapper/abstract_record.rb +53 -0
  14. data/lib/sequel_mapper/association_loaders.rb +52 -0
  15. data/lib/sequel_mapper/collection_mutability_proxy.rb +77 -0
  16. data/lib/sequel_mapper/configurations/conventional_association_configuration.rb +187 -0
  17. data/lib/sequel_mapper/configurations/conventional_configuration.rb +269 -0
  18. data/lib/sequel_mapper/dataset.rb +37 -0
  19. data/lib/sequel_mapper/deleted_record.rb +16 -0
  20. data/lib/sequel_mapper/dirty_map.rb +31 -0
  21. data/lib/sequel_mapper/graph_loader.rb +48 -0
  22. data/lib/sequel_mapper/graph_serializer.rb +107 -0
  23. data/lib/sequel_mapper/identity_map.rb +22 -0
  24. data/lib/sequel_mapper/lazy_object_proxy.rb +51 -0
  25. data/lib/sequel_mapper/many_to_many_association.rb +181 -0
  26. data/lib/sequel_mapper/many_to_one_association.rb +60 -0
  27. data/lib/sequel_mapper/mapper_facade.rb +180 -0
  28. data/lib/sequel_mapper/one_to_many_association.rb +51 -0
  29. data/lib/sequel_mapper/public_conveniencies.rb +27 -0
  30. data/lib/sequel_mapper/query_order.rb +32 -0
  31. data/lib/sequel_mapper/queryable_lazy_dataset_loader.rb +70 -0
  32. data/lib/sequel_mapper/relation_mapping.rb +35 -0
  33. data/lib/sequel_mapper/serializer.rb +18 -0
  34. data/lib/sequel_mapper/short_inspection_string.rb +18 -0
  35. data/lib/sequel_mapper/subset_queries_proxy.rb +11 -0
  36. data/lib/sequel_mapper/upserted_record.rb +15 -0
  37. data/lib/sequel_mapper/version.rb +1 -1
  38. data/sequel_mapper.gemspec +3 -0
  39. data/spec/config_override_spec.rb +167 -0
  40. data/spec/custom_serializers_spec.rb +77 -0
  41. data/spec/deletion_spec.rb +104 -0
  42. data/spec/graph_persistence_spec.rb +83 -88
  43. data/spec/graph_traversal_spec.rb +32 -31
  44. data/spec/new_graph_persistence_spec.rb +69 -0
  45. data/spec/object_identity_spec.rb +70 -0
  46. data/spec/ordered_association_spec.rb +46 -16
  47. data/spec/persistence_efficiency_spec.rb +186 -0
  48. data/spec/predefined_queries_spec.rb +73 -0
  49. data/spec/proxying_spec.rb +25 -19
  50. data/spec/querying_spec.rb +24 -27
  51. data/spec/readme_examples_spec.rb +35 -0
  52. data/spec/sequel_mapper/abstract_record_spec.rb +179 -0
  53. data/spec/sequel_mapper/{association_proxy_spec.rb → collection_mutability_proxy_spec.rb} +6 -6
  54. data/spec/sequel_mapper/deleted_record_spec.rb +59 -0
  55. data/spec/sequel_mapper/lazy_object_proxy_spec.rb +140 -0
  56. data/spec/sequel_mapper/public_conveniencies_spec.rb +49 -0
  57. data/spec/sequel_mapper/queryable_lazy_dataset_loader_spec.rb +103 -0
  58. data/spec/sequel_mapper/upserted_record_spec.rb +59 -0
  59. data/spec/spec_helper.rb +7 -10
  60. data/spec/support/blog_schema.rb +29 -0
  61. data/spec/support/have_persisted_matcher.rb +19 -0
  62. data/spec/support/mapper_setup.rb +234 -0
  63. data/spec/support/mock_sequel.rb +0 -1
  64. data/spec/support/object_graph_setup.rb +106 -0
  65. data/spec/support/seed_data_setup.rb +122 -0
  66. data/spec/support/sequel_persistence_setup.rb +19 -0
  67. data/spec/support/sequel_test_support.rb +159 -0
  68. metadata +121 -15
  69. data/lib/sequel_mapper/association_proxy.rb +0 -54
  70. data/lib/sequel_mapper/belongs_to_association_proxy.rb +0 -27
  71. data/lib/sequel_mapper/graph.rb +0 -174
  72. data/lib/sequel_mapper/queryable_association_proxy.rb +0 -23
  73. data/spec/sequel_mapper/belongs_to_association_proxy_spec.rb +0 -65
  74. data/spec/support/graph_fixture.rb +0 -331
  75. data/spec/support/query_counter.rb +0 -29
@@ -0,0 +1,19 @@
1
+ require "support/sequel_test_support"
2
+
3
+ RSpec.shared_context "sequel persistence setup" do
4
+ include SequelMapper::SequelTestSupport
5
+
6
+ before { truncate_tables }
7
+
8
+ let(:datastore) {
9
+ db_connection.tap { |db|
10
+ # The query_counter will let us make assertions about how efficiently
11
+ # the database is being used
12
+ db.loggers << query_counter
13
+ }
14
+ }
15
+
16
+ let(:query_counter) {
17
+ SequelMapper::SequelTestSupport::QueryCounter.new
18
+ }
19
+ end
@@ -0,0 +1,159 @@
1
+ require "sequel"
2
+
3
+ module SequelMapper
4
+ module SequelTestSupport
5
+ def create_database
6
+ `psql postgres --command "CREATE DATABASE $PGDATABASE;"`
7
+ end
8
+ module_function :create_database
9
+
10
+ def drop_database
11
+ `psql postgres --command "DROP DATABASE $PGDATABASE;"`
12
+ end
13
+ module_function :drop_database
14
+
15
+ def drop_tables
16
+ db_connection.tables.each do |table_name|
17
+ db_connection.drop_table(table_name)
18
+ end
19
+ end
20
+ module_function :drop_tables
21
+
22
+ def truncate_tables
23
+ db_connection.tables.each do |table_name|
24
+ db_connection[table_name].truncate
25
+ end
26
+ end
27
+ module_function :truncate_tables
28
+
29
+ def db_connection
30
+ Sequel.default_timezone = :utc
31
+ @db_connection ||= Sequel.postgres(
32
+ host: ENV.fetch("PGHOST"),
33
+ user: ENV.fetch("PGUSER"),
34
+ database: ENV.fetch("PGDATABASE"),
35
+ )
36
+ end
37
+ module_function :db_connection
38
+
39
+ def create_tables(schema)
40
+ options_map = {
41
+ id: { primary_key: true },
42
+ }
43
+
44
+ schema.each do |table_name, fields|
45
+
46
+ db_connection.create_table(table_name) do
47
+ fields.each do |field|
48
+ type = field.fetch(:type)
49
+ name = field.fetch(:name)
50
+ options = options_map.fetch(name, {})
51
+
52
+ send(type, name, options)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ module_function :create_tables
58
+
59
+ def insert_records(datastore, records)
60
+ records.each { |(namespace, record)|
61
+ datastore[namespace].insert(record)
62
+ }
63
+ end
64
+
65
+ class QueryCounter
66
+ def initialize
67
+ reset
68
+ end
69
+
70
+ def read_count
71
+ read_count_with_describes -
72
+ list_tables_query_count -
73
+ describe_table_queries_count
74
+ end
75
+
76
+ def delete_count
77
+ @info.count { |query|
78
+ /\A\([0-9\.]+s\) DELETE/i === query
79
+ }
80
+ end
81
+
82
+ def read_count_with_describes
83
+ @info.count { |query|
84
+ /\A\([0-9\.]+s\) SELECT/i === query
85
+ }
86
+ end
87
+
88
+ def update_count
89
+ @info.count { |query|
90
+ /\A\([0-9\.]+s\) UPDATE/i === query
91
+ }
92
+ end
93
+
94
+ def show_queries
95
+ puts @info.join("\n")
96
+ end
97
+
98
+ def info(message)
99
+ @info.push(message)
100
+ end
101
+
102
+ def error(message)
103
+ @error.push(message)
104
+ end
105
+
106
+ def warn(message)
107
+ @warn.push(message)
108
+ end
109
+
110
+ def reset
111
+ @described_table_queries = []
112
+ @info = []
113
+ @error = []
114
+ @warn = []
115
+ end
116
+
117
+ private
118
+
119
+ def list_tables_query_count
120
+ @info.count { |query| list_tables_query_pattern.match(query) }
121
+ end
122
+
123
+ def describe_table_queries_count
124
+ describe_table_queries.count
125
+ end
126
+
127
+ def describe_table_queries
128
+ # TODO this could probably be better solved with finite automata
129
+ described_table_queries = []
130
+
131
+ queries_without_table_list
132
+ .take_while { |query|
133
+ described_table_queries.push(query)
134
+ described_table_query_pattern.match(query) &&
135
+ described_table_queries.length == described_table_queries.uniq.length
136
+ }
137
+ end
138
+
139
+ def queries_without_table_list
140
+ @info
141
+ .drop_while { |query|
142
+ !list_tables_query_pattern.match(query)
143
+ }
144
+ .drop_while { |query|
145
+ list_tables_query_pattern.match(query)
146
+ }
147
+ end
148
+
149
+
150
+ def list_tables_query_pattern
151
+ /\A\([0-9\.]+s\) SELECT "relname" FROM "pg_class"/
152
+ end
153
+
154
+ def described_table_query_pattern
155
+ /\A\([0-9\.]+s\) SELECT \* FROM "[^"]+" LIMIT 1/i
156
+ end
157
+ end
158
+ end
159
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Best
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-27 00:00:00.000000000 Z
11
+ date: 2016-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: cucumber
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: pg
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +108,34 @@ dependencies:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: '4.16'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: fetchable
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.0'
97
139
  description: ''
98
140
  email:
99
141
  - bestie@gmail.com
@@ -104,31 +146,74 @@ files:
104
146
  - ".gitignore"
105
147
  - ".rspec"
106
148
  - ".ruby-version"
149
+ - CODE_OF_CONDUCT.md
107
150
  - Gemfile
108
151
  - Gemfile.lock
109
152
  - LICENSE.txt
153
+ - MissingFeatures.md
110
154
  - README.md
111
155
  - Rakefile
112
156
  - TODO.md
157
+ - features/env.rb
158
+ - features/example.feature
159
+ - features/step_definitions/example_steps.rb
113
160
  - lib/sequel_mapper.rb
114
- - lib/sequel_mapper/association_proxy.rb
115
- - lib/sequel_mapper/belongs_to_association_proxy.rb
116
- - lib/sequel_mapper/graph.rb
117
- - lib/sequel_mapper/queryable_association_proxy.rb
161
+ - lib/sequel_mapper/abstract_record.rb
162
+ - lib/sequel_mapper/association_loaders.rb
163
+ - lib/sequel_mapper/collection_mutability_proxy.rb
164
+ - lib/sequel_mapper/configurations/conventional_association_configuration.rb
165
+ - lib/sequel_mapper/configurations/conventional_configuration.rb
166
+ - lib/sequel_mapper/dataset.rb
167
+ - lib/sequel_mapper/deleted_record.rb
168
+ - lib/sequel_mapper/dirty_map.rb
169
+ - lib/sequel_mapper/graph_loader.rb
170
+ - lib/sequel_mapper/graph_serializer.rb
171
+ - lib/sequel_mapper/identity_map.rb
172
+ - lib/sequel_mapper/lazy_object_proxy.rb
173
+ - lib/sequel_mapper/many_to_many_association.rb
174
+ - lib/sequel_mapper/many_to_one_association.rb
175
+ - lib/sequel_mapper/mapper_facade.rb
176
+ - lib/sequel_mapper/one_to_many_association.rb
177
+ - lib/sequel_mapper/public_conveniencies.rb
178
+ - lib/sequel_mapper/query_order.rb
179
+ - lib/sequel_mapper/queryable_lazy_dataset_loader.rb
180
+ - lib/sequel_mapper/relation_mapping.rb
181
+ - lib/sequel_mapper/serializer.rb
182
+ - lib/sequel_mapper/short_inspection_string.rb
118
183
  - lib/sequel_mapper/struct_factory.rb
184
+ - lib/sequel_mapper/subset_queries_proxy.rb
185
+ - lib/sequel_mapper/upserted_record.rb
119
186
  - lib/sequel_mapper/version.rb
120
187
  - sequel_mapper.gemspec
188
+ - spec/config_override_spec.rb
189
+ - spec/custom_serializers_spec.rb
190
+ - spec/deletion_spec.rb
121
191
  - spec/graph_persistence_spec.rb
122
192
  - spec/graph_traversal_spec.rb
193
+ - spec/new_graph_persistence_spec.rb
194
+ - spec/object_identity_spec.rb
123
195
  - spec/ordered_association_spec.rb
196
+ - spec/persistence_efficiency_spec.rb
197
+ - spec/predefined_queries_spec.rb
124
198
  - spec/proxying_spec.rb
125
199
  - spec/querying_spec.rb
126
- - spec/sequel_mapper/association_proxy_spec.rb
127
- - spec/sequel_mapper/belongs_to_association_proxy_spec.rb
200
+ - spec/readme_examples_spec.rb
201
+ - spec/sequel_mapper/abstract_record_spec.rb
202
+ - spec/sequel_mapper/collection_mutability_proxy_spec.rb
203
+ - spec/sequel_mapper/deleted_record_spec.rb
204
+ - spec/sequel_mapper/lazy_object_proxy_spec.rb
205
+ - spec/sequel_mapper/public_conveniencies_spec.rb
206
+ - spec/sequel_mapper/queryable_lazy_dataset_loader_spec.rb
207
+ - spec/sequel_mapper/upserted_record_spec.rb
128
208
  - spec/spec_helper.rb
129
- - spec/support/graph_fixture.rb
209
+ - spec/support/blog_schema.rb
210
+ - spec/support/have_persisted_matcher.rb
211
+ - spec/support/mapper_setup.rb
130
212
  - spec/support/mock_sequel.rb
131
- - spec/support/query_counter.rb
213
+ - spec/support/object_graph_setup.rb
214
+ - spec/support/seed_data_setup.rb
215
+ - spec/support/sequel_persistence_setup.rb
216
+ - spec/support/sequel_test_support.rb
132
217
  homepage: https://github.com/bestie/sequel_mapper
133
218
  licenses:
134
219
  - MIT
@@ -149,19 +234,40 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
234
  version: '0'
150
235
  requirements: []
151
236
  rubyforge_project:
152
- rubygems_version: 2.2.2
237
+ rubygems_version: 2.4.5
153
238
  signing_key:
154
239
  specification_version: 4
155
240
  summary: A data mapper built on top of the Sequel database toolkit
156
241
  test_files:
242
+ - features/env.rb
243
+ - features/example.feature
244
+ - features/step_definitions/example_steps.rb
245
+ - spec/config_override_spec.rb
246
+ - spec/custom_serializers_spec.rb
247
+ - spec/deletion_spec.rb
157
248
  - spec/graph_persistence_spec.rb
158
249
  - spec/graph_traversal_spec.rb
250
+ - spec/new_graph_persistence_spec.rb
251
+ - spec/object_identity_spec.rb
159
252
  - spec/ordered_association_spec.rb
253
+ - spec/persistence_efficiency_spec.rb
254
+ - spec/predefined_queries_spec.rb
160
255
  - spec/proxying_spec.rb
161
256
  - spec/querying_spec.rb
162
- - spec/sequel_mapper/association_proxy_spec.rb
163
- - spec/sequel_mapper/belongs_to_association_proxy_spec.rb
257
+ - spec/readme_examples_spec.rb
258
+ - spec/sequel_mapper/abstract_record_spec.rb
259
+ - spec/sequel_mapper/collection_mutability_proxy_spec.rb
260
+ - spec/sequel_mapper/deleted_record_spec.rb
261
+ - spec/sequel_mapper/lazy_object_proxy_spec.rb
262
+ - spec/sequel_mapper/public_conveniencies_spec.rb
263
+ - spec/sequel_mapper/queryable_lazy_dataset_loader_spec.rb
264
+ - spec/sequel_mapper/upserted_record_spec.rb
164
265
  - spec/spec_helper.rb
165
- - spec/support/graph_fixture.rb
266
+ - spec/support/blog_schema.rb
267
+ - spec/support/have_persisted_matcher.rb
268
+ - spec/support/mapper_setup.rb
166
269
  - spec/support/mock_sequel.rb
167
- - spec/support/query_counter.rb
270
+ - spec/support/object_graph_setup.rb
271
+ - spec/support/seed_data_setup.rb
272
+ - spec/support/sequel_persistence_setup.rb
273
+ - spec/support/sequel_test_support.rb
@@ -1,54 +0,0 @@
1
- require "forwardable"
2
-
3
- module SequelMapper
4
- class AssociationProxy
5
- def initialize(assoc_enum)
6
- @assoc_enum = assoc_enum
7
- @added_nodes = []
8
- @removed_nodes = []
9
- end
10
-
11
- attr_reader :assoc_enum, :removed_nodes, :added_nodes
12
- private :assoc_enum
13
-
14
- include Enumerable
15
- def each(&block)
16
- enum = Enumerator.new do |yielder|
17
- assoc_enum.each do |element|
18
- yielder.yield(element) unless removed?(element)
19
- end
20
-
21
- @added_nodes.each do |node|
22
- yielder.yield(node)
23
- end
24
- end
25
-
26
- if block
27
- enum.each(&block)
28
- self
29
- else
30
- enum
31
- end
32
- end
33
-
34
- def remove(node)
35
- @removed_nodes.push(node)
36
- self
37
- end
38
-
39
- def push(node)
40
- @added_nodes.push(node)
41
- end
42
-
43
- def where(criteria)
44
- @assoc_enum.where(criteria)
45
- self
46
- end
47
-
48
- private
49
-
50
- def removed?(node)
51
- @removed_nodes.include?(node)
52
- end
53
- end
54
- end
@@ -1,27 +0,0 @@
1
- require "delegate"
2
-
3
- class BelongsToAssociationProxy < SimpleDelegator
4
- def initialize(object_loader)
5
- @object_loader = object_loader
6
- @loaded = false
7
- end
8
-
9
- def method_missing(method_id, *args, &block)
10
- __load_object__
11
-
12
- super
13
- end
14
-
15
- def __getobj__
16
- __load_object__
17
- super
18
- end
19
-
20
- private
21
-
22
- def __load_object__
23
- __setobj__(@object_loader.call).tap {
24
- @loaded = true
25
- } unless @loaded
26
- end
27
- end