n_1_finder 0.0.4 → 0.0.5

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: 53d31e40235f5510cee7b906ce2c83f76d681eb3
4
- data.tar.gz: bc1cf15f6593999d87e9f4f10c9e1ab2fcc1cc54
3
+ metadata.gz: 961ceb11825e90ca10011fb5d9be594976e31d30
4
+ data.tar.gz: 2223479f079ca9e0c1e1384243e76ad249babf64
5
5
  SHA512:
6
- metadata.gz: bf40aa00184ebd40ae71ad11e7d19d70af0a7dbd9d3795afe3f9c30cfd9c00246287bf7da75ab975493b839b5630595e83ffe95664542a97f043a9f2ac2b0e2d
7
- data.tar.gz: 7ea778e457f4de2dc18d74e48c8d5755722254a76046682eeff1606324a577d4d74f66b70559e05639f5ab4f74332557f5ef3f9d6a5a02e47f82e41436452874
6
+ metadata.gz: a15d14a85b1293769a7f11b77ff2fd0009b15e43502c8b1bb3ca3393d4f8682bfe71eceab4a5064e7470879498d835b6c4d8a3da7d73556a06089f03d98e0930
7
+ data.tar.gz: d5814f4732a51d49a1fde41f3a2d5ef7b9125910aae695ea686a959d6b02e0d531a0d0bc572fa20e11998bbd2de6f552e6830a122a61ea7d4ef2fba1174cc2ce
data/Readme.md CHANGED
@@ -2,6 +2,7 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/n_1_finder.svg)](https://badge.fury.io/rb/n_1_finder)
3
3
  [![Build Status](https://api.travis-ci.org/aglushkov/n1_finder.svg?branch=master)](https://travis-ci.org/aglushkov/n1_finder)
4
4
  [![Inline docs](http://inch-ci.org/github/aglushkov/n1_finder.svg?branch=master)](http://inch-ci.org/github/aglushkov/n1_finder)
5
+ [![Code Climate](https://codeclimate.com/github/aglushkov/n1_finder/badges/gpa.svg)](https://codeclimate.com/github/aglushkov/n1_finder)
5
6
 
6
7
  This gem helps to find N+1 queries.
7
8
 
@@ -12,27 +13,6 @@
12
13
  ## Installation
13
14
  `gem 'n_1_finder', group: :development`
14
15
 
15
- ## Configuration
16
- ### Logger
17
- Default is `Logger.new(STDOUT)`
18
-
19
- Logger can be any instance of `Logger` class.
20
-
21
- ```ruby
22
- N1Finder.logger = Logger.new('log/n1.log')
23
- ```
24
-
25
- ### ORM
26
- Default is `:active_record` if you have activerecord gem installed.
27
-
28
- Default is `:sequel` if you have sequel gem installed.
29
-
30
- Allowed values are `:active_record` and `:sequel`
31
-
32
- ```ruby
33
- N1Finder.orm = :active_record
34
- ```
35
-
36
16
  ## Using
37
17
  Include middleware to your Rack app:
38
18
  ```ruby
@@ -68,6 +48,27 @@ N+1 QUERY DETECTED:
68
48
  SELECT "comments".* FROM "comments" WHERE "comments"."user_id" = $1, user_id = 947
69
49
  ```
70
50
 
51
+ ## Configuration
52
+ ### Logger
53
+ Default is `Logger.new(STDOUT)`
54
+
55
+ Logger can be any instance of `Logger` class.
56
+
57
+ ```ruby
58
+ N1Finder.logger = Logger.new('log/n1.log')
59
+ ```
60
+
61
+ ### ORM
62
+ Default is `:active_record` if you have activerecord gem installed.
63
+
64
+ Default is `:sequel` if you have sequel gem installed.
65
+
66
+ Allowed values are `:active_record` and `:sequel`
67
+
68
+ ```ruby
69
+ N1Finder.orm = :active_record
70
+ ```
71
+
71
72
  ## Running tests
72
73
  - Copy `spec/.env.example` file to `spec/.env` and set database credentials.
73
74
  ```bash
data/lib/n_1_finder.rb CHANGED
@@ -1,32 +1,7 @@
1
- require 'n_1_finder/logger'
2
- require 'n_1_finder/middleware'
3
- require 'n_1_finder/query'
4
- require 'n_1_finder/n_1_query'
5
- require 'n_1_finder/storage'
6
- require 'n_1_finder/adapters/base_adapter'
7
- require 'n_1_finder/adapters/active_record_adapter'
8
- require 'n_1_finder/adapters/sequel_adapter'
9
- require 'n_1_finder/adapters/null_adapter'
10
-
11
1
  # Main class
12
2
  class N1Finder
13
- # Base error
14
- # @api private
15
- class Invalid < StandardError; end
16
-
17
- # Raised when specifying invalid ORM
18
- # @api private
19
- class InvalidORM < Invalid; end
20
-
21
- # Raised when specifying invalid logger
22
- # @api private
23
- class InvalidLogger < Invalid; end
24
-
25
3
  # Supported ORM adapters
26
- ORM_ADAPTERS = {
27
- active_record: N1Finder::Adapters::ActiveRecordAdapter,
28
- sequel: N1Finder::Adapters::SequelAdapter
29
- }.freeze
4
+ ORM_ADAPTERS = [:active_record, :sequel].freeze
30
5
 
31
6
  class << self
32
7
  # Supported ORM adapters
@@ -37,10 +12,10 @@ class N1Finder
37
12
  #
38
13
  # @return [void] result of block call
39
14
  def find
40
- storage = N1Finder::Storage.new
15
+ storage = Storage.new
41
16
  result = catch_queries(storage) { yield }
42
- n1_queries = N1Finder::N1Query.generate_by(storage.queries)
43
- N1Finder::Logger.new.log(n1_queries)
17
+ n1_queries = N1Query.generate_by(storage.queries)
18
+ Logger.new.log(n1_queries)
44
19
 
45
20
  result
46
21
  end
@@ -59,11 +34,11 @@ class N1Finder
59
34
  # @param [Logger] custom_logger
60
35
  # Must be instance of `Logger`
61
36
  #
62
- # @raise [N1Finder::InvalidLogger] If custom_logger is not an instance of `Logger`.
37
+ # @raise [N1Finder::Errors::InvalidLogger] If custom_logger is not an instance of `Logger`.
63
38
  #
64
39
  # @return [Logger]
65
40
  def logger=(custom_logger)
66
- raise N1Finder::InvalidLogger unless custom_logger.is_a?(::Logger)
41
+ raise Errors::InvalidLogger unless custom_logger.is_a?(::Logger)
67
42
 
68
43
  @logger = custom_logger
69
44
  end
@@ -75,12 +50,11 @@ class N1Finder
75
50
  #
76
51
  # @return [Symbol, nil]
77
52
  def orm
78
- @orm ||=
79
- if defined?(ActiveRecord)
80
- :active_record
81
- elsif defined?(Sequel)
82
- :sequel
83
- end
53
+ @orm ||= if defined?(ActiveRecord)
54
+ :active_record
55
+ elsif defined?(Sequel)
56
+ :sequel
57
+ end
84
58
  end
85
59
 
86
60
  # Configure ORM
@@ -88,11 +62,11 @@ class N1Finder
88
62
  # @param [Symbol] custom_orm
89
63
  # Must be `:active_record` or `:sequel`
90
64
  #
91
- # @raise [N1Finder::InvalidORM] If custom_orm is not in allowed list.
65
+ # @raise [N1Finder::Errors::InvalidORM] If custom_orm is not in allowed list.
92
66
  #
93
67
  # @return [Symbol]
94
68
  def orm=(custom_orm)
95
- raise N1Finder::InvalidORM unless ORM_ADAPTERS.keys.include?(custom_orm)
69
+ raise Errors::InvalidORM unless ORM_ADAPTERS.include?(custom_orm)
96
70
 
97
71
  @orm = custom_orm
98
72
  end
@@ -100,12 +74,22 @@ class N1Finder
100
74
  private
101
75
 
102
76
  def catch_queries(storage)
103
- adapter = adapter_class.new(storage)
77
+ adapter = Adapters::Factory.get(orm, storage)
104
78
  adapter.exec(&Proc.new)
105
79
  end
106
-
107
- def adapter_class
108
- ORM_ADAPTERS[orm] || N1Finder::Adapters::NullAdapter
109
- end
110
80
  end
111
81
  end
82
+
83
+ require 'n_1_finder/logger'
84
+ require 'n_1_finder/middleware'
85
+ require 'n_1_finder/query'
86
+ require 'n_1_finder/n_1_query'
87
+ require 'n_1_finder/storage'
88
+ require 'n_1_finder/adapters/factory'
89
+ require 'n_1_finder/adapters/base_adapter'
90
+ require 'n_1_finder/adapters/active_record_adapter'
91
+ require 'n_1_finder/adapters/sequel_adapter'
92
+ require 'n_1_finder/adapters/null_adapter'
93
+ require 'n_1_finder/errors/base'
94
+ require 'n_1_finder/errors/invalid_orm'
95
+ require 'n_1_finder/errors/invalid_logger'
@@ -1,46 +1,43 @@
1
1
  ##
2
- # Combine ORM adapters
2
+ # Adds common functionality to other adapters
3
3
  #
4
- module N1Finder::Adapters
5
- # Adds common functionality to other adapters
6
- class BaseAdapter
7
- # An alias that we create for MAIN_METHOD function
8
- MAIN_METHOD_ALIAS = :main_method_alias
4
+ class N1Finder::Adapters::BaseAdapter
5
+ # An alias that we create for MAIN_METHOD function
6
+ MAIN_METHOD_ALIAS = :main_method_alias
9
7
 
10
- # @!attribute [r] storage
11
- # Storage that stores queries
12
- attr_reader :storage
8
+ # @!attribute [r] storage
9
+ # Storage that stores queries
10
+ attr_reader :storage
13
11
 
14
- def initialize(storage)
15
- @storage = storage
16
- end
12
+ def initialize(storage)
13
+ @storage = storage
14
+ end
17
15
 
18
- # Replaces original query execution function (defined in MAIN_METHOD)
19
- # with our function that collects all queries and calls original function.
20
- # After passed block yileds, replaces our function with origianal and
21
- # removes our function.
22
- #
23
- # @yield passed block
24
- #
25
- # @return passed block execution result
26
- def exec
27
- set_trap
28
- yield
29
- ensure
30
- remove_trap
31
- end
16
+ # Replaces original query execution function (defined in MAIN_METHOD)
17
+ # with our function that collects all queries and calls original function.
18
+ # After passed block yileds, replaces our function with origianal and
19
+ # removes our function.
20
+ #
21
+ # @yield passed block
22
+ #
23
+ # @return passed block execution result
24
+ def exec
25
+ set_trap
26
+ yield
27
+ ensure
28
+ remove_trap
29
+ end
32
30
 
33
- private
31
+ private
34
32
 
35
- def remove_trap
36
- main_query_method = self.class::MAIN_METHOD
37
- main_method_alias = MAIN_METHOD_ALIAS
33
+ def remove_trap
34
+ main_query_method = self.class::MAIN_METHOD
35
+ main_method_alias = MAIN_METHOD_ALIAS
38
36
 
39
- database_class.class_eval do
40
- remove_method(main_query_method)
41
- alias_method main_query_method, main_method_alias
42
- remove_method(main_method_alias)
43
- end
37
+ database_class.class_eval do
38
+ remove_method(main_query_method)
39
+ alias_method main_query_method, main_method_alias
40
+ remove_method(main_method_alias)
44
41
  end
45
42
  end
46
43
  end
@@ -0,0 +1,16 @@
1
+ # Combine ORM adapters
2
+ module N1Finder::Adapters
3
+ # Adapters factory
4
+ class Factory
5
+ # Constructs new instance of adapter
6
+ def self.get(key, storage)
7
+ adapter_class = case key
8
+ when :active_record then N1Finder::Adapters::ActiveRecordAdapter
9
+ when :sequel then N1Finder::Adapters::SequelAdapter
10
+ else N1Finder::Adapters::NullAdapter
11
+ end
12
+
13
+ adapter_class.new(storage)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ # Errors module
2
+ # @api private
3
+ module N1Finder::Errors
4
+ # Base error class
5
+ class Base < StandardError
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ # Raised when specifying invalid logger
2
+ # @api private
3
+ class N1Finder::Errors::InvalidLogger < N1Finder::Errors::Base
4
+ end
@@ -0,0 +1,4 @@
1
+ # Raised when specifying invalid ORM
2
+ # @api private
3
+ class N1Finder::Errors::InvalidORM < N1Finder::Errors::Base
4
+ end
@@ -1,4 +1,4 @@
1
1
  class N1Finder
2
2
  # Gem version
3
- VERSION = '0.0.4'.freeze
3
+ VERSION = '0.0.5'.freeze
4
4
  end
@@ -0,0 +1,36 @@
1
+ RSpec.describe N1Finder::Adapters::Factory do
2
+ describe '.get' do
3
+ let(:storage) { 'STORAGE' }
4
+ subject { described_class.get(key, storage) }
5
+
6
+ context 'getting active_record' do
7
+ let(:key) { :active_record }
8
+ it 'returns active_record adapter' do
9
+ expect(subject).to be_a(N1Finder::Adapters::ActiveRecordAdapter)
10
+ end
11
+ it 'sets storage' do
12
+ expect(subject.storage).to eq storage
13
+ end
14
+ end
15
+
16
+ context 'getting sequel' do
17
+ let(:key) { :sequel }
18
+ it 'returns sequel adapter' do
19
+ expect(subject).to be_a(N1Finder::Adapters::SequelAdapter)
20
+ end
21
+ it 'sets storage' do
22
+ expect(subject.storage).to eq storage
23
+ end
24
+ end
25
+
26
+ context 'getting other adapter' do
27
+ let(:key) { :other }
28
+ it 'returns sequel adapter' do
29
+ expect(subject).to be_a(N1Finder::Adapters::NullAdapter)
30
+ end
31
+ it 'sets storage' do
32
+ expect(subject.storage).to eq storage
33
+ end
34
+ end
35
+ end
36
+ end
@@ -42,7 +42,7 @@ RSpec.describe N1Finder do
42
42
  context 'when logger is not a Logger' do
43
43
  let(:logger) { nil }
44
44
  it 'raises error' do
45
- expect { subject }.to raise_error described_class::InvalidLogger
45
+ expect { subject }.to raise_error described_class::Errors::InvalidLogger
46
46
  end
47
47
  end
48
48
  end
@@ -50,7 +50,7 @@ RSpec.describe N1Finder do
50
50
  describe '#orm=' do
51
51
  subject { described_class.orm = orm }
52
52
  context 'when provided supported orm' do
53
- let(:orm) { described_class::ORM_ADAPTERS.keys.sample }
53
+ let(:orm) { described_class::ORM_ADAPTERS.sample }
54
54
  it 'sets orm' do
55
55
  subject
56
56
  expect(described_class.orm).to eq orm
@@ -60,7 +60,7 @@ RSpec.describe N1Finder do
60
60
  context 'when orm is not supported' do
61
61
  let(:orm) { :mongo }
62
62
  it 'raises error' do
63
- expect { subject }.to raise_error N1Finder::InvalidORM
63
+ expect { subject }.to raise_error described_class::Errors::InvalidORM
64
64
  end
65
65
  end
66
66
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: n_1_finder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-29 00:00:00.000000000 Z
11
+ date: 2016-07-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Finds N+1 queries
14
14
  email: aglushkov@shakuro.com
@@ -20,8 +20,12 @@ files:
20
20
  - lib/n_1_finder.rb
21
21
  - lib/n_1_finder/adapters/active_record_adapter.rb
22
22
  - lib/n_1_finder/adapters/base_adapter.rb
23
+ - lib/n_1_finder/adapters/factory.rb
23
24
  - lib/n_1_finder/adapters/null_adapter.rb
24
25
  - lib/n_1_finder/adapters/sequel_adapter.rb
26
+ - lib/n_1_finder/errors/base.rb
27
+ - lib/n_1_finder/errors/invalid_logger.rb
28
+ - lib/n_1_finder/errors/invalid_orm.rb
25
29
  - lib/n_1_finder/logger.rb
26
30
  - lib/n_1_finder/middleware.rb
27
31
  - lib/n_1_finder/n_1_query.rb
@@ -30,6 +34,7 @@ files:
30
34
  - lib/n_1_finder/version.rb
31
35
  - spec/.env.example
32
36
  - spec/n_1_finder/adapters/active_record_adapter_spec.rb
37
+ - spec/n_1_finder/adapters/factory_spec.rb
33
38
  - spec/n_1_finder/adapters/null_adapter_spec.rb
34
39
  - spec/n_1_finder/adapters/sequel_adapter_spec.rb
35
40
  - spec/n_1_finder/features/active_record_mysql_spec.rb