arin 0.1.1 → 0.1.2

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: 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