arin 0.1.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b10ee0ba80cabed89245ed72f491f0bbbc73196
4
- data.tar.gz: 11962da1cfa1b6c7cf488268d72878955eb3a08d
3
+ metadata.gz: 2fd1981d6157a72fe95604cb03d0600fc451760d
4
+ data.tar.gz: 2671fca3c0624c6f2a24f65d21d482a117045d10
5
5
  SHA512:
6
- metadata.gz: 0a2f393223c258d6d5b6c670f5fd17ccad39324c721a5c8eab9d083e0d91d99f135f13c71fc5d3d0b920444fb62598bce5a018c6ac5a22f7e380c506a5a37e3c
7
- data.tar.gz: 4850e75ea2a42fea3a6ff67f51d2cce4cfe1581126ea53f57b5b6486a5be5a9420dac1791e226f5b7ac2cbc69241043911e4f0794418f70fb12394bd6378a74f
6
+ metadata.gz: 82070bd541eee0ecfe9b353cbea7e7d73db7f6b0cf0645f66ba5fcab83ae15feddd54b496a60820df5147d8a46ed39df42d6b793df68f58adde8979767581d62
7
+ data.tar.gz: f313027570cc47695e7bac51e9dc20ee45a5322a5c268eab12ac001e33ace7edc32a8b74ec80445276ee97bf0dad04fb493a6b9fd954c975837c256688228173
data/README.md CHANGED
@@ -7,7 +7,7 @@ Arin - ActiveRecord integrity checking tool
7
7
  Add this line to your application's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'arin', github: 'fmnoise/arin'
10
+ gem 'arin'
11
11
  ```
12
12
 
13
13
  And then execute:
@@ -22,21 +22,21 @@ Or install it yourself as:
22
22
 
23
23
  Consider the example: Order belongs to User which doesn't exist anymore.
24
24
 
25
- In order to find models of certain class which points to non-existant entities we need to pass class contant to constructor
25
+ In order to find models of certain class which points to non-existant entities we need to pass class constant to constructor:
26
26
  ```ruby
27
27
  Arin::Check.new(Order).issues
28
28
 
29
29
  # callable object style
30
30
  Arin::Check.(Order)
31
31
  ```
32
- Multiple classes should be passed as array
32
+ Multiple classes should be passed as array:
33
33
  ```ruby
34
34
  Arin::Check.new([Payment, Order]).issues
35
35
 
36
36
  # callable object style
37
37
  Arin::Check.([Payment, Order])
38
38
  ```
39
- Omit parameters to check all loaded models
39
+ Omit parameters to check all loaded models:
40
40
  ```ruby
41
41
  Rails.application.eager_load!
42
42
  Arin::Check.new.issues
@@ -45,9 +45,16 @@ Arin::Check.new.issues
45
45
  Arin::Check.()
46
46
  ```
47
47
 
48
- Working with found issues collection which is simple array of `Arin::Issue` instances
48
+ Working with found issues collection which is simple array of `Arin::Issue` instances:
49
49
  ```ruby
50
- issue = Arin::Check.().first
50
+ issues = Arin::Check.()
51
+
52
+ # getting stats
53
+ issues.group_by(&:class_name).map{ |k,v| Hash[k, v.size] }
54
+ => [{"Order"=>3}, {"Payment"=>2}]
55
+
56
+ # getting issue info
57
+ issue = issues.first
51
58
  => #<Arin::Issue:0x007f9fe2823af0
52
59
  @class_name="Order",
53
60
  @id=6789,
@@ -66,6 +73,7 @@ issue.relation_class
66
73
  issue.relation_id
67
74
  => 4567
68
75
 
76
+ # getting reported object
69
77
  issue.object
70
78
  => #<Order:0x007f9fdfbd9af8
71
79
  id: 6789,
@@ -74,6 +82,10 @@ issue.object
74
82
  updated_at: Sun, 20 Jun 2017 20:06:36 UTC +00:00>
75
83
  ```
76
84
 
85
+ ## TODO
86
+
87
+ Add tests
88
+
77
89
  ## Development
78
90
 
79
91
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -82,7 +94,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
82
94
 
83
95
  ## Contributing
84
96
 
85
- *The main idea behind Arin development is to stay as small and unopinionated as possible*
97
+ **The main idea behind Arin development is to stay as small and unopinionated as possible**
98
+
86
99
  Bug reports and pull requests are welcome on GitHub at https://github.com/fmnoise/arin.
87
100
 
88
101
  ## License
data/lib/arin/check.rb CHANGED
@@ -33,18 +33,36 @@ module Arin
33
33
  end
34
34
 
35
35
  def query
36
- subqueries = []
37
- classes.each do |klass|
38
- klass.reflect_on_all_associations(:belongs_to).each do |relation|
39
- q = relation_query(klass, relation) rescue nil
40
- subqueries << q if q && processable?(klass, relation)
41
- end
42
- end
43
- subqueries.join <<-SQL
36
+ queries.join <<-SQL
44
37
  UNION ALL
45
38
  SQL
46
39
  end
47
40
 
41
+ def queries
42
+ [].tap do |qs|
43
+ classes.each do |klass|
44
+ klass.reflect_on_all_associations(:belongs_to).each do |relation|
45
+ begin
46
+ if is_polymorphic?(relation)
47
+ polymorphics(klass, relation).each do |poly|
48
+ poly_class = poly.safe_constantize
49
+ if poly_class
50
+ qs << polymorphic_relation_query(klass, relation, poly_class)
51
+ else
52
+ qs << broken_polymorchic_class_query(klass, relation, poly)
53
+ end
54
+ end
55
+ else
56
+ qs << relation_query(klass, relation) if processable?(klass, relation)
57
+ end
58
+ rescue StandardError => e
59
+ handle_query_failure(klass, relation, e)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
48
66
  def processable?(klass, relation)
49
67
  klass.table_exists? &&
50
68
  klass.primary_key &&
@@ -64,5 +82,43 @@ module Arin
64
82
  AND t.#{relation.foreign_key} IS NOT NULL
65
83
  SQL
66
84
  end
85
+
86
+ def polymorphic_relation_query(klass, relation, relation_class)
87
+ <<-SQL
88
+ SELECT "#{klass.name}" AS class_name,
89
+ t.#{klass.primary_key} AS id,
90
+ "#{relation_class}" AS relation_class,
91
+ t.#{relation.foreign_key} AS relation_id
92
+ FROM #{klass.table_name} AS t
93
+ LEFT JOIN #{relation_class.table_name} AS r
94
+ ON t.#{relation.foreign_key} = r.#{relation_class.primary_key}
95
+ AND t.#{relation.foreign_type} = "#{relation_class}"
96
+ WHERE r.#{relation_class.primary_key} IS NULL
97
+ AND t.#{relation.foreign_key} IS NOT NULL
98
+ SQL
99
+ end
100
+
101
+ def broken_polymorphic_class_query(klass, relation, relation_class)
102
+ <<-SQL
103
+ SELECT "#{klass.name}" AS class_name,
104
+ t.#{klass.primary_key} AS id,
105
+ "#{relation_class}" AS relation_class,
106
+ t.#{relation.foreign_key} AS relation_id
107
+ FROM #{klass.table_name} AS t
108
+ WHERE t.#{relation.foreign_type} = "#{relation_class}"
109
+ SQL
110
+ end
111
+
112
+ def polymorphics(klass, relation)
113
+ klass.pluck(relation.foreign_type).uniq.compact
114
+ end
115
+
116
+ def is_polymorphic?(relation)
117
+ relation.options[:polymorphic]
118
+ end
119
+
120
+ def handle_query_failure(klass, relation, e)
121
+ warn("Cannot process #{relation.name} relation for #{klass}: #{e.message}")
122
+ end
67
123
  end
68
124
  end
data/lib/arin/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Arin
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - fmnoise@gmail.com