couchdb_to_sql 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.
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class SchemaTest < Test::Unit::TestCase
6
+ def test_init
7
+ database = create_database
8
+ @schema = CouchdbToSql::Schema.new(database, 'items')
9
+
10
+ assert_equal @schema.name, :items
11
+ assert_equal @schema.database, database
12
+ end
13
+
14
+ def test_init_when_table_does_not_exist
15
+ database = Sequel.sqlite
16
+ assert_raises Sequel::Error do
17
+ CouchdbToSql::Schema.new(database, :items)
18
+ end
19
+ end
20
+
21
+ def test_dataset
22
+ database = create_database
23
+ @schema = CouchdbToSql::Schema.new(database, 'items')
24
+ database.expects(:[]).with(:items)
25
+ @schema.dataset
26
+ end
27
+
28
+ def test_prepares_columns
29
+ database = create_database
30
+ @schema = CouchdbToSql::Schema.new(database, 'items')
31
+ assert_equal @schema.columns.keys, %i[id name]
32
+ obj = database.schema(:items)
33
+ assert_equal @schema.columns.values, [obj[0][1], obj[1][1]]
34
+ end
35
+
36
+ def test_prepares_column_names
37
+ database = create_database
38
+ @schema = CouchdbToSql::Schema.new(database, 'items')
39
+ assert_equal @schema.column_names, %i[id name]
40
+ end
41
+
42
+ protected
43
+
44
+ def create_database
45
+ database = Sequel.sqlite
46
+ database.create_table :items do
47
+ primary_key :id
48
+ String :name
49
+ end
50
+ database
51
+ end
52
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TableBuilderTest < Test::Unit::TestCase
6
+ def described_class
7
+ CouchdbToSql::TableBuilder
8
+ end
9
+
10
+ def setup
11
+ @database = create_database
12
+ @changes = mock
13
+ @changes.stubs(:database).returns(@database)
14
+ @changes.stubs(:schema).returns(CouchdbToSql::Schema.new(@database, :items))
15
+ @handler = CouchdbToSql::DocumentHandler.new(@changes)
16
+ end
17
+
18
+ def test_init
19
+ doc = CouchRest::Document.new('type' => 'Item', 'name' => 'Some Item', '_id' => '1234')
20
+ @handler.document = doc
21
+ @row = described_class.new(@handler, 'items')
22
+
23
+ assert_equal @row.parent, @handler
24
+ assert_equal @row.handler, @handler
25
+ assert_equal @row.document, doc
26
+ assert_equal @row.table_name, :items
27
+
28
+ assert_equal @row.primary_key, :item_id
29
+
30
+ # Also confirm that the automated calls were made
31
+ assert_equal @row.attributes[:name], 'Some Item'
32
+ assert_nil @row.attributes[:type]
33
+ assert_nil @row.attributes[:_id]
34
+ assert_equal @row.attributes[:item_id], '1234'
35
+
36
+ assert_equal @row.instance_eval('@_collections.length'), 0
37
+ end
38
+
39
+ def test_init_with_primary_key
40
+ doc = { 'type' => 'Item', 'name' => 'Some Item', '_id' => '1234' }
41
+ @handler.document = doc
42
+ @row = described_class.new(@handler, :items, primary_key: :entry_id)
43
+
44
+ assert_equal @row.primary_key, :entry_id
45
+ end
46
+
47
+ def test_execute_with_new_row
48
+ doc = { 'type' => 'Item', 'name' => 'Some Item', '_id' => '1234' }
49
+ @handler.document = doc
50
+ @row = described_class.new(@handler, :items)
51
+ @row.execute
52
+
53
+ items = @database[:items]
54
+ item = items.first
55
+ assert_equal items.where(item_id: '1234').count, 1
56
+ assert_equal item[:name], 'Some Item'
57
+ end
58
+
59
+ def test_execute_with_new_row_with_time
60
+ time = Time.now
61
+ doc = { 'type' => 'Item', 'name' => 'Some Item', '_id' => '1234', 'created_at' => time.to_s }
62
+ @handler.document = doc
63
+ @row = described_class.new(@handler, :items)
64
+ @row.execute
65
+ items = @database[:items]
66
+ item = items.first
67
+ assert item[:created_at].is_a?(Time)
68
+ assert_equal item[:created_at].to_s, time.to_s
69
+ end
70
+
71
+ def test_column_assign_with_symbol
72
+ doc = { 'type' => 'Item', 'full_name' => 'Some Other Item', '_id' => '1234' }
73
+ @handler.document = doc
74
+ @row = described_class.new @handler, :items do
75
+ column :name, :full_name
76
+ end
77
+ @row.execute
78
+
79
+ data = @database[:items].first
80
+ assert_equal data[:name], doc['full_name']
81
+ end
82
+
83
+ def test_column_assign_with_value
84
+ doc = { 'type' => 'Item', '_id' => '1234' }
85
+ @handler.document = doc
86
+ @row = described_class.new @handler, :items do
87
+ column :name, 'Force the name'
88
+ end
89
+ @row.execute
90
+
91
+ data = @database[:items].first
92
+ assert_equal data[:name], 'Force the name'
93
+ end
94
+
95
+ def test_column_assign_with_nil
96
+ doc = { 'type' => 'Item', 'name' => 'Some Item Name', '_id' => '1234' }
97
+ @handler.document = doc
98
+ @row = described_class.new @handler, :items do
99
+ column :name, nil
100
+ end
101
+ @row.execute
102
+ data = @database[:items].first
103
+ assert_equal data[:name], nil
104
+ end
105
+
106
+ def test_column_assign_with_empty_for_non_string
107
+ doc = { 'type' => 'Item', 'name' => 'Some Item Name', 'created_at' => '', '_id' => '1234' }
108
+ @handler.document = doc
109
+ @row = described_class.new @handler, :items
110
+ @row.execute
111
+ data = @database[:items].first
112
+ assert_equal data[:created_at], nil
113
+ end
114
+
115
+ def test_column_assign_with_integer
116
+ doc = { 'type' => 'Item', 'count' => 3, '_id' => '1234' }
117
+ @handler.document = doc
118
+ @row = described_class.new @handler, :items
119
+ @row.execute
120
+ data = @database[:items].first
121
+ assert_equal data[:count], 3
122
+ end
123
+
124
+ def test_column_assign_with_integer_as_string
125
+ doc = { 'type' => 'Item', 'count' => '1', '_id' => '1234' }
126
+ @handler.document = doc
127
+ @row = described_class.new @handler, :items
128
+ @row.execute
129
+ data = @database[:items].first
130
+ assert_equal data[:count], 1
131
+ end
132
+
133
+ def test_column_assign_with_float
134
+ doc = { 'type' => 'Item', 'price' => 1.2, '_id' => '1234' }
135
+ @handler.document = doc
136
+ @row = described_class.new @handler, :items
137
+ @row.execute
138
+ data = @database[:items].first
139
+ assert_equal data[:price], 1.2
140
+ end
141
+
142
+ def test_column_assign_with_float_as_string
143
+ doc = { 'type' => 'Item', 'price' => '1.2', '_id' => '1234' }
144
+ @handler.document = doc
145
+ @row = described_class.new @handler, :items
146
+ @row.execute
147
+ data = @database[:items].first
148
+ assert_equal data[:price], 1.2
149
+ end
150
+
151
+ def test_column_assign_with_block
152
+ doc = { 'type' => 'Item', '_id' => '1234' }
153
+ @handler.document = doc
154
+ @row = described_class.new @handler, :items do
155
+ column :name do
156
+ 'Name from block'
157
+ end
158
+ end
159
+ @row.execute
160
+
161
+ data = @database[:items].first
162
+ assert_equal data[:name], 'Name from block'
163
+ end
164
+
165
+ def test_column_assign_with_no_field
166
+ doc = { 'type' => 'Item', 'name' => 'Some Other Item', '_id' => '1234' }
167
+ @handler.document = doc
168
+ @row = described_class.new @handler, :items do
169
+ column :name
170
+ end
171
+ @row.execute
172
+
173
+ data = @database[:items].first
174
+ assert_equal data[:name], doc['name']
175
+ end
176
+
177
+ protected
178
+
179
+ def create_database
180
+ database = Sequel.sqlite
181
+ database.create_table :items do
182
+ String :item_id
183
+ String :name
184
+ Integer :count
185
+ Float :price
186
+ Time :created_at
187
+ index :item_id, unique: true
188
+ end
189
+ database
190
+ end
191
+
192
+ def create_many_to_many_items
193
+ @database.create_table :group_items do
194
+ String :group_id
195
+ String :item_id
196
+ index :group_id
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TableDestroyerTest < Test::Unit::TestCase
6
+ def described_class
7
+ CouchdbToSql::TableDestroyer
8
+ end
9
+
10
+ def setup
11
+ @database = create_database
12
+ @changes = mock
13
+ @changes.stubs(:database).returns(@database)
14
+ @changes.stubs(:schema).returns(CouchdbToSql::Schema.new(@database, :items))
15
+ @handler = CouchdbToSql::DocumentHandler.new(@changes)
16
+ @handler.document = { '_id' => '12345' }
17
+ end
18
+
19
+ def test_init
20
+ @row = described_class.new(@handler, 'items')
21
+ assert_equal @row.primary_key, :item_id
22
+ end
23
+
24
+ def test_init_override_primary_key
25
+ @row = described_class.new(@handler, 'items', primary_key: 'foo_item_id')
26
+ assert_equal @row.primary_key, :foo_item_id
27
+ end
28
+
29
+ def test_handler
30
+ @row = described_class.new(@handler, :items)
31
+ assert_equal @row.handler, @handler
32
+ end
33
+
34
+ def test_key_filter
35
+ @row = described_class.new(@handler, :items)
36
+ assert_equal @row.key_filter, item_id: '12345'
37
+ end
38
+
39
+ def test_execution_deletes_rows
40
+ @database[:items].insert(name: 'Test Item 1', item_id: '12345')
41
+ assert_equal @database[:items].count, 1, 'Did not create sample row correctly!'
42
+ @row = described_class.new(@handler, :items)
43
+ @row.execute
44
+ assert_equal 0, @database[:items].count
45
+ end
46
+
47
+ protected
48
+
49
+ def create_database
50
+ database = Sequel.sqlite
51
+ database.create_table :items do
52
+ String :item_id
53
+ String :name
54
+ Time :created_at
55
+ index :item_id, unique: true
56
+ end
57
+ database.create_table :groups do
58
+ String :group_id
59
+ String :name
60
+ Time :created_at
61
+ index :group_id, unique: true
62
+ end
63
+ database
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: couchdb_to_sql
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Lown
8
+ - Per Lundberg
9
+ - Jens Nockert
10
+ - Andreas Finne
11
+ autorequire:
12
+ bindir: exe
13
+ cert_chain: []
14
+ date: 2017-10-10 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activesupport
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '5.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: couchrest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '2.0'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: httpclient
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '2.6'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '2.6'
58
+ - !ruby/object:Gem::Dependency
59
+ name: logging_library
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '1.0'
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 1.0.5
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.0'
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.5
78
+ - !ruby/object:Gem::Dependency
79
+ name: sequel
80
+ requirement: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 4.36.0
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: 4.36.0
92
+ - !ruby/object:Gem::Dependency
93
+ name: mocha
94
+ requirement: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ - !ruby/object:Gem::Dependency
107
+ name: rake
108
+ requirement: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '12.0'
113
+ type: :development
114
+ prerelease: false
115
+ version_requirements: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '12.0'
120
+ - !ruby/object:Gem::Dependency
121
+ name: rubocop
122
+ requirement: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ type: :development
128
+ prerelease: false
129
+ version_requirements: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ - !ruby/object:Gem::Dependency
135
+ name: simplecov
136
+ requirement: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - "~>"
139
+ - !ruby/object:Gem::Version
140
+ version: '0.15'
141
+ type: :development
142
+ prerelease: false
143
+ version_requirements: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - "~>"
146
+ - !ruby/object:Gem::Version
147
+ version: '0.15'
148
+ - !ruby/object:Gem::Dependency
149
+ name: test-unit
150
+ requirement: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - "~>"
153
+ - !ruby/object:Gem::Version
154
+ version: '3.2'
155
+ type: :development
156
+ prerelease: false
157
+ version_requirements: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - "~>"
160
+ - !ruby/object:Gem::Version
161
+ version: '3.2'
162
+ description: couchdb_to_sql provides a DSL that allows complex CouchDB documents to
163
+ be converted into rows in a RDBMS' table. The stream of events received from the
164
+ CouchDB changes feed will trigger documents to be fed into a matching filter block
165
+ and saved in the database.
166
+ email:
167
+ executables:
168
+ - couchdb_to_sql
169
+ extensions: []
170
+ extra_rdoc_files: []
171
+ files:
172
+ - ".gitignore"
173
+ - ".rubocop.yml"
174
+ - ".rubocop_todo.yml"
175
+ - ".ruby-version"
176
+ - ".travis.yml"
177
+ - ".vscode/launch.json"
178
+ - Gemfile
179
+ - LICENSE
180
+ - README.md
181
+ - Rakefile
182
+ - VERSION
183
+ - couchdb_to_sql.gemspec
184
+ - examples/feed.rb
185
+ - exe/couchdb_to_sql
186
+ - lib/couchdb_to_sql.rb
187
+ - lib/couchdb_to_sql/changes.rb
188
+ - lib/couchdb_to_sql/document_handler.rb
189
+ - lib/couchdb_to_sql/schema.rb
190
+ - lib/couchdb_to_sql/table_builder.rb
191
+ - lib/couchdb_to_sql/table_deleted_marker.rb
192
+ - lib/couchdb_to_sql/table_destroyer.rb
193
+ - lib/couchdb_to_sql/table_operator.rb
194
+ - test/functional/functional_changes_test.rb
195
+ - test/test_helper.rb
196
+ - test/unit/changes_test.rb
197
+ - test/unit/document_handler_test.rb
198
+ - test/unit/schema_test.rb
199
+ - test/unit/table_builder_test.rb
200
+ - test/unit/table_destroyer_test.rb
201
+ homepage: https://github.com/ecraft/couchdb_to_sql
202
+ licenses:
203
+ - MIT
204
+ metadata: {}
205
+ post_install_message:
206
+ rdoc_options: []
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ requirements: []
220
+ rubyforge_project:
221
+ rubygems_version: 2.6.14
222
+ signing_key:
223
+ specification_version: 4
224
+ summary: Listen to a CouchDB changes feed and create rows in a relational database
225
+ in real-time.
226
+ test_files:
227
+ - test/functional/functional_changes_test.rb
228
+ - test/test_helper.rb
229
+ - test/unit/changes_test.rb
230
+ - test/unit/document_handler_test.rb
231
+ - test/unit/schema_test.rb
232
+ - test/unit/table_builder_test.rb
233
+ - test/unit/table_destroyer_test.rb