arin 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b10ee0ba80cabed89245ed72f491f0bbbc73196
4
+ data.tar.gz: 11962da1cfa1b6c7cf488268d72878955eb3a08d
5
+ SHA512:
6
+ metadata.gz: 0a2f393223c258d6d5b6c670f5fd17ccad39324c721a5c8eab9d083e0d91d99f135f13c71fc5d3d0b920444fb62598bce5a018c6ac5a22f7e380c506a5a37e3c
7
+ data.tar.gz: 4850e75ea2a42fea3a6ff67f51d2cce4cfe1581126ea53f57b5b6486a5be5a9420dac1791e226f5b7ac2cbc69241043911e4f0794418f70fb12394bd6378a74f
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 fmnoise@gmail.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # Arin
2
+
3
+ Arin - ActiveRecord integrity checking tool
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'arin', github: 'fmnoise/arin'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install arin
20
+
21
+ ## Usage
22
+
23
+ Consider the example: Order belongs to User which doesn't exist anymore.
24
+
25
+ In order to find models of certain class which points to non-existant entities we need to pass class contant to constructor
26
+ ```ruby
27
+ Arin::Check.new(Order).issues
28
+
29
+ # callable object style
30
+ Arin::Check.(Order)
31
+ ```
32
+ Multiple classes should be passed as array
33
+ ```ruby
34
+ Arin::Check.new([Payment, Order]).issues
35
+
36
+ # callable object style
37
+ Arin::Check.([Payment, Order])
38
+ ```
39
+ Omit parameters to check all loaded models
40
+ ```ruby
41
+ Rails.application.eager_load!
42
+ Arin::Check.new.issues
43
+
44
+ # callable object style
45
+ Arin::Check.()
46
+ ```
47
+
48
+ Working with found issues collection which is simple array of `Arin::Issue` instances
49
+ ```ruby
50
+ issue = Arin::Check.().first
51
+ => #<Arin::Issue:0x007f9fe2823af0
52
+ @class_name="Order",
53
+ @id=6789,
54
+ @relation_class="User",
55
+ @relation_id=4567>
56
+
57
+ issue.class_name
58
+ => "Order"
59
+
60
+ issue.id
61
+ => 6789
62
+
63
+ issue.relation_class
64
+ => "User"
65
+
66
+ issue.relation_id
67
+ => 4567
68
+
69
+ issue.object
70
+ => #<Order:0x007f9fdfbd9af8
71
+ id: 6789,
72
+ user_id: 4567
73
+ created_at: Tue, 15 Dec 2016 01:45:37 UTC +00:00,
74
+ updated_at: Sun, 20 Jun 2017 20:06:36 UTC +00:00>
75
+ ```
76
+
77
+ ## Development
78
+
79
+ 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.
80
+
81
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
82
+
83
+ ## Contributing
84
+
85
+ *The main idea behind Arin development is to stay as small and unopinionated as possible*
86
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fmnoise/arin.
87
+
88
+ ## License
89
+
90
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "arin"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/arin/check.rb ADDED
@@ -0,0 +1,68 @@
1
+ require_relative './issue'
2
+
3
+ module Arin
4
+ class Check
5
+ attr_reader :classes
6
+
7
+ def self.call(classes = [])
8
+ self.new(classes).issues
9
+ end
10
+
11
+ def initialize(classes = [])
12
+ @classes = Array(classes).presence || all_classes
13
+ end
14
+
15
+ def issues
16
+ @issues ||= raw_results.map do |entry|
17
+ Arin::Issue.new \
18
+ class_name: entry['class_name'],
19
+ id: entry['id'],
20
+ relation_class: entry['relation_class'],
21
+ relation_id: entry['relation_id']
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def raw_results
28
+ query.present? ? ActiveRecord::Base.connection.select_all(query) : []
29
+ end
30
+
31
+ def all_classes
32
+ ActiveRecord::Base.descendants
33
+ end
34
+
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
44
+ UNION ALL
45
+ SQL
46
+ end
47
+
48
+ def processable?(klass, relation)
49
+ klass.table_exists? &&
50
+ klass.primary_key &&
51
+ klass.column_names.include?(relation.foreign_key)
52
+ end
53
+
54
+ def relation_query(klass, relation)
55
+ <<-SQL
56
+ SELECT "#{klass.name}" AS class_name,
57
+ t.#{klass.primary_key} AS id,
58
+ "#{relation.class_name}" AS relation_class,
59
+ t.#{relation.foreign_key} AS relation_id
60
+ FROM #{klass.table_name} AS t
61
+ LEFT JOIN #{relation.table_name} AS r
62
+ ON t.#{relation.foreign_key} = r.#{relation.association_primary_key}
63
+ WHERE r.#{relation.association_primary_key} IS NULL
64
+ AND t.#{relation.foreign_key} IS NOT NULL
65
+ SQL
66
+ end
67
+ end
68
+ end
data/lib/arin/issue.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Arin
2
+ class Issue
3
+ attr_reader :class_name, :id, :relation_class, :relation_id
4
+
5
+ def initialize(class_name:, id:, relation_class:, relation_id:)
6
+ @class_name = class_name
7
+ @id = id
8
+ @relation_class = relation_class
9
+ @relation_id = relation_id
10
+ end
11
+
12
+ def object
13
+ @object ||= class_name.constantize.find(id)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Arin
2
+ VERSION = "0.1.1"
3
+ end
data/lib/arin.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "arin/version"
2
+ require "arin/check"
3
+
4
+ module Arin
5
+ end
data/spec/arin_spec.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Arin do
4
+ it "has a version number" do
5
+ expect(Arin::VERSION).not_to be nil
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require "bundler/setup"
2
+ require "arin"
3
+
4
+ RSpec.configure do |config|
5
+ # Enable flags like --only-failures and --next-failure
6
+ config.example_status_persistence_file_path = ".rspec_status"
7
+
8
+ config.expect_with :rspec do |c|
9
+ c.syntax = :expect
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - fmnoise@gmail.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description:
70
+ email:
71
+ - fmnoise@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - Gemfile
77
+ - LICENSE.txt
78
+ - README.md
79
+ - Rakefile
80
+ - bin/console
81
+ - bin/setup
82
+ - lib/arin.rb
83
+ - lib/arin/check.rb
84
+ - lib/arin/issue.rb
85
+ - lib/arin/version.rb
86
+ - spec/arin_spec.rb
87
+ - spec/spec_helper.rb
88
+ homepage:
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.2.2
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: ActiveRecord Integrity checking tool
112
+ test_files: []