couchdb_to_sql 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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