partial_ks 0.4.2 → 0.5.0

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: ad9df615166ffb1addb9feff9c7a0db7cc73c841
4
- data.tar.gz: 9781d32d0230aa6e376822cd9803cfbea2938084
3
+ metadata.gz: 642d94cc600de50ae308e592033b37eb76332797
4
+ data.tar.gz: 7df7585728a3fe621ed0200d0a83451e3ee0855e
5
5
  SHA512:
6
- metadata.gz: 7445c9ebc62962e3ee09bd7650d79545a3af9477c89fdfdf0d81b530713ebe012e90c3abe007cbfeec24df28c1624bfe94935c1794929363ccbc75759d80d7ca
7
- data.tar.gz: c5ea6e4a4d723d8e6f86e748bd7f969974bff2775bb18f38ca33c5d5f1a015a15b2df1ceb26e079337541381e8686a3cf5abc6d38c53d95962116007c640c974
6
+ metadata.gz: ca7b7e3247cfa18f6ba92aa9de44bb2e52f5cee6ff42a61ff64f9c2e6214b61a78f7bcb29d707f210b7062e998abd09c7dd4e4f224f7a1f27b2ce8e4081e989d
7
+ data.tar.gz: eee97be3e6b61d8f3e05a077217ef7d3b6b0659bf663e45c5b06899c7dd58ca8729811c298cef16c09f0c9fa8de01587997fec3e2d52e0cdc972181e4c24c317
data/CHANGES.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ # 0.5.0
4
+
5
+ * New single entry point, `PartialKs::KitchenSync`. This means that Runner and ConfigurationGenerator are now internal concerns
6
+
7
+ * Teach ModelsList about #issues - Basically a list of models where its "parent" is a MultiParent. Exposed via PartialKs::KitchenSync#issues
8
+
9
+ * Various refactors and simplifications
10
+
3
11
  # 0.4.2
4
12
 
5
13
  Fix an issue where we did not support the new ApplicationRecord convention
data/CONTRIBUTING.md CHANGED
@@ -2,7 +2,7 @@ This document should tell all you need to know for contributing to this project.
2
2
 
3
3
  # Testing
4
4
 
5
- Tested with activerecord 4.2.7.1, 4.2.8 and 5.0.2 (on Ruby 2.3.3)
5
+ Tested with activerecord 4.2.7.1, 4.2.8, 5.0.2, 5.1.0 (on Ruby 2.3.3)
6
6
 
7
7
 
8
8
  To install and run tests :
data/README.md CHANGED
@@ -8,9 +8,7 @@ So how does it work ?
8
8
 
9
9
 
10
10
  ```
11
- manual_configuration = []
12
- config = PartialKs::ConfigurationGenerator.new(manual_configuration).call
13
- PartialKs::Runner.new([config]).run! do |tables_to_filter, tables|
11
+ PartialKs::KitchenSync.new(manual_configuration).run! do |tables_to_filter, tables|
14
12
  puts tables_to_filter.inspect
15
13
  puts tables.inspect
16
14
  end
@@ -27,24 +25,12 @@ manual_configuration = [
27
25
 
28
26
  NB: The first use case for this gem is to be run in conjuction with [Kitchen Sync](https://github.com/willbryant/kitchen_sync). On OSX, one can install Kitchen Sync using `brew install kitchen-sync`
29
27
 
30
- *TODO*
31
-
32
- * Provide a way for users to pass in manual configurations
33
- * Tool to run report using bundle exec
34
-
35
28
  # Public API
36
29
 
37
30
  It currently consists of :
38
31
 
39
- - ConfigurationGenerator
40
- - Runner
41
- - runs
42
- - reports (mostly for debugging)
43
-
44
- *TODO*
32
+ - PartialKs::KitchenSync
45
33
 
46
- * Rename PartialKs::ConfigurationGenerator#call to something better
47
- * Minimize Public API
48
34
 
49
35
  # Not supported
50
36
 
@@ -3,8 +3,8 @@ module PartialKs
3
3
  attr_reader :table, :parent_model, :custom_filter_relation
4
4
  delegate :table_name, :to => :table
5
5
 
6
- def initialize(table, parent_model, custom_filter_relation: nil)
7
- @table = table
6
+ def initialize(model, parent_model, custom_filter_relation: nil)
7
+ @table = PartialKs::Table.new(model)
8
8
  @parent_model = parent_model
9
9
  @custom_filter_relation = custom_filter_relation
10
10
  end
@@ -0,0 +1,14 @@
1
+ module PartialKs
2
+ class KitchenSync
3
+ attr_reader :models_list
4
+ delegate :issues, to: :models_list
5
+
6
+ def initialize(manual_configuration)
7
+ @models_list = ModelsList.new(manual_configuration)
8
+ end
9
+
10
+ def run!(&block)
11
+ Runner.new(models_list.all).run!(&block)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ module PartialKs
2
+ class ModelsList
3
+ attr_reader :manual_configuration
4
+
5
+ def initialize(manual_configuration)
6
+ @manual_configuration = manual_configuration
7
+ end
8
+
9
+ def all
10
+ @all ||= manual_configuration + automatic_configuration_except_manual
11
+ end
12
+
13
+ def issues
14
+ all.select{|model, parent| parent.is_a?(PartialKs::MultiParent)}
15
+ end
16
+
17
+ private
18
+ def automatic_configuration_except_manual
19
+ tables_already_present = manual_configuration.map(&:first).map(&:table_name)
20
+
21
+ PartialKs.all_rails_models.reject{|model| tables_already_present.include?(model.table_name) }.map do |model|
22
+ table = PartialKs::Table.new(model)
23
+ [table.model, table.inferred_parent_class]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,9 +1,9 @@
1
1
  module PartialKs
2
2
  class Runner
3
- attr_reader :table_graphs
3
+ attr_reader :models_list
4
4
 
5
- def initialize(table_graphs)
6
- @table_graphs = table_graphs
5
+ def initialize(models_list)
6
+ @models_list = models_list
7
7
  end
8
8
 
9
9
  def run!
@@ -20,7 +20,6 @@ module PartialKs
20
20
  end
21
21
  end
22
22
 
23
- # TODO output only tables_to_filter, depending on how KS handles filters
24
23
  yield tables_to_filter, table_names
25
24
  end
26
25
  end
@@ -44,29 +43,31 @@ module PartialKs
44
43
  end
45
44
 
46
45
  protected
46
+ def filtered_tables
47
+ @filtered_tables ||= models_list.map {|model, parent, custom_filter| PartialKs::FilteredTable.new(model, parent, custom_filter_relation: custom_filter)}
48
+ end
49
+
47
50
  def generations
48
51
  return @generations if defined?(@generations)
49
52
 
50
53
  @generations = []
51
- table_graphs.each do |filtered_tables|
52
- q = []
54
+ q = []
53
55
 
54
- filtered_tables.each do |filtered_table|
55
- q << filtered_table if filtered_table.parent_model.nil?
56
- end
56
+ filtered_tables.each do |filtered_table|
57
+ q << filtered_table if filtered_table.parent_model.nil?
58
+ end
57
59
 
58
- until q.empty?
59
- @generations << q
60
+ until q.empty?
61
+ @generations << q
60
62
 
61
- next_generation = []
62
- q.each do |table|
63
- filtered_tables.each do |child_table|
64
- next_generation << child_table if child_table.parent_model && child_table.parent_model.table_name == table.table_name
65
- end
63
+ next_generation = []
64
+ q.each do |table|
65
+ filtered_tables.each do |child_table|
66
+ next_generation << child_table if child_table.parent_model && child_table.parent_model.table_name == table.table_name
66
67
  end
67
-
68
- q = next_generation
69
68
  end
69
+
70
+ q = next_generation
70
71
  end
71
72
 
72
73
  @generations
@@ -7,14 +7,14 @@ module PartialKs
7
7
  @model = model
8
8
  end
9
9
 
10
- # sometimes the table is present, but the model is not defined
11
- # e.g. in market specific tables
12
- def model?
13
- model && model.respond_to?(:table_name)
14
- end
15
-
16
- def top_level_table?
17
- candidate_parent_classes.empty?
10
+ def inferred_parent_class
11
+ if candidate_parent_classes.empty?
12
+ nil
13
+ elsif candidate_parent_classes.size == 1
14
+ candidate_parent_classes.first
15
+ else
16
+ MultiParent.new(candidate_parent_classes)
17
+ end
18
18
  end
19
19
 
20
20
  # NB: can't do polymorphic for now, rails errors on reflection#klass
@@ -23,10 +23,6 @@ module PartialKs
23
23
  non_nullable_reflections.reject(&:polymorphic?).map(&:klass)
24
24
  end
25
25
 
26
- def parent_tables
27
- belongs_to_reflections.map(&:table_name)
28
- end
29
-
30
26
  def relation_for_associated_model(klass)
31
27
  association = model.reflect_on_all_associations.find {|assoc| assoc.class_name == klass.name}
32
28
  raise "#{filter_condition.name} not found in #{model.name} associations" if association.nil?
@@ -55,4 +51,21 @@ module PartialKs
55
51
  end
56
52
  end
57
53
  end
54
+
55
+ class MultiParent
56
+ attr_reader :parents
57
+
58
+ def initialize(parents)
59
+ @parents = parents
60
+ end
61
+
62
+ def ==(other)
63
+ table_name == other.table_name if other
64
+ end
65
+
66
+ # only used in comparison in Runner
67
+ def table_name
68
+ parents.map(&:table_name).join(",")
69
+ end
70
+ end
58
71
  end
@@ -1,3 +1,3 @@
1
1
  module PartialKs
2
- VERSION = '0.4.2'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/partial_ks.rb CHANGED
@@ -2,7 +2,7 @@ require 'active_record'
2
2
 
3
3
  require_relative 'partial_ks/all_rails_models'
4
4
  require_relative 'partial_ks/filtered_table'
5
- require_relative 'partial_ks/parent_inferrer'
6
5
  require_relative 'partial_ks/runner'
7
6
  require_relative 'partial_ks/table'
8
- require_relative 'partial_ks/configuration_generator'
7
+ require_relative 'partial_ks/models_list'
8
+ require_relative 'partial_ks/kitchen_sync'
data/partial_ks.gemspec CHANGED
@@ -10,7 +10,7 @@ EOF
10
10
  gem.has_rdoc = false
11
11
  gem.author = "Thong Kuah"
12
12
  gem.email = "kuahyeow@gmail.com"
13
- gem.homepage = "https://github.com/powershop/partial_ks"
13
+ gem.homepage = "https://github.com/fluxfederation/partial_ks"
14
14
  gem.license = "MIT"
15
15
 
16
16
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -16,4 +16,15 @@ describe "all rails tables" do
16
16
  it "returns the same number of models as the number of tables" do
17
17
  PartialKs.all_rails_models.map(&:table_name).sort.must_equal ActiveRecord::Base.connection.tables.sort
18
18
  end
19
+
20
+ it "does not choke on a table which has had its migration run" do
21
+ PartialKs.all_rails_models.wont_include NewModel
22
+ end
23
+
24
+ it "can return models with different table_name" do
25
+ model = OldEntry
26
+ model.table_name.wont_equal model.name.tableize
27
+
28
+ PartialKs.all_rails_models.must_include model
29
+ end
19
30
  end
@@ -1,10 +1,5 @@
1
1
  require 'test_helper'
2
2
 
3
- def generator(manual, tables)
4
- PartialKs::ConfigurationGenerator.new(manual, tables).call.
5
- map {|f| [f.table_name, f.parent_model, f.custom_filter_relation] }
6
- end
7
-
8
3
  describe "generating dependencies" do
9
4
  let(:manual_configuration) do
10
5
  [
@@ -12,39 +7,17 @@ describe "generating dependencies" do
12
7
  ]
13
8
  end
14
9
 
15
- # TODO remove redundant test (cf parent_inferrer_test)
16
- it "auto infers single belongs-to dependencies" do
17
- generator(manual_configuration, models: [User, BlogPost]).
18
- must_equal [
19
- ["users", nil, User.where(:id => [1])],
20
- ["blog_posts", User, nil]
21
- ]
10
+ it "returns the manual_configuration" do
11
+ result = PartialKs::ModelsList.new(manual_configuration).all
12
+ result.must_include manual_configuration.first
22
13
  end
23
14
 
24
- # TODO remove redundant test (cf parent_inferrer_test)
25
- it "auto infers top level tables" do
26
- generator(manual_configuration, models: [User, Tag]).
27
- must_equal [
28
- ["users", nil, User.where(:id => [1])],
29
- ["tags", nil, nil]
30
- ]
15
+ it "processes all models" do
16
+ result = PartialKs::ModelsList.new(manual_configuration).all
17
+ result.size.must_equal PartialKs.all_rails_models.size
31
18
  end
32
19
 
33
- it "can return models with different table_name" do
34
- model = OldEntry
35
- model.table_name.wont_equal model.name.tableize
36
-
37
- generator(manual_configuration, models: [User, model]).
38
- must_equal [
39
- ["users", nil, User.where(:id => [1])],
40
- ["cms_table", nil, nil]
41
- ]
42
- end
43
-
44
- it "does not choke on a table which has had its migration run" do
45
- generator(manual_configuration, models: [User, NewModel]).
46
- must_equal [
47
- ["users", nil, User.where(:id => [1])],
48
- ]
20
+ it "can identify MultiParent as issues" do
21
+ PartialKs::ModelsList.new(manual_configuration).issues.map(&:last).map(&:class).must_equal [PartialKs::MultiParent]
49
22
  end
50
23
  end
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
 
3
3
  describe "kitchen sync filter" do
4
- let(:table) { PartialKs::Table.new(PostTag) }
4
+ let(:model) { PostTag }
5
5
  let(:parent) { Minitest::Mock.new }
6
6
 
7
7
  it "proxies to Table if there's parent only" do
@@ -9,39 +9,39 @@ describe "kitchen sync filter" do
9
9
  relation_mock = Minitest::Mock.new
10
10
  relation_mock.expect :where_sql, "WHERE tag_id IN (0)"
11
11
 
12
- filtered_table = PartialKs::FilteredTable.new(table, parent)
13
- table.stub table_parent_relation_method, relation_mock do
12
+ filtered_table = PartialKs::FilteredTable.new(model, parent)
13
+ filtered_table.table.stub table_parent_relation_method, relation_mock do
14
14
  filtered_table.kitchen_sync_filter.must_equal({"only" => 'tag_id IN (0)'})
15
15
  end
16
16
  end
17
17
 
18
18
  it "uses the custom filter if provided" do
19
19
  filter = PostTag.where(:id => [1, 2])
20
- filtered_table = PartialKs::FilteredTable.new(table, nil, custom_filter_relation: filter)
20
+ filtered_table = PartialKs::FilteredTable.new(model, nil, custom_filter_relation: filter)
21
21
  filtered_table.kitchen_sync_filter.must_equal({"only" => '"post_tags"."id" IN (1, 2)'})
22
22
  end
23
23
 
24
24
  it "uses the filter inside a lambda" do
25
25
  filter = -> { PostTag.where(:id => [1, 2]) }
26
- filtered_table = PartialKs::FilteredTable.new(table, nil, custom_filter_relation: filter)
26
+ filtered_table = PartialKs::FilteredTable.new(model, nil, custom_filter_relation: filter)
27
27
  filtered_table.kitchen_sync_filter.must_equal({"only" => '"post_tags"."id" IN (1, 2)'})
28
28
  end
29
29
 
30
30
  it "uses a SQL where fragment as a filter if provided" do
31
31
  string_filter = "1=0"
32
- filtered_table = PartialKs::FilteredTable.new(table, nil, custom_filter_relation: string_filter)
32
+ filtered_table = PartialKs::FilteredTable.new(model, nil, custom_filter_relation: string_filter)
33
33
  filtered_table.kitchen_sync_filter.must_equal({"only" => string_filter})
34
34
  end
35
35
 
36
36
  it "uses a SQL statement as a filter if provided" do
37
37
  string_filter = "1=0"
38
- sql_statement = "select * from #{table.table_name} where #{string_filter}"
39
- filtered_table = PartialKs::FilteredTable.new(table, nil, custom_filter_relation: sql_statement)
38
+ sql_statement = "select * from #{model.table_name} where #{string_filter}"
39
+ filtered_table = PartialKs::FilteredTable.new(model, nil, custom_filter_relation: sql_statement)
40
40
  filtered_table.kitchen_sync_filter.must_equal({"only" => string_filter})
41
41
  end
42
42
 
43
43
  it "returns nil if parent is nil" do
44
- filtered_table = PartialKs::FilteredTable.new(table, nil)
44
+ filtered_table = PartialKs::FilteredTable.new(model, nil)
45
45
  filtered_table.kitchen_sync_filter.must_be_nil
46
46
  end
47
47
 
@@ -3,16 +3,16 @@ require 'test_helper'
3
3
  describe "inferring parents" do
4
4
  it "infers no parent for a top level table" do
5
5
  table = PartialKs::Table.new(Tag)
6
- PartialKs::ParentInferrer.new(table).inferred_parent_class.must_be_nil
6
+ table.inferred_parent_class.must_be_nil
7
7
  end
8
8
 
9
9
  it "infers a parent for a table that has a single belongs_to" do
10
10
  table = PartialKs::Table.new(BlogPost)
11
- PartialKs::ParentInferrer.new(table).inferred_parent_class.must_equal User
11
+ table.inferred_parent_class.must_equal User
12
12
  end
13
13
 
14
- it "infers no parent for a table has multiple belongs_to" do
14
+ it "infers a multi-parent for a table has multiple belongs_to" do
15
15
  table = PartialKs::Table.new(PostTag)
16
- lambda { PartialKs::ParentInferrer.new(table).inferred_parent_class }.must_raise PartialKs::ParentInferrer::CannotInfer
16
+ table.inferred_parent_class.must_equal PartialKs::MultiParent.new([BlogPost, Tag])
17
17
  end
18
18
  end
data/test/runner_test.rb CHANGED
@@ -2,29 +2,29 @@ require 'test_helper'
2
2
 
3
3
  describe 'end to end testing' do
4
4
  it "runs without error" do
5
- generator_output = PartialKs::ConfigurationGenerator.new([]).call
6
- PartialKs::Runner.new([generator_output]).run! do |tables_to_filter, table_names|
7
- # left empty
5
+ count = 0
6
+ multi_parents = [PostTag]
7
+
8
+ generator_output = PartialKs::ModelsList.new([]).all
9
+ PartialKs::Runner.new(generator_output).run! do |tables_to_filter, table_names|
10
+ count += table_names.size
8
11
  end
12
+
13
+ count.must_equal PartialKs.all_rails_models.size - multi_parents.size
9
14
  end
10
15
  end
11
16
 
12
17
  describe 'running based on output from generator' do
13
- let(:manual_configuration) do
14
- [
15
- ["users", nil, User.where(:id => [1])],
16
- ]
17
- end
18
-
19
18
  let(:generator_output) do
20
19
  [
21
- PartialKs::FilteredTable.new(PartialKs::Table.new(User), nil, custom_filter_relation: User.where(:id => [1])),
22
- PartialKs::FilteredTable.new(PartialKs::Table.new(Tag), nil),
23
- PartialKs::FilteredTable.new(PartialKs::Table.new(BlogPost), User),
20
+ [User, nil, User.where(:id => [1])],
21
+ [Tag, nil],
22
+ [BlogPost, User],
23
+ [PostTag, PartialKs::MultiParent.new([BlogPost, Tag])],
24
24
  ]
25
25
  end
26
26
 
27
- let(:runner) { PartialKs::Runner.new([generator_output]) }
27
+ let(:runner) { PartialKs::Runner.new(generator_output) }
28
28
 
29
29
  it "reports everything" do
30
30
  runner.report.must_equal [
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: partial_ks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thong Kuah
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-14 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -69,9 +69,9 @@ files:
69
69
  - Rakefile
70
70
  - lib/partial_ks.rb
71
71
  - lib/partial_ks/all_rails_models.rb
72
- - lib/partial_ks/configuration_generator.rb
73
72
  - lib/partial_ks/filtered_table.rb
74
- - lib/partial_ks/parent_inferrer.rb
73
+ - lib/partial_ks/kitchen_sync.rb
74
+ - lib/partial_ks/models_list.rb
75
75
  - lib/partial_ks/runner.rb
76
76
  - lib/partial_ks/table.rb
77
77
  - lib/partial_ks/version.rb
@@ -86,7 +86,7 @@ files:
86
86
  - test/setup_models.rb
87
87
  - test/table_test.rb
88
88
  - test/test_helper.rb
89
- homepage: https://github.com/powershop/partial_ks
89
+ homepage: https://github.com/fluxfederation/partial_ks
90
90
  licenses:
91
91
  - MIT
92
92
  metadata: {}
@@ -1,66 +0,0 @@
1
- # Given an initial table graph
2
- # goes through each table not already in the table graph,
3
- # and attempts to automatically populate the table into the table graph
4
- module PartialKs
5
- class ConfigurationGenerator
6
- attr_reader :manual_configuration
7
-
8
- def initialize(manual_configuration, models: nil)
9
- @manual_configuration = manual_configuration
10
- @models = models || PartialKs.all_rails_models
11
- end
12
-
13
- def call
14
- @filtered_tables ||= filtered_tables
15
- end
16
-
17
- protected
18
- def all_tables
19
- @all_tables ||= models.map {|model| PartialKs::Table.new(model) }.select(&:model?).index_by(&:table_name)
20
- end
21
-
22
- def models
23
- tables_in_database = ActiveRecord::Base.connection.tables
24
- @models.select{|model| tables_in_database.include?(model.table_name)}
25
- end
26
-
27
- def filtered_tables
28
- synced_tables = {}
29
-
30
- manual_configuration.each do |model, specified_parent_model, filter_for_table|
31
- table_name = model.table_name
32
- next unless all_tables[table_name]
33
-
34
- parent_model = specified_parent_model
35
- synced_tables[table_name] = PartialKs::FilteredTable.new(all_tables[table_name], parent_model, custom_filter_relation: filter_for_table)
36
- end
37
-
38
- all_tables.each do |table_name, table|
39
- next if synced_tables[table_name]
40
-
41
- begin
42
- inferrer = PartialKs::ParentInferrer.new(table)
43
- parent_model = inferrer.inferred_parent_class
44
- synced_tables[table_name] = PartialKs::FilteredTable.new(table, parent_model)
45
- rescue PartialKs::ParentInferrer::CannotInfer
46
- next
47
- end
48
-
49
- end
50
-
51
- # TODO remove this side effect. Maybe yield or a different method call ?
52
- puts "***************"
53
- remaining_size = 0
54
- all_tables.each do |table_name, table|
55
- next if synced_tables[table_name]
56
-
57
- puts "#{table.table_name} - #{table.parent_tables.join(',')}"
58
- remaining_size += 1
59
- end
60
- puts "WARNING: #{remaining_size} tables has no configuration"
61
-
62
- synced_tables.values
63
- end
64
-
65
- end
66
- end
@@ -1,21 +0,0 @@
1
- module PartialKs
2
- class ParentInferrer
3
- CannotInfer = Class.new(StandardError)
4
-
5
- attr_reader :table
6
-
7
- def initialize(table)
8
- @table = table
9
- end
10
-
11
- def inferred_parent_class
12
- if table.top_level_table?
13
- nil
14
- elsif table.candidate_parent_classes.size == 1
15
- table.candidate_parent_classes.first
16
- else
17
- raise CannotInfer, "table has multiple candidates for parents"
18
- end
19
- end
20
- end
21
- end