synchronisable 0.0.2

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.
Files changed (131) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +2 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +9 -0
  7. data/Guardfile +14 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +22 -0
  10. data/Rakefile +7 -0
  11. data/TODO.md +20 -0
  12. data/bin/autospec +16 -0
  13. data/bin/rake +16 -0
  14. data/bin/rspec +16 -0
  15. data/lib/generators/synchronizable/USAGE +2 -0
  16. data/lib/generators/synchronizable/install_generator.rb +24 -0
  17. data/lib/generators/synchronizable/templates/create_imports_migration.rb +21 -0
  18. data/lib/generators/synchronizable/templates/initializer.rb +14 -0
  19. data/lib/synchronizable.rb +92 -0
  20. data/lib/synchronizable/context.rb +25 -0
  21. data/lib/synchronizable/dsl/associations.rb +57 -0
  22. data/lib/synchronizable/dsl/associations/association.rb +59 -0
  23. data/lib/synchronizable/dsl/associations/has_many.rb +12 -0
  24. data/lib/synchronizable/dsl/associations/has_one.rb +13 -0
  25. data/lib/synchronizable/dsl/macro.rb +100 -0
  26. data/lib/synchronizable/dsl/macro/attribute.rb +41 -0
  27. data/lib/synchronizable/dsl/macro/expression.rb +51 -0
  28. data/lib/synchronizable/dsl/macro/method.rb +15 -0
  29. data/lib/synchronizable/error_handler.rb +50 -0
  30. data/lib/synchronizable/exceptions.rb +8 -0
  31. data/lib/synchronizable/locale/en.yml +17 -0
  32. data/lib/synchronizable/locale/ru.yml +17 -0
  33. data/lib/synchronizable/model.rb +54 -0
  34. data/lib/synchronizable/model/methods.rb +55 -0
  35. data/lib/synchronizable/models/import.rb +24 -0
  36. data/lib/synchronizable/source.rb +72 -0
  37. data/lib/synchronizable/synchronizer.rb +177 -0
  38. data/lib/synchronizable/synchronizers/synchronizer_default.rb +10 -0
  39. data/lib/synchronizable/version.rb +10 -0
  40. data/lib/synchronizable/worker.rb +191 -0
  41. data/spec/dummy/.gitignore +16 -0
  42. data/spec/dummy/Rakefile +6 -0
  43. data/spec/dummy/app/assets/images/.keep +0 -0
  44. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  45. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  46. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  47. data/spec/dummy/app/gateways/gateway_base.rb +19 -0
  48. data/spec/dummy/app/gateways/match_gateway.rb +15 -0
  49. data/spec/dummy/app/gateways/player_gateway.rb +26 -0
  50. data/spec/dummy/app/gateways/stage_gateway.rb +18 -0
  51. data/spec/dummy/app/gateways/team_gateway.rb +18 -0
  52. data/spec/dummy/app/gateways/tournament_gateway.rb +15 -0
  53. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  54. data/spec/dummy/app/mailers/.keep +0 -0
  55. data/spec/dummy/app/models/.keep +0 -0
  56. data/spec/dummy/app/models/match.rb +10 -0
  57. data/spec/dummy/app/models/match_player.rb +15 -0
  58. data/spec/dummy/app/models/player.rb +5 -0
  59. data/spec/dummy/app/models/stadium.rb +7 -0
  60. data/spec/dummy/app/models/stage.rb +6 -0
  61. data/spec/dummy/app/models/team.rb +5 -0
  62. data/spec/dummy/app/models/tournament.rb +7 -0
  63. data/spec/dummy/app/synchronizers/break_convention_team_synchronizer.rb +14 -0
  64. data/spec/dummy/app/synchronizers/match_synchronizer.rb +71 -0
  65. data/spec/dummy/app/synchronizers/player_synchronizer.rb +19 -0
  66. data/spec/dummy/app/synchronizers/stage_synchronizer.rb +20 -0
  67. data/spec/dummy/app/synchronizers/tournament_synchronizer.rb +20 -0
  68. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  69. data/spec/dummy/bin/bundle +3 -0
  70. data/spec/dummy/bin/rails +4 -0
  71. data/spec/dummy/bin/rake +4 -0
  72. data/spec/dummy/config.ru +4 -0
  73. data/spec/dummy/config/application.rb +26 -0
  74. data/spec/dummy/config/boot.rb +6 -0
  75. data/spec/dummy/config/database.yml +25 -0
  76. data/spec/dummy/config/environment.rb +5 -0
  77. data/spec/dummy/config/environments/development.rb +33 -0
  78. data/spec/dummy/config/environments/production.rb +80 -0
  79. data/spec/dummy/config/environments/test.rb +36 -0
  80. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  81. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  82. data/spec/dummy/config/initializers/inflections.rb +20 -0
  83. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  84. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  85. data/spec/dummy/config/initializers/session_store.rb +3 -0
  86. data/spec/dummy/config/initializers/synchronizable.rb +2 -0
  87. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  88. data/spec/dummy/config/locales/en.yml +23 -0
  89. data/spec/dummy/config/routes.rb +56 -0
  90. data/spec/dummy/db/migrate/20140422132431_create_teams.rb +11 -0
  91. data/spec/dummy/db/migrate/20140422132544_create_matches.rb +12 -0
  92. data/spec/dummy/db/migrate/20140422132708_create_players.rb +15 -0
  93. data/spec/dummy/db/migrate/20140422133122_create_match_players.rb +12 -0
  94. data/spec/dummy/db/migrate/20140422135244_create_imports.rb +21 -0
  95. data/spec/dummy/db/migrate/20140422140817_create_stadiums.rb +10 -0
  96. data/spec/dummy/db/migrate/20140507135800_create_tournaments.rb +13 -0
  97. data/spec/dummy/db/migrate/20140507135837_create_stages.rb +13 -0
  98. data/spec/dummy/db/migrate/20140507140039_add_stage_id_to_matches.rb +6 -0
  99. data/spec/dummy/db/schema.rb +103 -0
  100. data/spec/dummy/db/seeds.rb +7 -0
  101. data/spec/dummy/lib/assets/.keep +0 -0
  102. data/spec/dummy/lib/tasks/.keep +0 -0
  103. data/spec/dummy/log/.keep +0 -0
  104. data/spec/dummy/public/404.html +58 -0
  105. data/spec/dummy/public/422.html +58 -0
  106. data/spec/dummy/public/500.html +57 -0
  107. data/spec/dummy/public/favicon.ico +0 -0
  108. data/spec/dummy/public/robots.txt +5 -0
  109. data/spec/dummy/vendor/assets/javascripts/.keep +0 -0
  110. data/spec/dummy/vendor/assets/stylesheets/.keep +0 -0
  111. data/spec/factories/import.rb +5 -0
  112. data/spec/factories/match.rb +9 -0
  113. data/spec/factories/match_player.rb +9 -0
  114. data/spec/factories/player.rb +10 -0
  115. data/spec/factories/remote/match.rb +21 -0
  116. data/spec/factories/remote/player.rb +18 -0
  117. data/spec/factories/remote/stage.rb +26 -0
  118. data/spec/factories/remote/team.rb +21 -0
  119. data/spec/factories/remote/tournament.rb +18 -0
  120. data/spec/factories/stadium.rb +7 -0
  121. data/spec/factories/team.rb +16 -0
  122. data/spec/models/match_spec.rb +41 -0
  123. data/spec/models/team_spec.rb +85 -0
  124. data/spec/spec_helper.rb +64 -0
  125. data/spec/synchronizable/dsl/macro_spec.rb +59 -0
  126. data/spec/synchronizable/models/import_spec.rb +10 -0
  127. data/spec/synchronizable/support/has_macro.rb +12 -0
  128. data/spec/synchronizable/support/has_macro_subclass.rb +9 -0
  129. data/spec/synchronizable/synchronizable_spec.rb +60 -0
  130. data/synchronizable.gemspec +39 -0
  131. metadata +506 -0
@@ -0,0 +1,18 @@
1
+ FactoryGirl.define do
2
+ factory :remote_player, class: Hash do
3
+ player_id { generate :player_id }
4
+ team { generate :team_id }
5
+
6
+ eman_tsrif { generate :first_name }
7
+ eman_tsal { generate :last_name }
8
+ yadhtrib { generate :date }
9
+ pihsnezitic { generate :string }
10
+ thgieh { generate :integer }
11
+ thgiew { generate :integer }
12
+
13
+ ignored_1 { generate :string }
14
+ ignored_2 { generate :integer }
15
+
16
+ initialize_with { attributes }
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ FactoryGirl.define do
2
+ factory :remote_stage, class: Hash do
3
+ stage_id { generate :stage_id }
4
+ tour_id { generate :tournament_id }
5
+
6
+ eman { generate :string }
7
+ rebmun { generate :integer }
8
+ gninnigeb { generate :timestamp }
9
+ gnidge { generate :date }
10
+
11
+ ignored_1 { generate :date }
12
+ ignored_2 { generate :timestamp }
13
+
14
+ initialize_with { attributes }
15
+
16
+ trait :with_matches do
17
+ after(:build) do
18
+ match = build(:remote_match,
19
+ :home_team => 'team_0',
20
+ :away_team => 'team_1'
21
+ )
22
+ object[:matches_ids] = [match[:match_id]]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ FactoryGirl.define do
2
+ factory :remote_team, class: Hash do
3
+ maet_id { generate :team_id }
4
+
5
+ eman { generate :name }
6
+ yrtnuoc { generate :string }
7
+ ytic { generate :string }
8
+
9
+ ignored_1 { generate :string }
10
+ ignored_2 { generate :timestamp }
11
+
12
+ initialize_with { attributes }
13
+
14
+ trait :with_players do
15
+ after(:build) do |object, evaluator|
16
+ players = build_list(:remote_player, 4, team: object[:maet_id])
17
+ object[:players_ids] = players.map { |h| h[:player_id] }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ FactoryGirl.define do
2
+ factory :remote_tournament, class: Hash do
3
+ tour_id { generate :tournament_id }
4
+ eman { generate :string }
5
+ eman_trohs { generate :string }
6
+ gninnigeb { generate :date }
7
+ gnidge { generate :date }
8
+
9
+ initialize_with { attributes }
10
+
11
+ trait :with_stages do
12
+ after(:build) do |object, evaluator|
13
+ stages = build_list(:remote_stage, 2, tour_id: object[:tour_id])
14
+ object[:stages_ids] = stages.map { |h| h[:stage_id] }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :stadium do
3
+ name { generate :string }
4
+ capacity { generate :integer }
5
+ end
6
+ end
7
+
@@ -0,0 +1,16 @@
1
+ FactoryGirl.define do
2
+ factory :team do
3
+ name { generate :string }
4
+
5
+ trait :with_stadium do
6
+ association :stadium
7
+ end
8
+
9
+ trait :with_players do
10
+ after(:build) do |object, evaluator|
11
+ create_list(:player, 11, :team => object)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Match do
4
+ describe 'synchronization' do
5
+ context 'when has associations defined in Synchronizer' do
6
+ subject do
7
+ -> { Match.sync }
8
+ end
9
+
10
+ it { should change { Match.count }.by(1) }
11
+ it { should change { Team.count }.by(2) }
12
+ it { should change { Player.count }.by(4) }
13
+ it { should change { MatchPlayer.count }.by(4) }
14
+
15
+ it { should change { Synchronizable::Import.count }.by(11) }
16
+ end
17
+
18
+ # TODO: Left here until :include option is implemented
19
+ #
20
+ # context 'when associations specified with :include option' do
21
+ # subject do
22
+ # -> { sync_match }
23
+ # end
24
+
25
+ # def sync_match
26
+ # Match.sync(:include => {
27
+ # :match => {
28
+ # :team => :players
29
+ # }
30
+ # })
31
+ # end
32
+
33
+ # it { should change { Match.count }.by(1) }
34
+ # it { should change { Team.count }.by(2) }
35
+ # it { should change { Player.count }.by(22) }
36
+ # it { should change { MatchPlayer.count }.by(22) }
37
+
38
+ # it { should change { Synchronizable::Import.count }.by(47) }
39
+ # end
40
+ end
41
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+
3
+ describe Team do
4
+ describe 'synchronization' do
5
+ let!(:remote_attrs) do
6
+ [
7
+ {
8
+ :maet_id => 'team1',
9
+ :eman => 'y',
10
+ :yrtnuoc => 'USA',
11
+ :ytic => 'Washington',
12
+ :ignored_1 => 'ignored',
13
+ :ignored_2 => 'ignored'
14
+ },
15
+ {
16
+ :maet_id => 'team2',
17
+ :eman => 'z',
18
+ :yrtnuoc => 'France',
19
+ :ytic => 'Paris',
20
+ :ignored_2 => 'ignored'
21
+ },
22
+ {
23
+ :eman => 'a',
24
+ :yrtnuoc => 'blah',
25
+ :ytic => 'blah'
26
+ }
27
+ ]
28
+ end
29
+
30
+ context 'sync with no data specified' do
31
+ subject do
32
+ -> { Team.sync }
33
+ end
34
+
35
+ it { should change { Team.count }.by(2) }
36
+ it { should change { Player.count }.by(4) }
37
+
38
+ it { should change { Synchronizable::Import.count }.by(6) }
39
+ end
40
+
41
+ context 'when remote id is not specified' do
42
+ subject { Team.sync([remote_attrs.last]) }
43
+
44
+ its(:errors) { should have(1).items }
45
+ end
46
+
47
+ context 'when local record does not exist' do
48
+ subject do
49
+ -> { Team.sync(remote_attrs.take(2)) }
50
+ end
51
+
52
+ it { should change { Team.count }.by(2) }
53
+ it { should change { Synchronizable::Import.count }.by(2) }
54
+ end
55
+
56
+ context 'when local and import records exists' do
57
+ let!(:import) do
58
+ create(:import,
59
+ :remote_id => 'team1',
60
+ :synchronizable => create(:team,
61
+ :name => 'x',
62
+ :country => 'Russia',
63
+ :city => 'Moscow',
64
+ )
65
+ )
66
+ end
67
+
68
+ let!(:team) { import.synchronizable }
69
+
70
+ subject do
71
+ -> {
72
+ Team.sync(remote_attrs.take(2))
73
+ team.reload
74
+ }
75
+ end
76
+
77
+ it { should change { Team.count }.by(1) }
78
+ it { should change { Synchronizable::Import.count }.by(1) }
79
+
80
+ it { should change { team.name }.from('x').to('y') }
81
+ it { should change { team.country }.from('Russia').to('USA') }
82
+ it { should change { team.city }.from('Moscow').to('Washington') }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,64 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+
3
+ require 'database_cleaner'
4
+ require 'factory_girl'
5
+ require 'factory_girl_sequences'
6
+ require 'spork'
7
+ require 'simplecov'
8
+
9
+ SimpleCov.start
10
+
11
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
12
+
13
+ require 'synchronizable'
14
+
15
+ require File.expand_path('../dummy/config/environment', __FILE__)
16
+ require 'rspec/rails'
17
+
18
+ support_pattern = File.join(File.dirname(__FILE__), 'synchronizable', 'support', '**', '*.rb')
19
+ factories_pattern = File.join(File.dirname(__FILE__), 'factories', '**', '*.rb')
20
+
21
+ Dir[factories_pattern].each { |file| require file }
22
+ Dir[support_pattern].each { |file| require file }
23
+
24
+ ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
25
+
26
+ Spork.prefork do
27
+ RSpec.configure do |config|
28
+ config.treat_symbols_as_metadata_keys_with_true_values = true
29
+ config.run_all_when_everything_filtered = true
30
+ config.filter_run focus: true
31
+ config.order = 'random'
32
+ config.include FactoryGirl::Syntax::Methods
33
+
34
+ config.before(:suite) do
35
+ begin
36
+ FactoryGirl.lint
37
+ ensure
38
+ DatabaseCleaner.clean_with(:truncation)
39
+ end
40
+ end
41
+
42
+ config.before(:each) { DatabaseCleaner.strategy = :transaction }
43
+
44
+ config.before(:each, js: true) do
45
+ DatabaseCleaner.strategy = :truncation
46
+ end
47
+
48
+ config.before(:each) { DatabaseCleaner.start }
49
+ config.after(:each) { DatabaseCleaner.clean }
50
+
51
+ if ENV['RUN_SLOW_TESTS'] != 'true'
52
+ config.filter_run_excluding slow: true
53
+ end
54
+ end
55
+
56
+ FactoryGirl.define do
57
+ %w(match team player match_player stage tournament).each do |model|
58
+ sequence(:"#{model}_id") { |n| "#{model}_#{n}" }
59
+ end
60
+ end
61
+ end
62
+
63
+ Spork.each_run do
64
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Synchronizable::DSL::Macro do
4
+ describe 'commom attributes' do
5
+ subject { HasMacro }
6
+
7
+ before do
8
+ subject.xyz 7
9
+ subject.arr 1, 2, 3
10
+ end
11
+
12
+ it { respond_to? :foo }
13
+ it { respond_to? :bar }
14
+ it { respond_to? :baz }
15
+ it { respond_to? :xxx }
16
+ it { respond_to? :arr }
17
+
18
+ its(:foo) { should be nil }
19
+ its(:bar) { should eq(1) }
20
+ its(:baz) { should eq(2) }
21
+ its(:xyz) { should eq('7') }
22
+ its(:arr) { should eq([1, 2, 3]) }
23
+ end
24
+
25
+ describe 'attribute with default value lambda that raises an error' do
26
+ it 'raises error' do
27
+ expect { HasMacro.carefull }.to raise_error(NotImplementedError)
28
+ end
29
+
30
+ context 'when overriden in subclass not to raise an error' do
31
+ subject { HasMacroSubclass }
32
+
33
+ it { respond_to? :foo }
34
+ it { respond_to? :bar }
35
+
36
+ its(:foo) { should be nil }
37
+ its(:bar) { should eq(1) }
38
+
39
+ it 'not raises error' do
40
+ expect { HasMacroSubclass.carefull }.to_not raise_error
41
+ end
42
+
43
+ it 'equals to the new default value' do
44
+ expect(HasMacroSubclass.carefull).to eq(0)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe 'methods' do
50
+ subject { HasMacroSubclass }
51
+
52
+ it { respond_to? :sqr }
53
+ its(:sqr) { respond_to? :call }
54
+
55
+ it "sqr method definition returns square of two numbers" do
56
+ expect(subject.sqr.(2)).to eq(4)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Synchronizable::Import do
4
+ let!(:team) { create :team }
5
+ subject { create(:import, synchronizable: team) }
6
+
7
+ it 'destroys itself with synchronizable record' do
8
+ expect { subject.destroy_with_synchronizable }.to change(Team, :count).by(-1)
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ class HasMacro
2
+ include Synchronizable::DSL::Macro
3
+
4
+ attribute :bar, default: 1
5
+ attribute :foo
6
+ attribute :baz, default: -> { bar + 1 }
7
+ attribute :carefull, default: -> { raise NotImplementedError }
8
+ attribute :xyz, converter: ->(x) { x.to_s }
9
+ attribute :arr
10
+
11
+ method :sqr
12
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'has_macro'
2
+
3
+ class HasMacroSubclass < HasMacro
4
+ attribute :carefull, default: 0
5
+
6
+ sqr do |x|
7
+ x * x
8
+ end
9
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Synchronizable do
4
+ describe 'synchronization' do
5
+ subject do
6
+ -> { Synchronizable.sync }
7
+ end
8
+
9
+ describe 'models specified in configuration' do
10
+ context 'only Team and Match' do
11
+ before :all do
12
+ Synchronizable.models = %w(Match Team)
13
+ end
14
+
15
+ it { should change { Match.count }.by(1) }
16
+ it { should change { Team.count }.by(2) }
17
+ it { should change { Player.count }.by(4) }
18
+ it { should change { MatchPlayer.count }.by(4) }
19
+
20
+ it { should change { Synchronizable::Import.count }.by(11) }
21
+ end
22
+
23
+ context 'all' do
24
+ before :all do
25
+ Synchronizable.models = %w(
26
+ Stage Tournament Team
27
+ Match MatchPlayer Player
28
+ )
29
+ end
30
+
31
+ it { should change { Tournament.count }.by(1) }
32
+ it { should change { Stage.count }.by(2) }
33
+ it { should change { Match.count }.by(1) }
34
+ it { should change { Team.count }.by(2) }
35
+ it { should change { MatchPlayer.count }.by(4) }
36
+ it { should change { Player.count }.by(4) }
37
+
38
+ it { should change { Synchronizable::Import.count }.by(14) }
39
+ end
40
+
41
+ # TODO: Left here until :include option is implemented
42
+ #
43
+ # context 'when models setting is overriden in method call' do
44
+ # before :all do
45
+ # Synchronizable.models = %w(Team Match)
46
+ # end
47
+
48
+ # subject do
49
+ # -> { Synchronizable.sync(Match, Player) }
50
+ # end
51
+
52
+ # it { should change { Match.count }.by(1) }
53
+ # it { should change { Player.count }.by(22) }
54
+ # it { should_not change { Team.count }.by(2) }
55
+
56
+ # it { should change { Synchronizable::Import.count }.by(5) }
57
+ # end
58
+ end
59
+ end
60
+ end