txdb 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e59bfc3e60354b89d0a572dc8639ecc1bec5146
4
- data.tar.gz: 05599e91b876f536edabd4f05163f769fbf2a2c5
3
+ metadata.gz: 0c2c319827b4fdab7a23880e83db01a22cbff37f
4
+ data.tar.gz: e4daed35214662b575b686607b825b29fed8aed7
5
5
  SHA512:
6
- metadata.gz: 7903d1a0966bc7428dce7de537418ba437e06e48ec95032c4fb21bcc513c8703552c28183be6e23b6271b2f5b921d8ebe5eb4e27500c005c3316590daa84f7a2
7
- data.tar.gz: 470a4c9d4d8df0a31f8d8c1275384dab4ba8c487266a6093ad44299ba42e12f61ea0b750e1c814a9b5c2e289204b1b110b83bf8aa5c93c204beb2d74cd3a21e4
6
+ metadata.gz: c0e524ba754bed238ccf5647f1711c357cf87a59fd558fb6fa69e06732c6570eb4486f87de36634f9488d79499db1b1e36acd86ebb3836e791684e35aa472f94
7
+ data.tar.gz: 78b1aa0ada81ef0c9369b46177a4dedf6db6a5fcd07c31151167544dac9bfe69bc0178eeb5b8ce35b525d90210f0b40d9569cba5acc6b36de235d794f984a004
@@ -9,6 +9,7 @@ module Txdb
9
9
  autoload :Downloader, 'txdb/downloader'
10
10
  autoload :Handlers, 'txdb/handlers'
11
11
  autoload :Hooks, 'txdb/app'
12
+ autoload :Iterators, 'txdb/iterators'
12
13
  autoload :Response, 'txdb/response'
13
14
  autoload :ResponseHelpers, 'txdb/response_helpers'
14
15
  autoload :Table, 'txdb/table'
@@ -51,7 +51,7 @@ module Txdb
51
51
  end
52
52
 
53
53
  def content_for_records
54
- each_record.each_with_object({}) do |record, ret|
54
+ iterator.each_with_object({}) do |record, ret|
55
55
  ret[record[:id]] = content_for_record(record)
56
56
  end
57
57
  end
@@ -61,33 +61,13 @@ module Txdb
61
61
  value = record[col.to_sym]
62
62
 
63
63
  unless value.to_s.strip.empty?
64
- ret[col] = value
64
+ ret[col.to_s] = value
65
65
  end
66
66
  end
67
67
  end
68
68
 
69
- def each_record
70
- return to_enum(__method__) unless block_given?
71
-
72
- counter = 0
73
- last_id = nil
74
-
75
- loop do
76
- records = table.db
77
- .from(origin_table_name(table.name))
78
- .where { id >= counter }
79
- .order(:id)
80
- .limit(50)
81
-
82
- break if records.count == 0
83
-
84
- records.each do |record|
85
- yield record
86
- last_id = record[:id]
87
- end
88
-
89
- counter = last_id + 1
90
- end
69
+ def iterator
70
+ @iterator ||= Iterators::GlobalizeIterator.new(table)
91
71
  end
92
72
  end
93
73
 
@@ -25,10 +25,12 @@ module Txdb
25
25
  private
26
26
 
27
27
  def update_row(id, fields, locale)
28
- row = table.db.where(foreign_key.to_sym => id, locale: locale)
28
+ row = table.connection.where(
29
+ foreign_key.to_sym => id, locale: locale
30
+ )
29
31
 
30
32
  if row.empty?
31
- table.db << fields
33
+ table.connection << fields
32
34
  .merge(foreign_key.to_sym => id, locale: locale)
33
35
  .merge(created_at)
34
36
  .merge(updated_at)
@@ -38,12 +40,12 @@ module Txdb
38
40
  end
39
41
 
40
42
  def created_at
41
- return {} unless table.db.columns.include?(:created_at)
43
+ return {} unless table.connection.columns.include?(:created_at)
42
44
  { created_at: get_utc_time }
43
45
  end
44
46
 
45
47
  def updated_at
46
- return {} unless table.db.columns.include?(:updated_at)
48
+ return {} unless table.connection.columns.include?(:updated_at)
47
49
  { updated_at: get_utc_time }
48
50
  end
49
51
 
@@ -25,16 +25,21 @@ module Txdb
25
25
  end
26
26
  end
27
27
 
28
- def db
29
- @db ||= Sequel.connect(connection_string, max_connections: pool)
28
+ def connection
29
+ @connection ||= Sequel.connect(connection_string, max_connections: pool)
30
30
  end
31
31
 
32
32
  def from(*args, &block)
33
- db.from(*args, &block)
33
+ connection.from(*args, &block)
34
34
  end
35
35
 
36
36
  def transifex_api
37
37
  transifex_project.api
38
38
  end
39
+
40
+ def find_table(name)
41
+ name = name.to_s
42
+ tables.find { |table| table.name == name }
43
+ end
39
44
  end
40
45
  end
@@ -3,8 +3,8 @@ require 'txgh'
3
3
  module Txdb
4
4
  class Downloader
5
5
  class << self
6
- def download(database)
7
- new(database).download
6
+ def download(database, locale)
7
+ new(database).download(locale)
8
8
  end
9
9
  end
10
10
 
@@ -0,0 +1,6 @@
1
+ module Txdb
2
+ module Iterators
3
+ autoload :AutoIncrementIterator, 'txdb/iterators/auto_increment_iterator'
4
+ autoload :GlobalizeIterator, 'txdb/iterators/globalize_iterator'
5
+ end
6
+ end
@@ -0,0 +1,61 @@
1
+ module Txdb
2
+ module Iterators
3
+ class AutoIncrementIterator
4
+ include Enumerable
5
+
6
+ DEFAULT_BATCH_SIZE = 50
7
+ DEFAULT_COLUMN = :id
8
+
9
+ attr_reader :table, :batch_size, :column
10
+
11
+ def initialize(table, options = {})
12
+ @table = table
13
+ @batch_size = options.fetch(:batch_size, DEFAULT_BATCH_SIZE)
14
+ @column = options.fetch(:column, DEFAULT_COLUMN)
15
+ end
16
+
17
+ def each
18
+ return to_enum(__method__) unless block_given?
19
+
20
+ counter = 0
21
+ last_value = nil
22
+ sql_column = Sequel.expr(column)
23
+
24
+ loop do
25
+ records = table.connection
26
+ .from(table_name)
27
+ .where { sql_column >= counter }
28
+ .order(column)
29
+ .limit(batch_size)
30
+
31
+ break if records.count == 0
32
+
33
+ records.each do |record|
34
+ yield record
35
+ last_value = record[column]
36
+ end
37
+
38
+ counter = last_value + 1
39
+ end
40
+ end
41
+
42
+ alias_method :each_record, :each
43
+
44
+ def compact_map
45
+ return to_enum(__method__) unless block_given?
46
+
47
+ each_with_object([]) do |elem, ret|
48
+ if val = yield(elem)
49
+ ret << val
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def table_name
57
+ table.name
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,13 @@
1
+ module Txdb
2
+ module Iterators
3
+ class GlobalizeIterator < AutoIncrementIterator
4
+ private
5
+
6
+ include Backends::Globalize::Helpers
7
+
8
+ def table_name
9
+ origin_table_name(table.name)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -12,8 +12,8 @@ module Txdb
12
12
  @source_lang = options.fetch(:source_lang)
13
13
  end
14
14
 
15
- def db
16
- database.db.from(name)
15
+ def connection
16
+ database.connection.from(name)
17
17
  end
18
18
 
19
19
  def read_content
@@ -1,3 +1,3 @@
1
1
  module Txdb
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
 
4
4
  include Txdb::Backends
5
5
 
6
- describe Globalize::Helpers, test_db: true do
6
+ describe Globalize::Helpers, test_config: true do
7
7
  describe '.origin_table_name' do
8
8
  it 'pluralizes and removes the translations suffix' do
9
9
  origin = Globalize::Helpers.origin_table_name('widget_translations')
@@ -17,8 +17,15 @@ describe Globalize::Helpers, test_db: true do
17
17
  end
18
18
 
19
19
  describe '#resource_slug_for' do
20
- let(:database) { TestDb.database }
21
- let(:table) { database.tables.first }
20
+ let(:database) do
21
+ Txdb::TestConfigurator.setup do
22
+ create_table(:my_table) do
23
+ primary_key :id
24
+ end
25
+ end
26
+ end
27
+
28
+ let(:table) { database.find_table(:my_table) }
22
29
 
23
30
  it 'constructs a slug from the database and table names' do
24
31
  expect(Globalize::Helpers.resource_slug_for(table)).to eq(
@@ -1,28 +1,28 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/globalize_db'
2
+ require 'spec_helpers/globalize_configurator'
3
3
  require 'yaml'
4
4
 
5
5
  include Txdb::Backends
6
6
 
7
- describe Globalize::Reader, globalize_db: true do
7
+ describe Globalize::Reader, globalize_config: true do
8
8
  include_context :globalize
9
9
 
10
10
  describe '#read_content' do
11
11
  it 'reads data from the given table and returns an array of resources' do
12
- sprocket_id = widgets.insert(name: 'sprocket')
13
- flange_id = widgets.insert(name: 'flange')
14
- widget_translations.insert(widget_id: sprocket_id, locale: 'es', name: 'sproqueta')
15
- widget_translations.insert(widget_id: flange_id, locale: 'es', name: 'flango')
12
+ sprocket_id = widgets.connection.insert(name: 'sprocket')
13
+ flange_id = widgets.connection.insert(name: 'flange')
14
+ widget_translations.connection.insert(widget_id: sprocket_id, locale: 'es', name: 'sproqueta')
15
+ widget_translations.connection.insert(widget_id: flange_id, locale: 'es', name: 'flango')
16
16
 
17
- reader = Globalize::Reader.new(widget_translations_table)
17
+ reader = Globalize::Reader.new(widget_translations)
18
18
  resources = reader.read_content
19
19
  expect(resources.size).to eq(1)
20
20
  resource = resources.first
21
21
 
22
- expect(resource.source_file).to eq(widget_translations_table.name)
22
+ expect(resource.source_file).to eq(widget_translations.name)
23
23
  expect(resource.project_slug).to eq(database.transifex_project.project_slug)
24
24
  expect(resource.resource_slug).to(
25
- eq(Globalize::Helpers.resource_slug_for(widget_translations_table))
25
+ eq(Globalize::Helpers.resource_slug_for(widget_translations))
26
26
  )
27
27
 
28
28
  expect(resource.content).to eq(
@@ -1,12 +1,12 @@
1
1
  require 'active_support/core_ext/numeric/time'
2
2
  require 'spec_helper'
3
- require 'spec_helpers/globalize_db'
3
+ require 'spec_helpers/globalize_configurator'
4
4
  require 'timecop'
5
5
  require 'yaml'
6
6
 
7
7
  include Txdb::Backends
8
8
 
9
- describe Globalize::Writer, globalize_db: true do
9
+ describe Globalize::Writer, globalize_config: true do
10
10
  include_context :globalize
11
11
 
12
12
  describe '#write_content' do
@@ -21,8 +21,8 @@ describe Globalize::Writer, globalize_db: true do
21
21
 
22
22
  context 'with some content' do
23
23
  before(:each) do
24
- @sprocket_id = widgets.insert(name: 'sprocket')
25
- @writer = Globalize::Writer.new(widget_translations_table)
24
+ @sprocket_id = widgets.connection.insert(name: 'sprocket')
25
+ @writer = Globalize::Writer.new(widget_translations)
26
26
 
27
27
  @content = YAML.dump(
28
28
  'widgets' => {
@@ -35,10 +35,10 @@ describe Globalize::Writer, globalize_db: true do
35
35
 
36
36
  it 'inserts the translations into the database' do
37
37
  expect { @writer.write_content(@resource, 'es') }.to(
38
- change { widget_translations.count }.from(0).to(1)
38
+ change { widget_translations.connection.count }.from(0).to(1)
39
39
  )
40
40
 
41
- translation = widget_translations.first
41
+ translation = widget_translations.connection.first
42
42
 
43
43
  expect(translation).to include(
44
44
  widget_id: @sprocket_id, name: 'sproqueta', locale: 'es'
@@ -47,7 +47,7 @@ describe Globalize::Writer, globalize_db: true do
47
47
 
48
48
  context 'with created_at and updated_at columns' do
49
49
  before(:each) do
50
- GlobalizeDb.db.alter_table(:widget_translations) do
50
+ database.connection.alter_table(:widget_translations) do
51
51
  add_column :created_at, Time
52
52
  add_column :updated_at, Time
53
53
  end
@@ -56,7 +56,7 @@ describe Globalize::Writer, globalize_db: true do
56
56
  it 'fills in the created_at and updated_at columns' do
57
57
  Timecop.freeze(Time.now) do
58
58
  @writer.write_content(@resource, 'es')
59
- translation = widget_translations.first
59
+ translation = widget_translations.connection.first
60
60
  expect(translation[:created_at].to_i).to eq(Time.now.utc.to_i)
61
61
  expect(translation[:updated_at].to_i).to eq(Time.now.utc.to_i)
62
62
  end
@@ -68,12 +68,12 @@ describe Globalize::Writer, globalize_db: true do
68
68
  today = Time.now + 1.day # groundhog day
69
69
 
70
70
  Timecop.freeze(today) do
71
- translation = widget_translations.first
71
+ translation = widget_translations.connection.first
72
72
  expect(translation[:updated_at].to_i).to_not eq(today.utc.to_i)
73
73
 
74
74
  # record already exists, so should get updated with new timestamp
75
75
  @writer.write_content(@resource, 'es')
76
- translation = widget_translations.first
76
+ translation = widget_translations.connection.first
77
77
  expect(translation[:updated_at].to_i).to eq(today.utc.to_i)
78
78
  end
79
79
  end
@@ -81,12 +81,12 @@ describe Globalize::Writer, globalize_db: true do
81
81
  end
82
82
 
83
83
  it 'updates the record if it already exists' do
84
- sprocket_id = widgets.insert(name: 'sprocket')
85
- sprocket_trans_id = widget_translations.insert(
84
+ sprocket_id = widgets.connection.insert(name: 'sprocket')
85
+ sprocket_trans_id = widget_translations.connection.insert(
86
86
  widget_id: sprocket_id, locale: 'es', name: 'sproqueta'
87
87
  )
88
88
 
89
- writer = Globalize::Writer.new(widget_translations_table)
89
+ writer = Globalize::Writer.new(widget_translations)
90
90
 
91
91
  content = YAML.dump(
92
92
  'widgets' => {
@@ -97,10 +97,10 @@ describe Globalize::Writer, globalize_db: true do
97
97
  resource = Txdb::TxResource.new(base_resource, content)
98
98
 
99
99
  expect { writer.write_content(resource, 'es') }.to_not(
100
- change { widget_translations.count }
100
+ change { widget_translations.connection.count }
101
101
  )
102
102
 
103
- translation = widget_translations.where(id: sprocket_trans_id).first
103
+ translation = widget_translations.connection.where(id: sprocket_trans_id).first
104
104
  expect(translation).to include(name: 'sproqueta2')
105
105
  end
106
106
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
  require 'tempfile'
4
4
  require 'yaml'
5
5
 
@@ -10,9 +10,23 @@ describe Txdb::Config do
10
10
  Txdb::Config.instance_variable_set(:@raw_config, nil)
11
11
  end
12
12
 
13
+ let(:config) do
14
+ {
15
+ databases: [
16
+ Txdb::TestConfigurator.base_config.tap do |base_config|
17
+ base_config[:tables] << {
18
+ name: 'my_table',
19
+ source_lang: 'en',
20
+ columns: []
21
+ }
22
+ end
23
+ ]
24
+ }
25
+ end
26
+
13
27
  describe '.databases' do
14
28
  it 'loads config from a string' do
15
- with_env('TXDB_CONFIG' => "raw://#{YAML.dump(TestDb.raw_config)}") do
29
+ with_env('TXDB_CONFIG' => "raw://#{YAML.dump(config)}") do
16
30
  expect(Txdb::Config.databases.size).to eq(1)
17
31
  database = Txdb::Config.databases.first
18
32
 
@@ -25,7 +39,7 @@ describe Txdb::Config do
25
39
 
26
40
  it 'loads config from a file' do
27
41
  file = Tempfile.new('translations')
28
- file.write(YAML.dump(TestDb.raw_config))
42
+ file.write(YAML.dump(config))
29
43
  file.flush
30
44
 
31
45
  with_env('TXDB_CONFIG' => "file://#{file.path}") do
@@ -45,14 +59,14 @@ describe Txdb::Config do
45
59
 
46
60
  describe '.each_table' do
47
61
  it 'returns an enumerator' do
48
- expect(Txdb::Config.each_table).to be_a(Enumerator)
62
+ with_env('TXDB_CONFIG' => "raw://#{YAML.dump(config)}") do
63
+ expect(Txdb::Config.each_table).to be_a(Enumerator)
64
+ end
49
65
  end
50
66
 
51
67
  it 'yields each table in each database' do
52
68
  # set up another database with another table so we can make sure the
53
69
  # method loops over more than one db, yielding tables from each
54
- config = TestDb.raw_config.dup
55
- config[:databases] = config[:databases].dup
56
70
  config[:databases] << config[:databases].first.merge(
57
71
  database: 'spec/test2.sqlite3',
58
72
  tables: [
@@ -1,18 +1,20 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
 
4
4
  include Txdb
5
5
 
6
- describe Database, test_db: true do
7
- let(:database) { TestDb.database }
6
+ describe Database, test_config: true do
7
+ let(:database) do
8
+ TestConfigurator.setup
9
+ end
8
10
 
9
11
  describe '#db' do
10
12
  it 'provides access to the database connection' do
11
- expect(database.db).to be_a(Sequel::SQLite::Database)
13
+ expect(database.connection).to be_a(Sequel::SQLite::Database)
12
14
  end
13
15
 
14
16
  it 'sets the max number of connections as specified in the config' do
15
- expect(database.db.pool.max_size).to eq(database.pool)
17
+ expect(database.connection.pool.max_size).to eq(database.pool)
16
18
  end
17
19
  end
18
20
 
@@ -1,11 +1,18 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
  require 'spec_helpers/test_backend'
4
4
 
5
5
  include Txdb
6
6
 
7
- describe Downloader, test_db: true do
8
- let(:database) { TestDb.database }
7
+ describe Downloader, test_config: true do
8
+ let(:database) do
9
+ TestConfigurator.setup do
10
+ create_table(:foo) do
11
+ primary_key :id
12
+ end
13
+ end
14
+ end
15
+
9
16
  let(:downloader) { Downloader.new(database) }
10
17
  let(:transifex_api) { double(:transifex_api) }
11
18
 
@@ -1,17 +1,24 @@
1
1
  require 'spec_helper'
2
2
  require 'spec_helpers/test_backend'
3
- require 'spec_helpers/test_db'
3
+ require 'spec_helpers/test_configurator'
4
4
  require 'uri'
5
5
  require 'yaml'
6
6
 
7
7
  include Txdb
8
8
  include Txdb::Handlers
9
9
 
10
- describe HookHandler do
10
+ describe HookHandler, test_config: true do
11
11
  include Rack::Test::Methods
12
12
 
13
- let(:database) { TestDb.database }
14
- let(:table) { database.tables.first }
13
+ let(:database) do
14
+ TestConfigurator.setup do
15
+ create_table(:foo) do
16
+ primary_key :id
17
+ end
18
+ end
19
+ end
20
+
21
+ let(:table) { database.find_table(:foo) }
15
22
  let(:project) { database.transifex_project }
16
23
  let(:resource) { TestBackend.resource }
17
24
 
@@ -1,16 +1,23 @@
1
1
  require 'spec_helper'
2
2
  require 'spec_helpers/test_backend'
3
- require 'spec_helpers/test_db'
3
+ require 'spec_helpers/test_configurator'
4
4
  require 'uri'
5
5
  require 'yaml'
6
6
 
7
7
  include Txdb::Handlers::Triggers
8
8
 
9
- describe PullHandler do
9
+ describe PullHandler, test_config: true do
10
10
  include Rack::Test::Methods
11
11
 
12
- let(:database) { TestDb.database }
13
- let(:table) { database.tables.first }
12
+ let(:database) do
13
+ Txdb::TestConfigurator.setup do
14
+ create_table(:foo) do
15
+ primary_key :id
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:table) { database.find_table(:foo) }
14
21
  let(:project) { database.transifex_project }
15
22
 
16
23
  def app
@@ -1,16 +1,23 @@
1
1
  require 'spec_helper'
2
2
  require 'spec_helpers/test_backend'
3
- require 'spec_helpers/test_db'
3
+ require 'spec_helpers/test_configurator'
4
4
  require 'uri'
5
5
  require 'yaml'
6
6
 
7
7
  include Txdb::Handlers::Triggers
8
8
 
9
- describe PushHandler do
9
+ describe PushHandler, test_config: true do
10
10
  include Rack::Test::Methods
11
11
 
12
- let(:database) { TestDb.database }
13
- let(:table) { database.tables.first }
12
+ let(:database) do
13
+ Txdb::TestConfigurator.setup do
14
+ create_table(:foo) do
15
+ primary_key :id
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:table) { database.find_table(:foo) }
14
21
  let(:project) { database.transifex_project }
15
22
 
16
23
  def app
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_configurator'
3
+
4
+ include Txdb::Iterators
5
+
6
+ describe AutoIncrementIterator, test_config: true do
7
+ let(:database) do
8
+ Txdb::TestConfigurator.setup do
9
+ create_table(:teams) do
10
+ primary_key :id
11
+ string :name, translate: true
12
+ source_lang 'en'
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:table) { database.tables.first }
18
+ let(:teams) { %w(seahawks warriors giants mariners sounders) }
19
+
20
+ let(:iterator) do
21
+ AutoIncrementIterator.new(table)
22
+ end
23
+
24
+ it 'iterates sequentially over every database entry' do
25
+ entries = teams.map { |team| { name: team } }
26
+ entries.each { |entry| table.connection << entry }
27
+
28
+ iterator.each do |db_entry|
29
+ entries.delete_if { |entry| db_entry[:name] == entry[:name] }
30
+ end
31
+
32
+ expect(entries).to be_empty
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'spec_helpers/test_configurator'
3
+
4
+ include Txdb::Iterators
5
+
6
+ describe GlobalizeIterator, test_config: true do
7
+ let(:database) do
8
+ Txdb::TestConfigurator.setup do
9
+ create_table(:teams) do
10
+ primary_key :id
11
+ string :name
12
+ end
13
+
14
+ create_table(:team_translations) do
15
+ primary_key :id
16
+ string :name, translate: true
17
+ string :locale
18
+ source_lang 'en'
19
+ end
20
+ end
21
+ end
22
+
23
+ let(:teams_table) { database.find_table(:teams) }
24
+ let(:team_translations_table) { database.find_table(:team_translations) }
25
+ let(:teams) { %w(seahawks warriors giants mariners sounders) }
26
+
27
+ let(:iterator) do
28
+ GlobalizeIterator.new(team_translations_table)
29
+ end
30
+
31
+ it 'iterates over the items in the parent table' do
32
+ teams.each do |team|
33
+ teams_table.connection << { name: team }
34
+ team_translations_table.connection << { name: "#{team}-es", locale: 'es' }
35
+ end
36
+
37
+ entries = iterator.map { |entry| entry[:name] }
38
+
39
+ # should be equivalent to the English team names, since it should have
40
+ # iterated over entries in the parent table, not the translations table
41
+ expect(entries.sort).to eq(teams.sort)
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helpers/test_configurator'
2
+
3
+ module Txdb
4
+ # The globalize configurator uses the functionality in the test configurator
5
+ # to create a couple of test tables for testing globalize-specific scenarios.
6
+ class GlobalizeConfigurator < TestConfigurator
7
+ class << self
8
+ def setup(&block)
9
+ super do
10
+ create_table(:widgets) do
11
+ primary_key :id
12
+ string :name
13
+ end
14
+
15
+ create_table(:widget_translations) do
16
+ primary_key :id
17
+ integer :widget_id
18
+ string :locale
19
+ string :name, translate: true
20
+ source_lang 'en'
21
+ end
22
+
23
+ block.call if block
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ RSpec.shared_context(:globalize) do
31
+ let(:database) { Txdb::GlobalizeConfigurator.setup }
32
+ let(:widgets) { database.find_table(:widgets) }
33
+ let(:widget_translations) { database.find_table(:widget_translations) }
34
+ end
35
+
36
+ RSpec.configure do |config|
37
+ config.around(:each) do |example|
38
+ Txdb::GlobalizeConfigurator.reset_db if example.metadata[:globalize_config]
39
+ example.run
40
+ end
41
+ end
@@ -0,0 +1,156 @@
1
+ require 'spec_helpers/env_helpers'
2
+ require 'spec_helpers/test_backend'
3
+ require 'yaml'
4
+
5
+ module Txdb
6
+ # The test configurator is responsible for creating test databases and tables.
7
+ # It creates actual SQLite tables and the corresponding Table and Database
8
+ # config objects that are usually constructed from config.yml. The SQLite
9
+ # database is deleted and old instances of TestConfigurator are released to
10
+ # the garbage collector before each test run. Set the test_config: true tag on
11
+ # your top-level RSpec describe blocks to activate this cleanup behavior.
12
+ #
13
+ # Example:
14
+ #
15
+ # describe MyClass, test_config: true do
16
+ # let(:database) do
17
+ # TestConfigurator.setup do
18
+ # create_table :my_table do
19
+ # primary_key :id
20
+ # string :name, translate: true
21
+ # end
22
+ # end
23
+ # end
24
+ # end
25
+ #
26
+ # Any field marked with translate: true will be added to the list of columns
27
+ # to translate in the corresponding Table object.
28
+ #
29
+ # TestConfigurator.setup returns an instance of Database, which can be used
30
+ # anywhere a Database instance is required. For example, you can use the
31
+ # return value to create a downloader:
32
+ #
33
+ # it 'downloads some stuff' do
34
+ # Txdb::Downloader.new(database).download('ko')
35
+ # end
36
+ class TestConfigurator
37
+ class << self
38
+ def setup(&block)
39
+ test_config = new.tap do |test_config|
40
+ test_config.instance_eval(&block) if block
41
+ end
42
+
43
+ databases << test_config.database
44
+ databases.last
45
+ end
46
+
47
+ def reset_db
48
+ databases.clear
49
+
50
+ if File.exist?('spec/test.sqlite3')
51
+ File.unlink('spec/test.sqlite3')
52
+ end
53
+ end
54
+
55
+ def databases
56
+ @databases ||= []
57
+ end
58
+
59
+ def base_config
60
+ {
61
+ adapter: 'sqlite',
62
+ backend: 'test-backend',
63
+ username: 'username',
64
+ password: 'password',
65
+ database: 'spec/test.sqlite3',
66
+ transifex: {
67
+ organization: 'myorg',
68
+ project_slug: 'myproject',
69
+ username: 'username',
70
+ password: 'password',
71
+ webhook_secret: '123abc'
72
+ },
73
+ tables: []
74
+ }
75
+ end
76
+ end
77
+
78
+ attr_reader :database
79
+
80
+ def initialize
81
+ @database = Txdb::Database.new(self.class.base_config)
82
+ end
83
+
84
+ def connection
85
+ database.connection
86
+ end
87
+
88
+ def create_table(name, &block)
89
+ # sequel won't create the table unless it has at least one column
90
+ connection.create_table(name) { integer :remove_me_blarg_blarg }
91
+ creator = TableCreator.new(name, database, &block)
92
+ database.tables << creator.table
93
+ connection.alter_table(name) { drop_column :remove_me_blarg_blarg }
94
+ end
95
+ end
96
+
97
+ class TableCreator
98
+ attr_reader :name, :database, :columns, :source_lang
99
+
100
+ def initialize(name, database, &block)
101
+ @name = name
102
+ @database = database
103
+ @columns = []
104
+ @first = true
105
+ instance_eval(&block)
106
+ end
107
+
108
+ def primary_key(column, *args)
109
+ connection.alter_table(name) { add_primary_key(column, *args) }
110
+ end
111
+
112
+ def string(column, *args)
113
+ add_column(column, :string, *args)
114
+ end
115
+
116
+ def integer(column, *args)
117
+ add_column(column, :integer, *args)
118
+ end
119
+
120
+ def source_lang(lang)
121
+ @source_lang = lang
122
+ end
123
+
124
+ def table
125
+ Txdb::Table.new(
126
+ database, {
127
+ name: name.to_s, columns: columns, source_lang: @source_lang
128
+ }
129
+ )
130
+ end
131
+
132
+ private
133
+
134
+ def add_column(column, type, *args)
135
+ columns << column if translate?(args)
136
+ connection.alter_table(name) { add_column(column, type, *args) }
137
+ end
138
+
139
+ def connection
140
+ database.connection
141
+ end
142
+
143
+ def translate?(args)
144
+ args.any? do |arg|
145
+ arg.is_a?(Hash) && arg[:translate]
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ RSpec.configure do |config|
152
+ config.around(:each) do |example|
153
+ Txdb::TestConfigurator.reset_db if example.metadata[:test_config]
154
+ example.run
155
+ end
156
+ end
@@ -1,17 +1,24 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
  require 'yaml'
4
4
 
5
5
  include Txdb
6
6
 
7
- describe Table, test_db: true do
8
- let(:database) { TestDb.database }
9
- let(:table) { database.tables.first }
7
+ describe Table, test_config: true do
8
+ let(:database) do
9
+ TestConfigurator.setup do
10
+ create_table(:my_table) do
11
+ primary_key :id
12
+ end
13
+ end
14
+ end
15
+
16
+ let(:table) { database.find_table(:my_table) }
10
17
 
11
- describe '#db' do
18
+ describe '#connection' do
12
19
  it 'returns a dataset primed to select from the table' do
13
- expect(table.db).to be_a(Sequel::Dataset)
14
- expect(table.db.sql).to eq('SELECT * FROM `my_table`')
20
+ expect(table.connection).to be_a(Sequel::Dataset)
21
+ expect(table.connection.sql).to eq('SELECT * FROM `my_table`')
15
22
  end
16
23
  end
17
24
 
Binary file
@@ -1,10 +1,13 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
 
4
4
  include Txdb
5
5
 
6
- describe TransifexProject, test_db: true do
7
- let(:database) { TestDb.database }
6
+ describe TransifexProject, test_config: true do
7
+ let(:database) do
8
+ TestConfigurator.setup
9
+ end
10
+
8
11
  let(:project) { database.transifex_project }
9
12
 
10
13
  describe '#api' do
@@ -1,11 +1,18 @@
1
1
  require 'spec_helper'
2
- require 'spec_helpers/test_db'
2
+ require 'spec_helpers/test_configurator'
3
3
  require 'spec_helpers/test_backend'
4
4
 
5
5
  include Txdb
6
6
 
7
- describe Uploader, test_db: true do
8
- let(:database) { TestDb.database }
7
+ describe Uploader, test_config: true do
8
+ let(:database) do
9
+ TestConfigurator.setup do
10
+ create_table(:foo) do
11
+ primary_key :id
12
+ end
13
+ end
14
+ end
15
+
9
16
  let(:uploader) { Uploader.new(database) }
10
17
  let(:transifex_api) { double(:transifex_api) }
11
18
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: txdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cameron Dutro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-27 00:00:00.000000000 Z
11
+ date: 2016-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -80,6 +80,9 @@ files:
80
80
  - lib/txdb/handlers/triggers/handler.rb
81
81
  - lib/txdb/handlers/triggers/pull_handler.rb
82
82
  - lib/txdb/handlers/triggers/push_handler.rb
83
+ - lib/txdb/iterators.rb
84
+ - lib/txdb/iterators/auto_increment_iterator.rb
85
+ - lib/txdb/iterators/globalize_iterator.rb
83
86
  - lib/txdb/response.rb
84
87
  - lib/txdb/response_helpers.rb
85
88
  - lib/txdb/table.rb
@@ -98,11 +101,13 @@ files:
98
101
  - spec/handlers/hook_handler_spec.rb
99
102
  - spec/handlers/triggers/pull_handler_spec.rb
100
103
  - spec/handlers/triggers/push_handler_spec.rb
104
+ - spec/iterators/auto_increment_iterator_spec.rb
105
+ - spec/iterators/globalize_iterator_spec.rb
101
106
  - spec/spec_helper.rb
102
107
  - spec/spec_helpers/env_helpers.rb
103
- - spec/spec_helpers/globalize_db.rb
108
+ - spec/spec_helpers/globalize_configurator.rb
104
109
  - spec/spec_helpers/test_backend.rb
105
- - spec/spec_helpers/test_db.rb
110
+ - spec/spec_helpers/test_configurator.rb
106
111
  - spec/table_spec.rb
107
112
  - spec/test.sqlite3
108
113
  - spec/transifex_project_spec.rb
@@ -1,60 +0,0 @@
1
- require 'spec_helpers/test_db'
2
-
3
- class GlobalizeDb < TestDb
4
- class << self
5
- def database
6
- @database ||= Txdb::Database.new(
7
- raw_config[:databases].first.merge(
8
- backend: Txdb::Backends.get('globalize'),
9
- tables: [{
10
- name: 'widget_translations',
11
- source_lang: 'en',
12
- columns: %w(name)
13
- }]
14
- )
15
- )
16
- end
17
-
18
- def setup_db
19
- db.create_table(:widgets) do
20
- primary_key :id
21
- string :name
22
- end
23
-
24
- db.create_table(:widget_translations) do
25
- primary_key :id
26
- integer :widget_id
27
- string :locale
28
- string :name
29
- end
30
- end
31
-
32
- def widgets
33
- db[:widgets]
34
- end
35
-
36
- def widget_translations
37
- db[:widget_translations]
38
- end
39
-
40
- def widget_translations_table
41
- database.tables.find do |table|
42
- table.name == 'widget_translations'
43
- end
44
- end
45
- end
46
- end
47
-
48
- RSpec.shared_context(:globalize) do
49
- let(:widgets) { GlobalizeDb.widgets }
50
- let(:widget_translations) { GlobalizeDb.widget_translations }
51
- let(:widget_translations_table) { GlobalizeDb.widget_translations_table }
52
- let(:database) { GlobalizeDb.database }
53
- end
54
-
55
- RSpec.configure do |config|
56
- config.around(:each) do |example|
57
- GlobalizeDb.reset_db if example.metadata[:globalize_db]
58
- example.run
59
- end
60
- end
@@ -1,76 +0,0 @@
1
- require 'spec_helpers/env_helpers'
2
- require 'spec_helpers/test_backend'
3
- require 'yaml'
4
-
5
- class TestDb
6
- class << self
7
- def db
8
- @db ||= database.db
9
- end
10
-
11
- def database
12
- @database ||= Txdb::Database.new(raw_config[:databases].first)
13
- end
14
-
15
- def db_path
16
- File.join(File.dirname(__FILE__), '../test.sqlite3')
17
- end
18
-
19
- def raw_config
20
- @config ||= deep_freeze({
21
- databases: [{
22
- adapter: 'sqlite',
23
- backend: 'test-backend',
24
- username: 'username',
25
- password: 'password',
26
- database: 'spec/test.sqlite3',
27
- transifex: {
28
- organization: 'myorg',
29
- project_slug: 'myproject',
30
- username: 'username',
31
- password: 'password',
32
- webhook_secret: '123abc'
33
- },
34
- tables: [{
35
- name: 'my_table',
36
- source_lang: 'en',
37
- columns: %w(my_column)
38
- }]
39
- }]
40
- })
41
- end
42
-
43
- def reset_db
44
- db.tables.each { |t| db.drop_table(t) }
45
- setup_db
46
- end
47
-
48
- def setup_db
49
- # no-op
50
- end
51
-
52
- private
53
-
54
- def deep_freeze(obj)
55
- case obj
56
- when Hash
57
- obj.each_with_object({}) do |(k, v), ret|
58
- ret[k] = deep_freeze(v)
59
- end.freeze
60
-
61
- when Array
62
- obj.map { |elem| deep_freeze(elem) }.freeze
63
-
64
- else
65
- obj
66
- end
67
- end
68
- end
69
- end
70
-
71
- RSpec.configure do |config|
72
- config.around(:each) do |example|
73
- TestDb.reset_db if example.metadata[:test_db]
74
- example.run
75
- end
76
- end