synchronisable 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46c5332c053921eb44021c59a846a1451eede185
4
- data.tar.gz: d33c7cdb48f1266ebb3737a20c7a6c4b3688b12c
3
+ metadata.gz: 5e53ab569c0106db0a2e1f17b9446111c8dde193
4
+ data.tar.gz: caebb67d58390fddd864b91a8e8901904f5094bf
5
5
  SHA512:
6
- metadata.gz: a42307f344f720d63a7519969481e94fffcc9a9010510cf39791ea43b93ad5e64304c80074aa1b5f5133d720fc16cbaf829650dfeb3da50d814efe3608eb72a4
7
- data.tar.gz: 7b35e861d0ea8c002d4215b2965713c2c2ebb30f509f24e652f687f95e0237bb69be0dee671aa66fc944f4a714e417a9a4c85f59c1862f6d8f727879b0cff6f9
6
+ metadata.gz: 209cee6e20cf9f5edd9b52e105e1c6a9db92beb0fd66a91e1a5841c10594ac41195b2708c6ab8f04776a431b03253c606f6a2185503c8e43b8ff9dd1db74525b
7
+ data.tar.gz: bd26bb9a7a7377ff5c3778b9ae3cce6525b99fccee41c4a113680dce94dcadd2bbeb5822141478ee33ca85250a4c2e570c3e26caa59dc9f6b6d5a02111565a6d
data/Guardfile CHANGED
@@ -6,9 +6,3 @@ guard :rspec, :all_on_start => false, :all_after_pass => false do
6
6
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
7
  watch('spec/spec_helper.rb') { "spec" }
8
8
  end
9
-
10
-
11
- guard 'spork' do
12
- watch('Gemfile.lock')
13
- watch('spec/spec_helper.rb') { :rspec }
14
- end
data/TODO.md CHANGED
@@ -17,6 +17,7 @@ Primary objectives
17
17
  - [x] sync with ids array
18
18
  - [ ] handle case when association type is a :hash
19
19
  - [ ] sync method for collection proxy (Model.where(condition).sync)
20
+ - [ ] better specs for cases when we should fetch/find using complex params
20
21
 
21
22
  Think about
22
23
  ======================================
@@ -27,7 +28,7 @@ Secondary objectives
27
28
  ======================================
28
29
  - [x] option for verbose logging
29
30
  - [x] colorized STDOUT
30
- - [ ] actualize docs
31
+ - [x] actualize docs
31
32
 
32
33
 
33
34
  The desired interface:
@@ -38,7 +39,7 @@ The desired interface:
38
39
  ```
39
40
 
40
41
  ```
41
- Match.sync(:include => {
42
+ + Match.sync(:include => {
42
43
  :match_players => :player
43
44
  })
44
45
  + Model.sync([id1, ..., idn])
@@ -0,0 +1,11 @@
1
+ require 'i18n'
2
+
3
+ locale_paths = File.join(File.dirname(__FILE__),
4
+ '..', 'locale', '*.yml')
5
+
6
+ Dir[locale_paths].each { |path| I18n.load_path << path }
7
+ I18n.backend.load_translations unless defined?(Rails)
8
+
9
+ I18n.config.enforce_available_locales = true
10
+ I18n.default_locale = :en
11
+ I18n.available_locales = [:en, :ru]
File without changes
@@ -2,7 +2,7 @@ require 'colorize'
2
2
 
3
3
  require 'synchronisable/error_handler'
4
4
  require 'synchronisable/context'
5
- require 'synchronisable/input_parser'
5
+ require 'synchronisable/input/parser'
6
6
  require 'synchronisable/source'
7
7
  require 'synchronisable/models/import'
8
8
  require 'synchronisable/helper/logging'
@@ -77,7 +77,7 @@ module Synchronisable
77
77
  #
78
78
  # @return [Synchronisable::Context] synchronization context
79
79
  #
80
- # @see Synchronisable::InputParser
80
+ # @see Synchronisable::Input::Parser
81
81
  def call(data)
82
82
  sync do |context|
83
83
  error_handler = ErrorHandler.new(logger, context)
@@ -116,7 +116,7 @@ module Synchronisable
116
116
  @includes = options[:includes]
117
117
  @parent = options[:parent]
118
118
 
119
- @input = InputParser.new(@model, @synchronizer)
119
+ @input = Input::Parser.new(@model, @synchronizer)
120
120
  end
121
121
 
122
122
  def sync
@@ -1,7 +1,5 @@
1
1
  module Synchronisable
2
2
  class Gateway
3
- attr_reader :synchronizer
4
-
5
3
  def fetch(params = {})
6
4
  not_implemented :fetch
7
5
  end
@@ -0,0 +1,54 @@
1
+ module Synchronisable
2
+ module Input
3
+ # Provides a set of helper methods
4
+ # to describe user input.
5
+ #
6
+ # @api private
7
+ #
8
+ # @see Synchronisable::Input::Descriptor
9
+ class Descriptor
10
+ attr_reader :data
11
+
12
+ def initialize(data)
13
+ @data = data
14
+ end
15
+
16
+ def empty?
17
+ @data.blank?
18
+ end
19
+
20
+ def params?
21
+ @data.is_a?(Hash)
22
+ end
23
+
24
+ def remote_id?
25
+ @data.is_a?(String)
26
+ end
27
+
28
+ def local_id?
29
+ @data.is_a?(Integer)
30
+ end
31
+
32
+ def array_of_ids?
33
+ enumerable? && (
34
+ first_element.is_a?(String) ||
35
+ first_element.is_a?(Integer)
36
+ )
37
+ end
38
+
39
+ def element_class
40
+ first_element.try(:class)
41
+ end
42
+
43
+ private
44
+
45
+ def first_element
46
+ @data.try(:first)
47
+ end
48
+
49
+ def enumerable?
50
+ @data.is_a?(Enumerable)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,70 @@
1
+ require 'synchronisable/input/descriptor'
2
+
3
+ module Synchronisable
4
+ module Input
5
+ # Responsible for guessing the user input format.
6
+ #
7
+ # @api private
8
+ #
9
+ # @see Synchronisable::Input::Parser
10
+ class Parser
11
+ def initialize(model, synchronizer)
12
+ @model = model
13
+ @synchronizer = synchronizer
14
+ end
15
+
16
+ # Parses the user input.
17
+ #
18
+ # @param data [Array<Hash>, Array<String>, Array<Integer>, String, Integer]
19
+ # synchronization data to handle.
20
+ #
21
+ # @return [Array<Hash>] array of hashes with remote attributes
22
+ def parse(data)
23
+ input = Descriptor.new(data)
24
+
25
+ result = case
26
+ when input.empty?
27
+ @synchronizer.fetch
28
+ when input.params?
29
+ find_or_fetch_by_params(input.data)
30
+ when input.remote_id?
31
+ @synchronizer.find(data)
32
+ when input.local_id?
33
+ find_by_local_id(data)
34
+ when input.array_of_ids?
35
+ find_by_array_of_ids(input)
36
+ else
37
+ result = data.dup
38
+ end
39
+
40
+ [result].flatten.compact
41
+ end
42
+
43
+ private
44
+
45
+ def find_or_fetch_by_params(params)
46
+ sync_method = params.key?(:id) ? :find : :fetch
47
+ @synchronizer.send(sync_method, params)
48
+ end
49
+
50
+ def find_by_array_of_ids(input)
51
+ records = find_imports(input.element_class.name, input.data)
52
+ records.map { |r| @synchronizer.find(r.remote_id) }
53
+ end
54
+
55
+ def find_by_local_id(id)
56
+ import = @model.find_by(id: id).try(:import)
57
+ import ? @synchronizer.find(import.remote_id) : nil
58
+ end
59
+
60
+ def find_imports(class_name, ids)
61
+ case class_name
62
+ when 'Fixnum'
63
+ ids.map { |id| @model.find_by(id: id).try(&:import) }
64
+ when 'String'
65
+ ids.map { |id| Import.find_by(id: id) }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -2,7 +2,7 @@ module Synchronisable
2
2
  module VERSION
3
3
  MAJOR = 1
4
4
  MINOR = 1
5
- PATCH = 3
5
+ PATCH = 4
6
6
  SUFFIX = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, SUFFIX].compact.join('.')
@@ -8,7 +8,7 @@ require 'active_support/core_ext/string/inflections'
8
8
  require 'active_support/configurable'
9
9
  require 'active_support/concern'
10
10
 
11
- require 'i18n'
11
+ require 'synchronisable/bootstrap/i18n'
12
12
 
13
13
  require 'synchronisable/version'
14
14
  require 'synchronisable/models/import'
@@ -16,15 +16,6 @@ require 'synchronisable/synchronizer'
16
16
  require 'synchronisable/model'
17
17
  require 'synchronisable/gateway'
18
18
 
19
- locale_paths = File.join(File.dirname(__FILE__),
20
- 'synchronisable', 'locale', '*.yml')
21
-
22
- Dir[locale_paths].each { |path| I18n.load_path << path }
23
- I18n.backend.load_translations unless defined?(Rails)
24
-
25
- I18n.config.enforce_available_locales = true
26
- I18n.default_locale = :en
27
- I18n.available_locales = [:en, :ru]
28
19
 
29
20
  module Synchronisable
30
21
  include ActiveSupport::Configurable
@@ -1,8 +1,4 @@
1
1
  class StageGateway < GatewayBase
2
- def id_key
3
- :stage_id
4
- end
5
-
6
2
  def source
7
3
  @source ||= [
8
4
  FactoryGirl.build(:remote_stage,
@@ -15,4 +11,26 @@ class StageGateway < GatewayBase
15
11
  )
16
12
  ]
17
13
  end
14
+
15
+ def fetch(params)
16
+ tournament_id = params[:tournament_id]
17
+
18
+ raise "missed parameter 'tournament_id'" unless tournament_id
19
+
20
+ source.select do |attrs|
21
+ attrs[:tour_id] = tournament_id
22
+ end
23
+ end
24
+
25
+ def find(params)
26
+ tournament_id, id = params[:tournament_id], params[:id]
27
+
28
+ raise "missed parameter 'tournament_id'" unless tournament_id
29
+ raise "missed parameter 'id'" unless id
30
+
31
+ source.find do |attrs|
32
+ attrs[:tour_id] = tournament_id &&
33
+ attrs[:stage_id] = id
34
+ end
35
+ end
18
36
  end
@@ -8,7 +8,16 @@ class TournamentGateway < GatewayBase
8
8
  FactoryGirl.build(:remote_tournament,
9
9
  :tour_id => 'tournament_0',
10
10
  :is_current => true,
11
- :stages_ids => %w(stage_0 stage_1)
11
+ :stages_ids => [
12
+ {
13
+ id: 'stage_0',
14
+ tournament_id: 'tournament_0'
15
+ },
16
+ {
17
+ id: 'stage_1',
18
+ tournament_id: 'tournament_0'
19
+ }
20
+ ]
12
21
  )
13
22
  ]
14
23
  end
@@ -11,10 +11,12 @@ describe Stage do
11
11
  end
12
12
 
13
13
  describe 'skipping with before_sync hook' do
14
- subject { -> { Stage.sync(remote_attrs, :includes => {}) } }
14
+ let!(:context) { Stage.sync(remote_attrs, :includes => {}) }
15
15
 
16
- it { is_expected.to change { Stage.count }.by(2) }
17
- it { is_expected.to change { Synchronisable::Import.count }.by(2) }
16
+ it 'skips hashes where name is "ignored"' do
17
+ expect(Stage.count).to eq(2)
18
+ expect(Synchronisable::Import.count).to eq(2)
19
+ end
18
20
  end
19
21
  end
20
22
  end
@@ -121,7 +121,7 @@ describe Team do
121
121
  end
122
122
 
123
123
  context 'when remote id is not specified in attributes hash' do
124
- it "return synchronization result that contains 1 error" do
124
+ it 'return synchronization result that contains 1 error' do
125
125
  result = Team.sync([remote_attrs.last])
126
126
  expect(result.errors.count).to eq(1)
127
127
  end
data/spec/spec_helper.rb CHANGED
@@ -6,7 +6,6 @@ ENV['RAILS_ENV'] ||= 'test'
6
6
  require 'database_cleaner'
7
7
  require 'factory_girl'
8
8
  require 'factory_girl_sequences'
9
- require 'spork'
10
9
 
11
10
  if ENV['COVERAGE']
12
11
  require 'simplecov'
@@ -34,41 +33,36 @@ Dir[support_pattern].each { |file| require file }
34
33
 
35
34
  ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
36
35
 
37
- Spork.prefork do
38
- RSpec.configure do |config|
39
- config.run_all_when_everything_filtered = true
40
- config.filter_run focus: true
41
- config.order = 'random'
42
- config.include FactoryGirl::Syntax::Methods
43
-
44
- config.before(:suite) do
45
- begin
46
- FactoryGirl.lint
47
- ensure
48
- DatabaseCleaner.clean_with(:truncation)
49
- end
50
- end
51
-
52
- config.before(:each) { DatabaseCleaner.strategy = :transaction }
53
-
54
- config.before(:each, js: true) do
55
- DatabaseCleaner.strategy = :truncation
36
+ RSpec.configure do |config|
37
+ config.run_all_when_everything_filtered = true
38
+ config.filter_run focus: true
39
+ config.order = 'random'
40
+ config.include FactoryGirl::Syntax::Methods
41
+
42
+ config.before(:suite) do
43
+ begin
44
+ FactoryGirl.lint
45
+ ensure
46
+ DatabaseCleaner.clean_with(:truncation)
56
47
  end
48
+ end
57
49
 
58
- config.before(:each) { DatabaseCleaner.start }
59
- config.after(:each) { DatabaseCleaner.clean }
50
+ config.before(:each) { DatabaseCleaner.strategy = :transaction }
60
51
 
61
- if ENV['RUN_SLOW_TESTS'] != 'true'
62
- config.filter_run_excluding slow: true
63
- end
52
+ config.before(:each, js: true) do
53
+ DatabaseCleaner.strategy = :truncation
64
54
  end
65
55
 
66
- FactoryGirl.define do
67
- %w(remote match team player match_player stage tournament).each do |prefix|
68
- sequence(:"#{prefix}_id") { |n| "#{prefix}_#{n}" }
69
- end
56
+ config.before(:each) { DatabaseCleaner.start }
57
+ config.after(:each) { DatabaseCleaner.clean }
58
+
59
+ if ENV['RUN_SLOW_TESTS'] != 'true'
60
+ config.filter_run_excluding slow: true
70
61
  end
71
62
  end
72
63
 
73
- Spork.each_run do
64
+ FactoryGirl.define do
65
+ %w(remote match team player match_player stage tournament).each do |prefix|
66
+ sequence(:"#{prefix}_id") { |n| "#{prefix}_#{n}" }
67
+ end
74
68
  end
@@ -23,7 +23,7 @@ describe Synchronisable do
23
23
  context 'all' do
24
24
  before :all do
25
25
  Synchronisable.models = %w(
26
- Stage Tournament Team
26
+ Tournament Team
27
27
  Match MatchPlayer Player
28
28
  )
29
29
  end
@@ -38,21 +38,25 @@ describe Synchronisable do
38
38
  it { is_expected.to change { Synchronisable::Import.count }.by(14) }
39
39
  end
40
40
 
41
- # context 'when models setting is overriden in method call' do
42
- # before :all do
43
- # Synchronisable.models = %w(Team Match)
44
- # end
41
+ context 'when models setting is overriden in method call' do
42
+ before :all do
43
+ Synchronisable.models = %w(Team Match)
44
+ end
45
45
 
46
- # subject do
47
- # -> { Synchronisable.sync(Match, Player) }
48
- # end
46
+ subject do
47
+ -> { Synchronisable.sync(Match, Player) }
48
+ end
49
+
50
+ it { is_expected.to change { Match.count }.by(1) }
51
+ it { is_expected.to change { Team.count }.by(2) }
52
+ it { is_expected.to change { Player.count }.by(4) }
53
+ it { is_expected.to change { MatchPlayer.count }.by(4) }
49
54
 
50
- # it { is_expected.to change { Match.count }.by(1) }
51
- # it { is_expected.to change { Player.count }.by(22) }
52
- # it { is_expected.not_to change { Team.count }.by(2) }
55
+ it { is_expected.not_to change { Stage.count } }
56
+ it { is_expected.not_to change { Tournament.count } }
53
57
 
54
- # it { is_expected.to change { Synchronisable::Import.count }.by(5) }
55
- # end
58
+ it { is_expected.to change { Synchronisable::Import.count }.by(11) }
59
+ end
56
60
  end
57
61
  end
58
62
  end
@@ -35,7 +35,6 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency "database_cleaner"
36
36
  spec.add_development_dependency "mutant"
37
37
  spec.add_development_dependency "mutant-rspec"
38
- spec.add_development_dependency "guard-spork"
39
38
  spec.add_development_dependency "guard-rspec"
40
39
  spec.add_development_dependency "simplecov"
41
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synchronisable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasiliy Yorkin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-07 00:00:00.000000000 Z
11
+ date: 2014-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -234,20 +234,6 @@ dependencies:
234
234
  - - ">="
235
235
  - !ruby/object:Gem::Version
236
236
  version: '0'
237
- - !ruby/object:Gem::Dependency
238
- name: guard-spork
239
- requirement: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - ">="
242
- - !ruby/object:Gem::Version
243
- version: '0'
244
- type: :development
245
- prerelease: false
246
- version_requirements: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - ">="
249
- - !ruby/object:Gem::Version
250
- version: '0'
251
237
  - !ruby/object:Gem::Dependency
252
238
  name: guard-rspec
253
239
  requirement: !ruby/object:Gem::Requirement
@@ -301,6 +287,8 @@ files:
301
287
  - lib/generators/synchronisable/templates/initializer.rb
302
288
  - lib/synchronisable.rb
303
289
  - lib/synchronisable/attribute_mapper.rb
290
+ - lib/synchronisable/bootstrap/i18n.rb
291
+ - lib/synchronisable/configuration.rb
304
292
  - lib/synchronisable/context.rb
305
293
  - lib/synchronisable/controller.rb
306
294
  - lib/synchronisable/dsl/associations.rb
@@ -316,8 +304,8 @@ files:
316
304
  - lib/synchronisable/exceptions.rb
317
305
  - lib/synchronisable/gateway.rb
318
306
  - lib/synchronisable/helper/logging.rb
319
- - lib/synchronisable/input_descriptor.rb
320
- - lib/synchronisable/input_parser.rb
307
+ - lib/synchronisable/input/descriptor.rb
308
+ - lib/synchronisable/input/parser.rb
321
309
  - lib/synchronisable/locale/en.yml
322
310
  - lib/synchronisable/locale/ru.yml
323
311
  - lib/synchronisable/model.rb
@@ -451,7 +439,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
451
439
  version: '0'
452
440
  requirements: []
453
441
  rubyforge_project:
454
- rubygems_version: 2.2.0
442
+ rubygems_version: 2.2.2
455
443
  signing_key:
456
444
  specification_version: 4
457
445
  summary: Provides base fuctionality (models, DSL) for AR synchronization with external
@@ -1,52 +0,0 @@
1
- module Synchronisable
2
- # Provides a set of helper methods
3
- # to describe user input.
4
- #
5
- # @api private
6
- #
7
- # @see Synchronisable::InputParser
8
- class InputDescriptor
9
- attr_reader :data
10
-
11
- def initialize(data)
12
- @data = data
13
- end
14
-
15
- def empty?
16
- @data.blank?
17
- end
18
-
19
- def params?
20
- @data.is_a?(Hash)
21
- end
22
-
23
- def remote_id?
24
- @data.is_a?(String)
25
- end
26
-
27
- def local_id?
28
- @data.is_a?(Integer)
29
- end
30
-
31
- def array_of_ids?
32
- enumerable? && (
33
- first_element.is_a?(String) ||
34
- first_element.is_a?(Integer)
35
- )
36
- end
37
-
38
- def element_class
39
- first_element.try(:class)
40
- end
41
-
42
- private
43
-
44
- def first_element
45
- @data.try(:first)
46
- end
47
-
48
- def enumerable?
49
- @data.is_a?(Enumerable)
50
- end
51
- end
52
- end
@@ -1,68 +0,0 @@
1
- require 'synchronisable/input_descriptor'
2
-
3
- module Synchronisable
4
- # Responsible for guessing the user input format.
5
- #
6
- # @api private
7
- #
8
- # @see Synchronisable::InputDescriptor
9
- class InputParser
10
- def initialize(model, synchronizer)
11
- @model = model
12
- @synchronizer = synchronizer
13
- end
14
-
15
- # Parses the user input.
16
- #
17
- # @param data [Array<Hash>, Array<String>, Array<Integer>, String, Integer]
18
- # synchronization data to handle.
19
- #
20
- # @return [Array<Hash>] array of hashes with remote attributes
21
- def parse(data)
22
- input = InputDescriptor.new(data)
23
-
24
- result = case
25
- when input.empty?
26
- @synchronizer.fetch
27
- when input.params?
28
- find_or_fetch_by_params(input.data)
29
- when input.remote_id?
30
- @synchronizer.find(data)
31
- when input.local_id?
32
- find_by_local_id(data)
33
- when input.array_of_ids?
34
- find_by_array_of_ids(input)
35
- else
36
- result = data.dup
37
- end
38
-
39
- [result].flatten.compact
40
- end
41
-
42
- private
43
-
44
- def find_or_fetch_by_params(params)
45
- sync_method = params.key?(:id) ? :find : :fetch
46
- @synchronizer.send(sync_method, params)
47
- end
48
-
49
- def find_by_array_of_ids(input)
50
- records = find_imports(input.element_class.name, input.data)
51
- records.map { |r| @synchronizer.find(r.remote_id) }
52
- end
53
-
54
- def find_by_local_id(id)
55
- import = @model.find_by(id: id).try(:import)
56
- import ? @synchronizer.find(import.remote_id) : nil
57
- end
58
-
59
- def find_imports(class_name, ids)
60
- case class_name
61
- when 'Fixnum'
62
- ids.map { |id| @model.find_by(id: id).try(&:import) }
63
- when 'String'
64
- ids.map { |id| Import.find_by(id: id) }
65
- end
66
- end
67
- end
68
- end