txdb 1.0.1 → 1.1.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: 51610845d38e64996c61cf4079ba3a41125cd848
4
- data.tar.gz: 5587fd9b799ed26f04f81358e19ee4eb64cb59a5
3
+ metadata.gz: 0e59bfc3e60354b89d0a572dc8639ecc1bec5146
4
+ data.tar.gz: 05599e91b876f536edabd4f05163f769fbf2a2c5
5
5
  SHA512:
6
- metadata.gz: efae7ded7c1f025b5fb2df089f83e93b4015028f6cf9c9a8653e3cb0c330e1e9a37477fdb0067dba5e3ee46b04cac6aa7cd6186d50df1d3220c3a91e24778820
7
- data.tar.gz: 77b6edd9f4d7ec885727216b7a8fe57da44556d3681203862cdcef389b5af080bcf9c97a38f4d32f6b7edc8cf9973db10168e20b0c810ad315e12a362854a79f
6
+ metadata.gz: 7903d1a0966bc7428dce7de537418ba437e06e48ec95032c4fb21bcc513c8703552c28183be6e23b6271b2f5b921d8ebe5eb4e27500c005c3316590daa84f7a2
7
+ data.tar.gz: 470a4c9d4d8df0a31f8d8c1275384dab4ba8c487266a6093ad44299ba42e12f61ea0b750e1c814a9b5c2e289204b1b110b83bf8aa5c93c204beb2d74cd3a21e4
@@ -0,0 +1,18 @@
1
+ require 'txgh'
2
+
3
+ module Txgh
4
+ class TxResource
5
+ class << self
6
+ def from_api_response(project_slug, response)
7
+ new(
8
+ project_slug,
9
+ response['slug'],
10
+ response['i18n_type'],
11
+ response['source_language_code'],
12
+ response['name'],
13
+ '', nil
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
data/lib/txdb.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'ext/txgh/tx_resource'
2
+
1
3
  module Txdb
2
4
  autoload :Application, 'txdb/app'
3
5
  autoload :Backends, 'txdb/backends'
@@ -3,13 +3,19 @@ module Txdb
3
3
  module Globalize
4
4
 
5
5
  class Backend
6
+ RESOURCE_TYPE = 'YML'
7
+
6
8
  class << self
7
9
  def read_content_from(table)
8
10
  Reader.new(table).read_content
9
11
  end
10
12
 
11
- def write_content_to(table, content, locale)
12
- Writer.new(table).write_content(content, locale)
13
+ def write_content_to(table, resource, locale)
14
+ Writer.new(table).write_content(resource, locale)
15
+ end
16
+
17
+ def owns_resource?(table, resource)
18
+ resource.resource_slug == Helpers.resource_slug_for(table)
13
19
  end
14
20
  end
15
21
  end
@@ -10,6 +10,10 @@ module Txdb
10
10
  table_name.sub(/_translations\z/, '')
11
11
  )
12
12
  end
13
+
14
+ def resource_slug_for(table)
15
+ Txgh::Utils.slugify("#{table.database.database}-#{table.name}")
16
+ end
13
17
  end
14
18
 
15
19
  Helpers.extend(Helpers)
@@ -1,3 +1,5 @@
1
+ require 'txgh'
2
+
1
3
  module Txdb
2
4
  module Backends
3
5
  module Globalize
@@ -12,11 +14,42 @@ module Txdb
12
14
  end
13
15
 
14
16
  def read_content
15
- { origin_table_name(table.name) => content_for_records }
17
+ [Txdb::TxResource.new(resource, serialized_content)]
16
18
  end
17
19
 
18
20
  private
19
21
 
22
+ def resource
23
+ @resource ||= Txgh::TxResource.new(
24
+ project_slug, resource_slug, Globalize::Backend::RESOURCE_TYPE,
25
+ source_lang, source_file, nil, nil
26
+ )
27
+ end
28
+
29
+ def project_slug
30
+ table.database.transifex_project.project_slug
31
+ end
32
+
33
+ def resource_slug
34
+ resource_slug_for(table)
35
+ end
36
+
37
+ def source_lang
38
+ table.source_lang
39
+ end
40
+
41
+ def source_file
42
+ table.name
43
+ end
44
+
45
+ def serialized_content
46
+ YAML.dump(content)
47
+ end
48
+
49
+ def content
50
+ @content ||= { origin_table_name(table.name) => content_for_records }
51
+ end
52
+
20
53
  def content_for_records
21
54
  each_record.each_with_object({}) do |record, ret|
22
55
  ret[record[:id]] = content_for_record(record)
@@ -13,22 +13,48 @@ module Txdb
13
13
  @table = table
14
14
  end
15
15
 
16
- def write_content(content, locale)
17
- content[origin_table_name(table.name)].each_pair do |id, fields|
18
- row = table.db.where(foreign_key.to_sym => id, locale: locale)
19
-
20
- if row.empty?
21
- table.db << fields.merge(
22
- foreign_key.to_sym => id, locale: locale
23
- )
24
- else
25
- row.update(fields)
26
- end
16
+ def write_content(resource, locale)
17
+ content = deserialize_content(resource.content)
18
+ content = content.fetch(origin_table_name(table.name), {})
19
+
20
+ content.each_pair do |id, fields|
21
+ update_row(id, fields, locale)
27
22
  end
28
23
  end
29
24
 
30
25
  private
31
26
 
27
+ def update_row(id, fields, locale)
28
+ row = table.db.where(foreign_key.to_sym => id, locale: locale)
29
+
30
+ if row.empty?
31
+ table.db << fields
32
+ .merge(foreign_key.to_sym => id, locale: locale)
33
+ .merge(created_at)
34
+ .merge(updated_at)
35
+ else
36
+ row.update(fields.merge(updated_at))
37
+ end
38
+ end
39
+
40
+ def created_at
41
+ return {} unless table.db.columns.include?(:created_at)
42
+ { created_at: get_utc_time }
43
+ end
44
+
45
+ def updated_at
46
+ return {} unless table.db.columns.include?(:updated_at)
47
+ { updated_at: get_utc_time }
48
+ end
49
+
50
+ def get_utc_time
51
+ Time.now.utc
52
+ end
53
+
54
+ def deserialize_content(content)
55
+ YAML.load(content)
56
+ end
57
+
32
58
  def foreign_key
33
59
  @foreign_key ||= table.name.sub(/_translations/, '_id')
34
60
  end
@@ -1,3 +1,5 @@
1
+ require 'txgh'
2
+
1
3
  module Txdb
2
4
  class Downloader
3
5
  class << self
@@ -19,14 +21,38 @@ module Txdb
19
21
  end
20
22
 
21
23
  def download_table(table, locale)
22
- content = transifex_api.download(table.resource, locale)
23
- table.write_content(content, locale)
24
+ resources.each do |tx_resource|
25
+ next unless process_resource?(tx_resource, table)
26
+ download_resource(tx_resource, table, locale)
27
+ end
28
+ end
29
+
30
+ def download_resource(tx_resource, table, locale)
31
+ content = transifex_api.download(tx_resource, locale)
32
+ resource = Txdb::TxResource.new(tx_resource, content)
33
+ table.write_content(resource, locale)
24
34
  end
25
35
 
26
36
  private
27
37
 
38
+ def process_resource?(resource, table)
39
+ database.backend.owns_resource?(table, resource)
40
+ end
41
+
42
+ def project_slug
43
+ database.transifex_project.project_slug
44
+ end
45
+
28
46
  def transifex_api
29
47
  database.transifex_api
30
48
  end
49
+
50
+ def resources
51
+ @resources ||= transifex_api
52
+ .get_resources(project_slug)
53
+ .map do |resource_hash|
54
+ Txgh::TxResource.from_api_response(project_slug, resource_hash)
55
+ end
56
+ end
31
57
  end
32
58
  end
@@ -19,11 +19,8 @@ module Txdb
19
19
  end
20
20
 
21
21
  def handle
22
- tables.each do |table|
23
- content = table.database.transifex_api.download(table.resource, locale)
24
- table.write_content(content, locale)
25
- end
26
-
22
+ return respond_with_error(401, 'Unauthorized') unless authentic_request?
23
+ downloader.download_resource(resource, table, locale)
27
24
  respond_with(200, {})
28
25
  rescue => e
29
26
  respond_with_error(500, "Internal server error: #{e.message}", e)
@@ -31,23 +28,54 @@ module Txdb
31
28
 
32
29
  private
33
30
 
34
- def locale
35
- payload['language']
31
+ def downloader
32
+ @downloader ||= Txdb::Downloader.new(database)
36
33
  end
37
34
 
38
- def tables
39
- @tables ||= Txdb::Config.each_table.select do |table|
40
- table.resource.resource_slug == payload['resource'] &&
41
- authentic_request?(table.database.transifex_project)
35
+ def database
36
+ @database ||= Txdb::Config.databases.find do |database|
37
+ database.transifex_project.project_slug == project_slug
42
38
  end
43
39
  end
44
40
 
45
- def authentic_request?(project)
41
+ def table
42
+ @table ||= database.tables.find do |table|
43
+ database.backend.owns_resource?(table, resource)
44
+ end
45
+ end
46
+
47
+ def resource
48
+ @resource ||= Txgh::TxResource.from_api_response(
49
+ project_slug, transifex_api.get_resource(project_slug, resource_slug)
50
+ )
51
+ end
52
+
53
+ def transifex_project
54
+ database.transifex_project
55
+ end
56
+
57
+ def authentic_request?
46
58
  Txgh::TransifexRequestAuth.authentic_request?(
47
- request, project.webhook_secret
59
+ request, transifex_project.webhook_secret
48
60
  )
49
61
  end
50
62
 
63
+ def transifex_api
64
+ database.transifex_api
65
+ end
66
+
67
+ def project_slug
68
+ payload['project']
69
+ end
70
+
71
+ def resource_slug
72
+ payload['resource']
73
+ end
74
+
75
+ def locale
76
+ payload['language']
77
+ end
78
+
51
79
  def payload
52
80
  @payload ||= begin
53
81
  request.body.rewind
@@ -24,26 +24,17 @@ module Txdb
24
24
  respond_with_error(500, "Internal server error: #{e.message}", e)
25
25
  end
26
26
 
27
- def databases
28
- @databases ||= if database_name = request.params['database']
29
- Txdb::Config.databases.select do |database|
30
- database.database == database_name
31
- end
32
- else
33
- Txdb::Config.databases
27
+ def database
28
+ @database ||= Txdb::Config.databases.find do |database|
29
+ database.database == request.params['database']
34
30
  end
35
31
  end
36
32
 
37
- def tables
38
- @tables ||= each_table_in(databases).select do |table|
33
+ def table
34
+ @table ||= database.tables.find do |table|
39
35
  table.name == request.params['table']
40
36
  end
41
37
  end
42
-
43
- def each_table_in(databases, &block)
44
- return to_enum(__method__, databases) unless block_given?
45
- databases.each { |database| database.tables.each(&block) }
46
- end
47
38
  end
48
39
  end
49
40
  end
@@ -5,10 +5,8 @@ module Txdb
5
5
  class PullHandler < Handler
6
6
  def handle
7
7
  handle_safely do
8
- tables.each do |table|
9
- locales_for(table).each do |locale|
10
- Downloader.new(table.database).download_table(table, locale)
11
- end
8
+ locales.each do |locale|
9
+ downloader.download_table(table, locale)
12
10
  end
13
11
 
14
12
  respond_with(200, {})
@@ -17,15 +15,14 @@ module Txdb
17
15
 
18
16
  private
19
17
 
20
- def locales_for(table)
21
- locale_cache[table.resource.project_slug] ||=
22
- table.database.transifex_api
23
- .get_languages(table.resource.project_slug)
24
- .map { |locale| locale['language_code'] }
18
+ def downloader
19
+ @downloader ||= Downloader.new(database)
25
20
  end
26
21
 
27
- def locale_cache
28
- @locale_cache ||= {}
22
+ def locales
23
+ database.transifex_api
24
+ .get_languages(database.transifex_project.project_slug)
25
+ .map { |locale| locale['language_code'] }
29
26
  end
30
27
  end
31
28
 
@@ -5,10 +5,7 @@ module Txdb
5
5
  class PushHandler < Handler
6
6
  def handle
7
7
  handle_safely do
8
- tables.each do |table|
9
- Uploader.new(table.database).upload_table(table)
10
- end
11
-
8
+ Uploader.new(database).upload_table(table)
12
9
  respond_with(200, {})
13
10
  end
14
11
  end
data/lib/txdb/table.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'txgh'
2
- require 'yaml'
3
2
 
4
3
  module Txdb
5
4
  class Table
@@ -17,20 +16,12 @@ module Txdb
17
16
  database.db.from(name)
18
17
  end
19
18
 
20
- def resource
21
- @resource ||= Txdb::TxResource.from_table(self)
22
- end
23
-
24
19
  def read_content
25
- YAML.dump(
26
- database.backend.read_content_from(self)
27
- )
20
+ database.backend.read_content_from(self)
28
21
  end
29
22
 
30
- def write_content(content, locale)
31
- database.backend.write_content_to(
32
- self, YAML.load(content), locale
33
- )
23
+ def write_content(resource, locale)
24
+ database.backend.write_content_to(self, resource, locale)
34
25
  end
35
26
  end
36
27
  end
@@ -1,52 +1,18 @@
1
- require 'txgh'
2
-
3
1
  module Txdb
4
2
  class TxResource
5
- RESOURCE_TYPE = 'YML'
6
-
7
- class << self
8
- def from_table(table)
9
- # project_slug, resource_slug, type, source_lang, source_file,
10
- # lang_map, translation_file
11
- new(
12
- Txgh::TxResource.new(
13
- project_slug(table), resource_slug(table), RESOURCE_TYPE,
14
- source_lang(table), source_file(table), nil, nil
15
- )
16
- )
17
- end
18
-
19
- private
20
-
21
- def project_slug(table)
22
- table.database.transifex_project.project_slug
23
- end
24
-
25
- def resource_slug(table)
26
- Txgh::Utils.slugify("#{table.database.database}-#{table.name}")
27
- end
28
-
29
- def source_lang(table)
30
- table.source_lang
31
- end
32
-
33
- def source_file(table)
34
- table.name
35
- end
36
- end
37
-
38
- attr_reader :resource
3
+ attr_reader :original, :content
39
4
 
40
- def initialize(resource)
41
- @resource = resource
5
+ def initialize(original, content)
6
+ @original = original
7
+ @content = content
42
8
  end
43
9
 
44
10
  def respond_to?(method)
45
- resource.respond_to?(method)
11
+ original.respond_to?(method)
46
12
  end
47
13
 
48
14
  def method_missing(method, *args, &block)
49
- resource.send(method, *args, &block)
15
+ original.send(method, *args, &block)
50
16
  end
51
17
  end
52
18
  end
data/lib/txdb/uploader.rb CHANGED
@@ -19,9 +19,11 @@ module Txdb
19
19
  end
20
20
 
21
21
  def upload_table(table)
22
- transifex_api.create_or_update(
23
- table.resource, table.read_content
24
- )
22
+ table.read_content.each do |resource|
23
+ transifex_api.create_or_update(
24
+ resource.original, resource.content
25
+ )
26
+ end
25
27
  end
26
28
 
27
29
  private
data/lib/txdb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Txdb
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
+ require 'spec_helpers/test_db'
2
3
 
3
4
  include Txdb::Backends
4
5
 
5
- describe Globalize::Helpers do
6
+ describe Globalize::Helpers, test_db: true do
6
7
  describe '.origin_table_name' do
7
8
  it 'pluralizes and removes the translations suffix' do
8
9
  origin = Globalize::Helpers.origin_table_name('widget_translations')
@@ -14,4 +15,15 @@ describe Globalize::Helpers do
14
15
  expect(origin).to eq('oxen')
15
16
  end
16
17
  end
18
+
19
+ describe '#resource_slug_for' do
20
+ let(:database) { TestDb.database }
21
+ let(:table) { database.tables.first }
22
+
23
+ it 'constructs a slug from the database and table names' do
24
+ expect(Globalize::Helpers.resource_slug_for(table)).to eq(
25
+ 'spec_test.sqlite3-my_table'
26
+ )
27
+ end
28
+ end
17
29
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'spec_helpers/globalize_db'
3
+ require 'yaml'
3
4
 
4
5
  include Txdb::Backends
5
6
 
@@ -7,19 +8,31 @@ describe Globalize::Reader, globalize_db: true do
7
8
  include_context :globalize
8
9
 
9
10
  describe '#read_content' do
10
- it 'reads data from the given table and puts it into a hash' do
11
+ it 'reads data from the given table and returns an array of resources' do
11
12
  sprocket_id = widgets.insert(name: 'sprocket')
12
13
  flange_id = widgets.insert(name: 'flange')
13
14
  widget_translations.insert(widget_id: sprocket_id, locale: 'es', name: 'sproqueta')
14
15
  widget_translations.insert(widget_id: flange_id, locale: 'es', name: 'flango')
15
16
 
16
17
  reader = Globalize::Reader.new(widget_translations_table)
17
- expect(reader.read_content).to eq({
18
- 'widgets' => {
19
- 1 => { 'name' => 'sprocket' },
20
- 2 => { 'name' => 'flange' }
21
- }
22
- })
18
+ resources = reader.read_content
19
+ expect(resources.size).to eq(1)
20
+ resource = resources.first
21
+
22
+ expect(resource.source_file).to eq(widget_translations_table.name)
23
+ expect(resource.project_slug).to eq(database.transifex_project.project_slug)
24
+ expect(resource.resource_slug).to(
25
+ eq(Globalize::Helpers.resource_slug_for(widget_translations_table))
26
+ )
27
+
28
+ expect(resource.content).to eq(
29
+ YAML.dump(
30
+ 'widgets' => {
31
+ 1 => { 'name' => 'sprocket' },
32
+ 2 => { 'name' => 'flange' }
33
+ }
34
+ )
35
+ )
23
36
  end
24
37
  end
25
38
  end
@@ -1,5 +1,8 @@
1
+ require 'active_support/core_ext/numeric/time'
1
2
  require 'spec_helper'
2
3
  require 'spec_helpers/globalize_db'
4
+ require 'timecop'
5
+ require 'yaml'
3
6
 
4
7
  include Txdb::Backends
5
8
 
@@ -7,25 +10,74 @@ describe Globalize::Writer, globalize_db: true do
7
10
  include_context :globalize
8
11
 
9
12
  describe '#write_content' do
10
- it 'inserts the translations into the database' do
11
- sprocket_id = widgets.insert(name: 'sprocket')
12
- writer = Globalize::Writer.new(widget_translations_table)
13
+ let(:base_resource) do
14
+ # project_slug, resource_slug, type, source_lang, source_file,
15
+ # lang_map, translation_file
16
+ Txgh::TxResource.new(
17
+ 'project_slug', 'resource_slug', Globalize::Backend::RESOURCE_TYPE,
18
+ 'source_lang', 'source_file', nil, nil
19
+ )
20
+ end
13
21
 
14
- content = {
15
- 'widgets' => {
16
- sprocket_id => { name: 'sproqueta' }
17
- }
18
- }
22
+ context 'with some content' do
23
+ before(:each) do
24
+ @sprocket_id = widgets.insert(name: 'sprocket')
25
+ @writer = Globalize::Writer.new(widget_translations_table)
19
26
 
20
- expect { writer.write_content(content, 'es') }.to(
21
- change { widget_translations.count }.from(0).to(1)
22
- )
27
+ @content = YAML.dump(
28
+ 'widgets' => {
29
+ @sprocket_id => { name: 'sproqueta' }
30
+ }
31
+ )
23
32
 
24
- translation = widget_translations.first
33
+ @resource = Txdb::TxResource.new(base_resource, @content)
34
+ end
25
35
 
26
- expect(translation).to include(
27
- widget_id: sprocket_id, name: 'sproqueta', locale: 'es'
28
- )
36
+ it 'inserts the translations into the database' do
37
+ expect { @writer.write_content(@resource, 'es') }.to(
38
+ change { widget_translations.count }.from(0).to(1)
39
+ )
40
+
41
+ translation = widget_translations.first
42
+
43
+ expect(translation).to include(
44
+ widget_id: @sprocket_id, name: 'sproqueta', locale: 'es'
45
+ )
46
+ end
47
+
48
+ context 'with created_at and updated_at columns' do
49
+ before(:each) do
50
+ GlobalizeDb.db.alter_table(:widget_translations) do
51
+ add_column :created_at, Time
52
+ add_column :updated_at, Time
53
+ end
54
+ end
55
+
56
+ it 'fills in the created_at and updated_at columns' do
57
+ Timecop.freeze(Time.now) do
58
+ @writer.write_content(@resource, 'es')
59
+ translation = widget_translations.first
60
+ expect(translation[:created_at].to_i).to eq(Time.now.utc.to_i)
61
+ expect(translation[:updated_at].to_i).to eq(Time.now.utc.to_i)
62
+ end
63
+ end
64
+
65
+ it 'updates the updated_at column if the record already exists' do
66
+ @writer.write_content(@resource, 'es')
67
+
68
+ today = Time.now + 1.day # groundhog day
69
+
70
+ Timecop.freeze(today) do
71
+ translation = widget_translations.first
72
+ expect(translation[:updated_at].to_i).to_not eq(today.utc.to_i)
73
+
74
+ # record already exists, so should get updated with new timestamp
75
+ @writer.write_content(@resource, 'es')
76
+ translation = widget_translations.first
77
+ expect(translation[:updated_at].to_i).to eq(today.utc.to_i)
78
+ end
79
+ end
80
+ end
29
81
  end
30
82
 
31
83
  it 'updates the record if it already exists' do
@@ -36,13 +88,15 @@ describe Globalize::Writer, globalize_db: true do
36
88
 
37
89
  writer = Globalize::Writer.new(widget_translations_table)
38
90
 
39
- content = {
91
+ content = YAML.dump(
40
92
  'widgets' => {
41
93
  sprocket_id => { name: 'sproqueta2' }
42
94
  }
43
- }
95
+ )
96
+
97
+ resource = Txdb::TxResource.new(base_resource, content)
44
98
 
45
- expect { writer.write_content(content, 'es') }.to_not(
99
+ expect { writer.write_content(resource, 'es') }.to_not(
46
100
  change { widget_translations.count }
47
101
  )
48
102
 
@@ -5,7 +5,7 @@ require 'spec_helpers/test_backend'
5
5
  include Txdb
6
6
 
7
7
  describe Downloader, test_db: true do
8
- let(:database) { Txdb::Config.databases.first }
8
+ let(:database) { TestDb.database }
9
9
  let(:downloader) { Downloader.new(database) }
10
10
  let(:transifex_api) { double(:transifex_api) }
11
11
 
@@ -17,20 +17,38 @@ describe Downloader, test_db: true do
17
17
 
18
18
  describe '#download' do
19
19
  it 'downloads translations from Transifex and writes them to the db' do
20
+ expect(transifex_api).to(
21
+ receive(:get_resources)
22
+ .with(database.transifex_project.project_slug)
23
+ .and_return([{
24
+ 'slug' => 'fake_resource_slug',
25
+ 'i18n_type' => 'fake_i18n_type',
26
+ 'source_language_code' => 'en',
27
+ 'name' => 'fake_name',
28
+ }])
29
+ )
30
+
31
+ content = YAML.dump({ foo: 'bar' })
32
+
20
33
  expect(transifex_api).to receive(:download) do |resource, locale|
21
34
  expect(resource.project_slug).to eq('myproject')
22
- expect(resource.resource_slug).to eq('spec_test.sqlite3-my_table')
35
+ expect(resource.resource_slug).to eq('fake_resource_slug')
23
36
  expect(locale).to eq('es')
24
- YAML.dump('widgets')
37
+ content
25
38
  end
26
39
 
27
40
  expect { downloader.download('es') }.to(
28
41
  change { TestBackend.writes.size }.from(0).to(1)
29
42
  )
30
43
 
31
- expect(TestBackend.writes.first).to eq(
32
- table: database.tables.first.name, locale: 'es', content: 'widgets'
33
- )
44
+ write = TestBackend.writes.first
45
+ expect(write[:table]).to eq(database.tables.first.name)
46
+ expect(write[:locale]).to eq('es')
47
+
48
+ expect(write[:resource]).to be_a(Txdb::TxResource)
49
+ expect(write[:resource].project_slug).to eq('myproject')
50
+ expect(write[:resource].resource_slug).to eq('fake_resource_slug')
51
+ expect(write[:resource].content).to eq(content)
34
52
  end
35
53
  end
36
54
  end
@@ -4,6 +4,7 @@ require 'spec_helpers/test_db'
4
4
  require 'uri'
5
5
  require 'yaml'
6
6
 
7
+ include Txdb
7
8
  include Txdb::Handlers
8
9
 
9
10
  describe HookHandler do
@@ -12,6 +13,16 @@ describe HookHandler do
12
13
  let(:database) { TestDb.database }
13
14
  let(:table) { database.tables.first }
14
15
  let(:project) { database.transifex_project }
16
+ let(:resource) { TestBackend.resource }
17
+
18
+ let(:body) { URI.encode_www_form(params.to_a) }
19
+ let(:params) do
20
+ {
21
+ 'project' => resource.project_slug,
22
+ 'resource' => resource.resource_slug,
23
+ 'language' => 'es'
24
+ }
25
+ end
15
26
 
16
27
  def app
17
28
  Txdb::Hooks
@@ -21,48 +32,49 @@ describe HookHandler do
21
32
  allow(Txdb::Config).to receive(:databases).and_return([database])
22
33
  end
23
34
 
24
- def sign(body)
25
- Txgh::TransifexRequestAuth.header_value(
26
- body, project.webhook_secret
27
- )
28
- end
29
-
30
35
  it "doesn't write content when unauthorized" do
31
- params = { 'resource' => table.resource.resource_slug, 'language' => 'es' }
32
- body = URI.encode_www_form(params.to_a)
33
36
  post '/transifex', body
34
37
 
35
- expect(last_response.status).to eq(200)
36
- expect(last_response.body).to eq('{}')
38
+ expect(last_response.status).to eq(401)
39
+ expect(JSON.parse(last_response.body)).to eq([{ 'error' => 'Unauthorized' }])
37
40
 
38
41
  expect(Txdb::TestBackend.writes).to be_empty
39
42
  end
40
43
 
41
44
  context 'with an authorized request' do
42
45
  let(:content) { { 'phrase' => 'trans' } }
43
- let(:params) { { 'resource' => table.resource.resource_slug, 'language' => 'es' } }
44
- let(:body) { URI.encode_www_form(params.to_a) }
45
- let(:headers) { { Txgh::TransifexRequestAuth::RACK_HEADER => sign(body) } }
46
+
47
+ before(:each) do
48
+ header(
49
+ Txgh::TransifexRequestAuth::TRANSIFEX_HEADER,
50
+ Txgh::TransifexRequestAuth.header_value(body, project.webhook_secret)
51
+ )
52
+ end
46
53
 
47
54
  it 'downloads and writes new content to the database' do
55
+ expect(project.api).to receive(:get_resource).and_return(resource.to_api_h)
48
56
  expect(project.api).to receive(:download).and_return(YAML.dump(content))
49
57
 
50
- expect { post('/transifex', body, headers) }.to(
58
+ expect { post('/transifex', body) }.to(
51
59
  change { Txdb::TestBackend.writes.size }.from(0).to(1)
52
60
  )
53
61
 
54
62
  expect(last_response.status).to eq(200)
55
63
  expect(last_response.body).to eq('{}')
56
64
 
57
- expect(Txdb::TestBackend.writes).to include(
58
- locale: 'es', table: table.name, content: content
59
- )
65
+ write = Txdb::TestBackend.writes.first
66
+
67
+ expect(write[:locale]).to eq('es')
68
+ expect(write[:table]).to eq(table.name)
69
+ expect(write[:resource]).to be_a(Txdb::TxResource)
70
+ expect(write[:resource].project_slug).to eq(resource.project_slug)
71
+ expect(write[:resource].resource_slug).to eq(resource.resource_slug)
60
72
  end
61
73
 
62
74
  it 'reports errors' do
63
- expect(project.api).to receive(:download).and_raise('jelly beans')
75
+ expect(project.api).to receive(:get_resource).and_raise('jelly beans')
64
76
 
65
- post '/transifex', body, headers
77
+ post '/transifex', body
66
78
 
67
79
  expect(last_response.status).to eq(500)
68
80
  expect(JSON.parse(last_response.body)).to eq(
@@ -28,8 +28,12 @@ describe PullHandler do
28
28
  it 'downloads the table for each locale' do
29
29
  locales = [{ 'language_code' => 'es' }, { 'language_code' => 'ja' }]
30
30
  content = { 'phrase' => 'trans' }
31
+
31
32
  expect(database.transifex_api).to receive(:get_languages).and_return(locales)
32
33
  allow(database.transifex_api).to receive(:download).and_return(YAML.dump(content))
34
+ expect(database.transifex_api).to receive(:get_resources).and_return(
35
+ [Txdb::TestBackend.resource.to_api_h]
36
+ )
33
37
 
34
38
  expect { patch('/pull', params) }.to(
35
39
  change { Txdb::TestBackend.writes.size }.from(0).to(2)
@@ -38,13 +42,20 @@ describe PullHandler do
38
42
  expect(last_response.status).to eq(200)
39
43
  expect(last_response.body).to eq('{}')
40
44
 
41
- expect(Txdb::TestBackend.writes).to include(
42
- locale: 'es', table: table.name, content: content
43
- )
45
+ expect(Txdb::TestBackend.writes.first[:locale]).to eq('es')
46
+ expect(Txdb::TestBackend.writes.last[:locale]).to eq('ja')
44
47
 
45
- expect(Txdb::TestBackend.writes).to include(
46
- locale: 'ja', table: table.name, content: content
47
- )
48
+ Txdb::TestBackend.writes.each do |write|
49
+ expect(write[:table]).to eq(table.name)
50
+
51
+ expect(write[:resource].project_slug).to(
52
+ eq(Txdb::TestBackend.resource.project_slug)
53
+ )
54
+
55
+ expect(write[:resource].resource_slug).to(
56
+ eq(Txdb::TestBackend.resource.resource_slug)
57
+ )
58
+ end
48
59
  end
49
60
 
50
61
  it 'reports errors' do
data/spec/spec_helper.rb CHANGED
@@ -9,6 +9,8 @@ require 'txdb'
9
9
  require 'spec_helpers/env_helpers'
10
10
  require 'spec_helpers/test_backend'
11
11
 
12
+ Sequel.default_timezone = :utc
13
+
12
14
  RSpec.configure do |config|
13
15
  config.before(:each) do
14
16
  Txdb::TestBackend.reset
@@ -16,13 +16,32 @@ module Txdb
16
16
 
17
17
  def read_content_from(table)
18
18
  reads << { table: table.name }
19
- {}
19
+ [resource]
20
20
  end
21
21
 
22
- def write_content_to(table, content, locale)
23
- writes << { table: table.name, content: content, locale: locale }
22
+ def write_content_to(table, resource, locale)
23
+ writes << { table: table.name, resource: resource, locale: locale }
24
24
  nil
25
25
  end
26
+
27
+ def owns_resource?(table, resource)
28
+ true
29
+ end
30
+
31
+ def base_resource
32
+ @base_resource ||= Txgh::TxResource.new(
33
+ 'myproject', 'resource_slug', 'type',
34
+ 'source_lang', 'source_file', nil, nil
35
+ )
36
+ end
37
+
38
+ def content
39
+ @content ||= 'fake content'
40
+ end
41
+
42
+ def resource
43
+ @resource ||= Txdb::TxResource.new(base_resource, content)
44
+ end
26
45
  end
27
46
  end
28
47
  end
data/spec/table_spec.rb CHANGED
@@ -15,44 +15,23 @@ describe Table, test_db: true do
15
15
  end
16
16
  end
17
17
 
18
- describe '#resource' do
19
- it 'creates a TxResource from the table' do
20
- resource = table.resource
21
- expect(resource).to be_a(Txdb::TxResource)
22
- expect(resource.project_slug).to eq('myproject')
23
- expect(resource.resource_slug).to eq(
24
- Txgh::Utils.slugify("#{database.database}-#{table.name}")
25
- )
26
- expect(resource.source_file).to eq(table.name)
27
- expect(resource.source_lang).to eq('en')
28
- end
29
- end
30
-
31
18
  describe '#read_content' do
32
- let(:content) { { foo: 'bar' } }
33
-
34
- it 'dumps the content in YAML format' do
35
- expect(database.backend).to(
36
- receive(:read_content_from).and_return(content)
37
- )
38
-
39
- expect(table.read_content).to eq(YAML.dump(content))
19
+ it 'proxies to the backend' do
20
+ expect(database.backend).to receive(:read_content_from)
21
+ table.read_content
40
22
  end
41
23
  end
42
24
 
43
25
  describe '#write_content' do
44
- let(:content) { { foo: 'bar' } }
45
- let(:locale) { 'es' }
46
-
47
- it 'parses and writes the content to the database' do
26
+ it 'proxies to the backend' do
48
27
  expect(database.backend).to(
49
28
  receive(:write_content_to) do |_, cont, loc|
50
- expect(cont).to eq(content)
51
- expect(loc).to eq(locale)
29
+ expect(cont).to eq(:content)
30
+ expect(loc).to eq(:locale)
52
31
  end
53
32
  )
54
33
 
55
- table.write_content(YAML.dump(content), locale)
34
+ table.write_content(:content, :locale)
56
35
  end
57
36
  end
58
37
  end
data/spec/test.sqlite3 CHANGED
Binary file
@@ -5,7 +5,7 @@ require 'spec_helpers/test_backend'
5
5
  include Txdb
6
6
 
7
7
  describe Uploader, test_db: true do
8
- let(:database) { Txdb::Config.databases.first }
8
+ let(:database) { TestDb.database }
9
9
  let(:uploader) { Uploader.new(database) }
10
10
  let(:transifex_api) { double(:transifex_api) }
11
11
 
@@ -18,19 +18,13 @@ describe Uploader, test_db: true do
18
18
  describe '#upload' do
19
19
  it 'reads phrases from the database and uploads them to Transifex' do
20
20
  expect(transifex_api).to receive(:create_or_update) do |resource, content|
21
- expect(resource.project_slug).to eq('myproject')
22
- expect(resource.resource_slug).to(
23
- eq(Txgh::Utils.slugify("#{database.database}-#{database.tables.first.name}"))
24
- )
21
+ expect(resource.project_slug).to eq(TestBackend.resource.project_slug)
22
+ expect(resource.resource_slug).to eq(TestBackend.resource.resource_slug)
25
23
  end
26
24
 
27
25
  expect { uploader.upload }.to(
28
26
  change { TestBackend.reads.size }.from(0).to(1)
29
27
  )
30
-
31
- expect(TestBackend.reads.first).to eq(
32
- table: database.tables.first.name
33
- )
34
28
  end
35
29
  end
36
30
  end
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.0.1
4
+ version: 1.1.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-17 00:00:00.000000000 Z
11
+ date: 2016-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -61,6 +61,7 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - LICENSE
63
63
  - README.md
64
+ - lib/ext/txgh/tx_resource.rb
64
65
  - lib/txdb.rb
65
66
  - lib/txdb/app.rb
66
67
  - lib/txdb/backends.rb
@@ -105,7 +106,6 @@ files:
105
106
  - spec/table_spec.rb
106
107
  - spec/test.sqlite3
107
108
  - spec/transifex_project_spec.rb
108
- - spec/tx_resource_spec.rb
109
109
  - spec/uploader_spec.rb
110
110
  - txdb.gemspec
111
111
  homepage: https://github.com/lumoslabs/txdb
@@ -1,17 +0,0 @@
1
- require 'spec_helper'
2
- require 'spec_helpers/test_db'
3
-
4
- include Txdb
5
-
6
- describe TxResource, test_db: true do
7
- let(:database) { TestDb.database }
8
- let(:table) { database.tables.first }
9
- let(:resource) { table.resource }
10
-
11
- it 'proxies methods to the underlying Txgh::TxResource' do
12
- expect(resource.project_slug).to eq('myproject')
13
- expect(resource.resource_slug).to(
14
- eq(Txgh::Utils.slugify("#{database.database}-#{table.name}"))
15
- )
16
- end
17
- end