json_api_preloader 0.0.2 → 0.0.3

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
  SHA256:
3
- metadata.gz: d725299c748475bda1ff7a33b4a9a8bda504b611fe9a8934c74194d431f0e9e3
4
- data.tar.gz: 8826dec180c6ccceecd7661b467385002fcfa91e40f419063e08a6b9ae57a7fb
3
+ metadata.gz: 66791aa33365826a3d35cc7ad50677dde7ff6c591eb2b44123d6d7a6ce973579
4
+ data.tar.gz: 5bc922c7755b35347f0748c1f983262d0d4f8a703bc7d63d92447e360c8649cb
5
5
  SHA512:
6
- metadata.gz: 637b8914db72bc81f99492b8392c3a3c6526b318779998d6060272c2c032c13702b50972dee14623d48f1e8c0a04b2dee991a0c69c0e1ff5ff440928dca90435
7
- data.tar.gz: 5ed82b42166084856533a9603f8eb66a583f5203ea8f8f437b3fb9faa418c60f981055f7a81dca0d7cc8838eac992b20c9c56c4e3b5025eaae6e7a9df2a4d253
6
+ metadata.gz: f00b0f5d6ae64afd1a35fd5c65c36493160fe8726a6250b96c339ffa4b6621d15d14ec350d368590a686ed5c08428c38368cf8ac1acd636522ea18404e7471f6
7
+ data.tar.gz: 8a08a81370abaa6bcc0ef101f747c3e9846779684655c95ee998a2161ace86b7c44ff56bae39a21759ce2090e8d23e42b85ae020ae37f7076b267fb8827c1b31
@@ -0,0 +1,34 @@
1
+ name: CI Workflow
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+
9
+ jobs:
10
+ ci-workflow:
11
+ name: CI Workflow
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout code
15
+ id: checkout-code
16
+ uses: actions/checkout@v2
17
+
18
+ - name: Setup ruby
19
+ id: setup-ruby
20
+ uses: actions/setup-ruby@v1
21
+ with:
22
+ ruby-version: 2.6
23
+
24
+ - name: Install gems
25
+ id: install-gems
26
+ run: make bundle
27
+
28
+ - name: Run linter
29
+ id: run-lint
30
+ run: make lint
31
+
32
+ - name: Run tests
33
+ id: run-tests
34
+ run: make test
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,9 +1,13 @@
1
1
  Style/Documentation:
2
2
  Enabled: false
3
3
 
4
- Layout/LineLength:
4
+ Metrics/LineLength:
5
5
  Max: 120
6
6
 
7
+ Metrics/BlockLength:
8
+ Exclude:
9
+ - 'spec/**/*'
10
+
7
11
  Naming/VariableNumber:
8
12
  EnforcedStyle: snake_case
9
13
 
data/Gemfile CHANGED
@@ -2,4 +2,7 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
+ gem 'activesupport'
6
+ gem 'byebug'
7
+ gem 'rspec'
5
8
  gem 'rubocop'
data/Gemfile.lock CHANGED
@@ -1,12 +1,37 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ activesupport (6.0.1)
5
+ concurrent-ruby (~> 1.0, >= 1.0.2)
6
+ i18n (>= 0.7, < 2)
7
+ minitest (~> 5.1)
8
+ tzinfo (~> 1.1)
9
+ zeitwerk (~> 2.2)
4
10
  ast (2.4.0)
11
+ byebug (11.1.1)
12
+ concurrent-ruby (1.1.5)
13
+ diff-lcs (1.3)
14
+ i18n (1.7.0)
15
+ concurrent-ruby (~> 1.0)
5
16
  jaro_winkler (1.5.3)
17
+ minitest (5.13.0)
6
18
  parallel (1.18.0)
7
19
  parser (2.6.5.0)
8
20
  ast (~> 2.4.0)
9
21
  rainbow (3.0.0)
22
+ rspec (3.8.0)
23
+ rspec-core (~> 3.8.0)
24
+ rspec-expectations (~> 3.8.0)
25
+ rspec-mocks (~> 3.8.0)
26
+ rspec-core (3.8.2)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-expectations (3.8.4)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.8.0)
31
+ rspec-mocks (3.8.1)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.8.0)
34
+ rspec-support (3.8.2)
10
35
  rubocop (0.75.0)
11
36
  jaro_winkler (~> 1.5.1)
12
37
  parallel (~> 1.10)
@@ -15,12 +40,19 @@ GEM
15
40
  ruby-progressbar (~> 1.7)
16
41
  unicode-display_width (>= 1.4.0, < 1.7)
17
42
  ruby-progressbar (1.10.1)
43
+ thread_safe (0.3.6)
44
+ tzinfo (1.2.5)
45
+ thread_safe (~> 0.1)
18
46
  unicode-display_width (1.6.0)
47
+ zeitwerk (2.2.1)
19
48
 
20
49
  PLATFORMS
21
50
  ruby
22
51
 
23
52
  DEPENDENCIES
53
+ activesupport
54
+ byebug
55
+ rspec
24
56
  rubocop
25
57
 
26
58
  BUNDLED WITH
data/Makefile ADDED
@@ -0,0 +1,12 @@
1
+ usage:
2
+ @echo "Available targets:"
3
+ @echo " * lint - Runs rubocop"
4
+ @echo " * test - Runs tests"
5
+ @echo " * bundle - Installs gems"
6
+
7
+ lint: ## Runs rubocop
8
+ bundle exec rubocop
9
+ test: ## Runs tests
10
+ bundle exec rspec
11
+ bundle: ## Runs tests
12
+ bundle install
data/Readme.md ADDED
@@ -0,0 +1,102 @@
1
+
2
+ # JsonApiPreloader
3
+
4
+ ![CI Workflow](https://github.com/koryushka/json_api_preloader/workflows/CI%20Workflow/badge.svg)
5
+ [![Gem Version](https://badge.fury.io/rb/json_api_preloader.svg)](https://badge.fury.io/rb/json_api_preloader)
6
+
7
+ JsonApiPreloader helps to preload associations based on query `include` parameter in order to avoid N+1 query.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'json_api_preloader'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install json_api_preloader
24
+
25
+ ## Usage
26
+
27
+ Let's say you have models:
28
+
29
+ ```ruby
30
+ class User < ApplicationRecord
31
+ has_many :posts
32
+ end
33
+
34
+ class Post < ApplicationRecord
35
+ belongs_to :user
36
+ has_many :comments
37
+ has_many :images
38
+ end
39
+
40
+ class Image < ApplicationRecord
41
+ belongs_to :post
42
+ end
43
+
44
+ class Comment < ApplicationRecord
45
+ belongs_to :post
46
+ end
47
+ ```
48
+
49
+ And you're querying `index` action of `users_controller` as following:
50
+
51
+ `GET /users?include=posts.images,posts.comments`
52
+
53
+ ```ruby
54
+ class UsersController < ApplicationController
55
+ include JsonApiPreloader::Core
56
+ setup_query_builder
57
+
58
+ def index
59
+ users = User.includes(preloaded)
60
+ # preloaded will be `{ posts: { images: {}, comments: {} } }`
61
+ end
62
+ end
63
+ ```
64
+
65
+ You can specify parent model per action:
66
+
67
+ ```ruby
68
+ setup_query_builder "SomeModel", action: :custom_action
69
+ ```
70
+
71
+ or with unexistent association:
72
+
73
+ `GET /users?include=posts.images,posts.comments,posts.unexistent,unexistent`
74
+
75
+ ```ruby
76
+ class UsersController < ApplicationController
77
+ include JsonApiPreloader::Core
78
+ setup_query_builder
79
+
80
+ def index
81
+ users = User.includes(preloaded)
82
+ # By default `preloaded` will be `{ posts: { images: {}, comments: {} } }`.
83
+ # If `check_associations` is set to `false` `preloaded` will be:
84
+ # { posts: { images: {}, comments: {}, unexistent: {} }, unexistent: {} }
85
+ # this might help client to understand the usage of endpoint, because error will be returned.
86
+ end
87
+ end
88
+ ```
89
+
90
+
91
+ You can configure JsonApiPreloader:
92
+
93
+ ```ruby
94
+ # config/initializers/json_api_preloader.rb
95
+ JsonApiPreloader.configure do |config|
96
+ # By default `check_associations` is set to true, which means that nonexistent
97
+ # associations will be ignored and trimmed.
98
+ config.check_associations = true
99
+ # Set your models` folder, by default it's `./app/models/**/*.rb`
100
+ config.models_folder = './app/models/**/*.rb'
101
+ end
102
+ ```
@@ -1,12 +1,18 @@
1
1
  # frozen_string_literal: true
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'json_api_preloader/version'
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = 'json_api_preloader'
5
- s.version = '0.0.2'
8
+ s.version = JsonApiPreloader::VERSION
6
9
  s.authors = ['Kiryl Karetnikau']
7
10
  s.license = 'MIT'
8
11
  s.email = 'kiryl.karetnikau@gmail.com'
9
12
  s.homepage = 'https://github.com/koryushka/json_api_preloader'
10
13
  s.summary = 'Preloads associations based on request param `included`'
11
14
  s.files = `git ls-files -z`.split("\x0")
15
+
16
+ s.add_development_dependency 'rspec', '~> 3.9.0'
17
+ s.add_dependency 'activesupport', '~> 5.0', '>= 5.0.0.1'
12
18
  end
@@ -2,14 +2,23 @@
2
2
 
3
3
  module JsonApiPreloader
4
4
  class AssociationsBuilder
5
- delegate :models, to: ModelsPreloader
5
+ class << self
6
+ def associations
7
+ @associations ||= ModelsPreloader.models.map do |model_name|
8
+ {
9
+ associations: associations_for(model_name),
10
+ name: model_name
11
+ }
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def associations_for(model_name)
18
+ model = model_name.safe_constantize
19
+ return [] unless model
6
20
 
7
- def call
8
- models.map do |model_name|
9
- {
10
- associations: model_name.constantize.reflect_on_all_associations.map { |ac| { ac.name => ac.klass.name } },
11
- name: model_name
12
- }
21
+ model.reflect_on_all_associations.map { |ac| { ac.name => ac.klass.name } }
13
22
  end
14
23
  end
15
24
  end
@@ -14,7 +14,7 @@ module JsonApiPreloader
14
14
  end
15
15
 
16
16
  def self.associations
17
- @associations ||= AssociationsBuilder.new.call
17
+ @associations ||= AssociationsBuilder.associations
18
18
  end
19
19
 
20
20
  private
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonApiPreloader
4
+ class Configuration
5
+ DEFAULT_CONFIG_OPTIONS = {
6
+ check_associations: true,
7
+ models_folder: './app/models/**/*.rb'
8
+ }.freeze
9
+
10
+ DEFAULT_CONFIG_OPTIONS.each do |option, value|
11
+ define_method(option) do
12
+ options[option].nil? ? value : options[option]
13
+ end
14
+
15
+ define_method("#{option}=") do |val|
16
+ options[option] = val
17
+ end
18
+ end
19
+
20
+ def initialize
21
+ @options = {}
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :options
27
+ end
28
+ end
@@ -1,28 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext'
3
4
  module JsonApiPreloader
4
5
  module Core
5
- extend ActiveSupport::Concern
6
-
7
- class_methods do
8
- def preload_from_params_for(model_name)
9
- class_attribute :preloader_configuration
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ base.class_attribute(:builder_configuration)
9
+ end
10
+ module ClassMethods
11
+ def setup_query_builder(model_name = nil, action: nil)
12
+ self.builder_configuration ||= []
10
13
 
11
- self.preloader_configuration = {
12
- name: model_name.constantize.name
14
+ self.builder_configuration << {
15
+ model_name: model_name ? model_name.constantize.name : based_on_controller_name,
16
+ action: action&.to_sym || :index
13
17
  }
14
18
  end
19
+
20
+ def based_on_controller_name
21
+ name.demodulize.gsub('Controller', '').singularize.constantize.name
22
+ end
15
23
  end
16
24
 
17
25
  private
18
26
 
19
- def preloaded
27
+ def preloaded_query
20
28
  included = params[:include]
21
- return {} unless included.presence
29
+ return {} if included.nil? || included.empty?
22
30
 
23
31
  nested_resources(
24
32
  included: included.split(','),
25
- parent: preloader_configuration[:name]
33
+ parent: parent_model
26
34
  )
27
35
  end
28
36
 
@@ -30,8 +38,10 @@ module JsonApiPreloader
30
38
  association = ary.shift
31
39
  return unless association
32
40
 
33
- new_parent = AssociationsChecker.new(parent, association).call
34
- return unless new_parent
41
+ if parent
42
+ new_parent = AssociationsChecker.new(parent, association).call
43
+ return unless new_parent
44
+ end
35
45
 
36
46
  modify_params(hsh[association], ary, new_parent)
37
47
  end
@@ -44,5 +54,18 @@ module JsonApiPreloader
44
54
  end
45
55
  result
46
56
  end
57
+
58
+ def preload_models?
59
+ @preload_models ||= ModelsPreloadChecker.preload_models?
60
+ end
61
+
62
+ def parent_model
63
+ return unless preload_models?
64
+
65
+ config = builder_configuration.detect { |conf| conf[:action] == action_name.to_sym }
66
+ return unless config
67
+
68
+ config[:model_name]
69
+ end
47
70
  end
48
71
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonApiPreloader
4
+ class ModelsPreloadChecker
5
+ class << self
6
+ def preload_models?
7
+ @preload_models ||= preload_possible? && preload_required?
8
+ end
9
+
10
+ private
11
+
12
+ def preload_possible?
13
+ defined?(ActiveRecord)
14
+ end
15
+
16
+ def preload_required?
17
+ JsonApiPreloader.configuration.check_associations
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,7 +5,7 @@ module JsonApiPreloader
5
5
  class << self
6
6
  def models
7
7
  @models ||= begin
8
- load_models! unless eager_loaded?
8
+ load_models! if load_required?
9
9
 
10
10
  model_names
11
11
  end
@@ -13,16 +13,22 @@ module JsonApiPreloader
13
13
 
14
14
  private
15
15
 
16
- def eager_loaded?
17
- Rails.application.config.eager_load
16
+ def load_required?
17
+ return !Rails.application.config.eager_load if defined?(Rails)
18
+
19
+ true
18
20
  end
19
21
 
20
22
  def load_models!
21
- Dir[Rails.root.join('app/models/**/*.rb')].sort.each { |f| require f }
23
+ Dir[models_folder].each { |f| require f }
24
+ end
25
+
26
+ def models_folder
27
+ JsonApiPreloader.configuration.models_folder
22
28
  end
23
29
 
24
30
  def model_names
25
- ApplicationRecord.descendants.collect(&:name)
31
+ ActiveRecord::Base.descendants.collect(&:name)
26
32
  end
27
33
  end
28
34
  end
@@ -0,0 +1,3 @@
1
+ module JsonApiPreloader
2
+ VERSION = '0.0.3'
3
+ end
@@ -2,5 +2,20 @@
2
2
 
3
3
  require 'json_api_preloader/core'
4
4
  require 'json_api_preloader/models_preloader'
5
+ require 'json_api_preloader/models_preload_checker'
5
6
  require 'json_api_preloader/associations_checker'
6
7
  require 'json_api_preloader/associations_builder'
8
+ require 'json_api_preloader/configuration'
9
+ require 'json_api_preloader/version'
10
+
11
+ module JsonApiPreloader
12
+ class << self
13
+ def configure(&block)
14
+ block.call(configuration)
15
+ end
16
+
17
+ def configuration
18
+ @configuration ||= Configuration.new
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'byebug'
4
+ RSpec.describe JsonApiPreloader::Core do
5
+ describe '.preloaded_query' do
6
+ let(:object) { Object.new }
7
+ before do
8
+ def object.controller_name
9
+ 'some_name'
10
+ end
11
+
12
+ object.extend(described_class)
13
+ end
14
+
15
+ context 'when models are not preloaded' do
16
+ before { allow(JsonApiPreloader::ModelsPreloadChecker).to receive(:preload_models?).and_return(false) }
17
+
18
+ context 'when `include` key is provided' do
19
+ before do
20
+ def object.params
21
+ { include: 'collection_to_include' }
22
+ end
23
+ end
24
+
25
+ it 'returns proper object' do
26
+ expect(object.send(:preloaded_query)).to eq(collection_to_include: {})
27
+ end
28
+ end
29
+
30
+ context 'when `include` is nil' do
31
+ before do
32
+ def object.params
33
+ { include: nil }
34
+ end
35
+ end
36
+ it 'returns proper object' do
37
+ expect(object.send(:preloaded_query)).to eq({})
38
+ end
39
+ end
40
+
41
+ context 'when `include` is empty string' do
42
+ before do
43
+ def object.params
44
+ { include: '' }
45
+ end
46
+ end
47
+ it 'returns proper object' do
48
+ expect(object.send(:preloaded_query)).to eq({})
49
+ end
50
+ end
51
+
52
+ context 'when `include` absents' do
53
+ before do
54
+ def object.params
55
+ {}
56
+ end
57
+ end
58
+ it 'returns proper object' do
59
+ expect(object.send(:preloaded_query)).to eq({})
60
+ end
61
+ end
62
+
63
+ context 'one level of nesting' do
64
+ before do
65
+ def object.params
66
+ { include: 'collection,second_collection,third_collection' }
67
+ end
68
+ end
69
+ it 'returns proper object' do
70
+ expect(object.send(:preloaded_query)).to eq(collection: {}, second_collection: {}, third_collection: {})
71
+ end
72
+ end
73
+
74
+ context 'two levels of nesting' do
75
+ before do
76
+ def object.params
77
+ {
78
+ include: 'first_level,first_level_2.second_level,first_level_2.second_level_2,first_level_3.second_level'
79
+ }
80
+ end
81
+ end
82
+
83
+ it 'returns proper object' do
84
+ expect(object.send(:preloaded_query))
85
+ .to eq(
86
+ first_level_2: { second_level: {}, second_level_2: {} }, first_level_3: { second_level: {} },
87
+ first_level: {}
88
+ )
89
+ end
90
+ end
91
+
92
+ context 'three levels of nesting' do
93
+ before do
94
+ def object.params
95
+ {
96
+ include: 'first_level,first_level_2,first_level_3,first_level_4.second_level,'\
97
+ 'first_level_4.second_level_2.third_level'
98
+ }
99
+ end
100
+ end
101
+
102
+ it 'returns proper object' do
103
+ expect(object.send(:preloaded_query))
104
+ .to eq(
105
+ first_level: {}, first_level_4: { second_level: {}, second_level_2: { third_level: {} } },
106
+ first_level_2: {}, first_level_3: {}
107
+ )
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#setup_query_builder' do
114
+ before { Object.include(described_class) }
115
+
116
+ context 'single setup per class' do
117
+ subject { Object.setup_query_builder(model_name, action: action) }
118
+
119
+ context 'when model name and action are nil' do
120
+ let(:model_name) { nil }
121
+ let(:action) { nil }
122
+
123
+ it { is_expected.to eq([{ model_name: 'Object', action: :index }]) }
124
+ end
125
+
126
+ context 'when model is set' do
127
+ before do
128
+ class TestModel; end
129
+ end
130
+ let(:model_name) { 'TestModel' }
131
+ let(:action) { nil }
132
+
133
+ it { is_expected.to eq([{ model_name: 'TestModel', action: :index }]) }
134
+ end
135
+
136
+ context 'when action is set' do
137
+ let(:model_name) { nil }
138
+ let(:action) { :custom_action }
139
+
140
+ it { is_expected.to eq([{ model_name: 'Object', action: :custom_action }]) }
141
+ end
142
+
143
+ context 'when model and action are set' do
144
+ before do
145
+ class TestModel; end
146
+ end
147
+ let(:model_name) { 'TestModel' }
148
+ let(:action) { :custom_action }
149
+
150
+ it { is_expected.to eq([{ model_name: 'TestModel', action: :custom_action }]) }
151
+ end
152
+
153
+ context 'when model does not exist' do
154
+ let(:model_name) { 'UnexistentModel' }
155
+ let(:action) { :custom_action }
156
+
157
+ it 'raises error' do
158
+ expect { subject }.to raise_error(NameError, "uninitialized constant #{model_name}")
159
+ end
160
+ end
161
+ end
162
+
163
+ context 'multiple setups per class' do
164
+ subject do
165
+ Object.setup_query_builder(model_name, action: action)
166
+ Object.setup_query_builder(model_name_2, action: action_2)
167
+ end
168
+
169
+ context 'when model name and action are set' do
170
+ before do
171
+ class TestModel end
172
+ class TestModel2 end
173
+ end
174
+
175
+ let(:model_name) { 'TestModel' }
176
+ let(:action) { :custom_action }
177
+ let(:model_name_2) { 'TestModel2' }
178
+ let(:action_2) { :custom_action_2 }
179
+
180
+ expected_setup = [
181
+ { model_name: 'TestModel', action: :custom_action },
182
+ { model_name: 'TestModel2', action: :custom_action_2 }
183
+ ]
184
+ it { is_expected.to match_array(expected_setup) }
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
6
+ # this file to always be loaded, without a need to explicitly require it in any
7
+ # files.
8
+ #
9
+ # Given that it is always loaded, you are encouraged to keep this file as
10
+ # light-weight as possible. Requiring heavyweight dependencies from this file
11
+ # will add to the boot time of your test suite on EVERY test run, even for an
12
+ # individual file that may not need all of that loaded. Instead, consider making
13
+ # a separate helper file that requires the additional dependencies and performs
14
+ # the additional setup, and require it from the spec files that actually need
15
+ # it.
16
+ #
17
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
18
+ require 'json_api_preloader'
19
+ Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
20
+
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
46
+ # have no way to turn it off -- the option exists only for backwards
47
+ # compatibility in RSpec 3). It causes shared context metadata to be
48
+ # inherited by the metadata hash of host groups and examples, rather than
49
+ # triggering implicit auto-inclusion in groups with matching metadata.
50
+ config.shared_context_metadata_behavior = :apply_to_host_groups
51
+
52
+ # The settings below are suggested to provide a good initial experience
53
+ # with RSpec, but feel free to customize to your heart's content.
54
+ # # This allows you to limit a spec run to individual examples or groups
55
+ # # you care about by tagging them with `:focus` metadata. When nothing
56
+ # # is tagged with `:focus`, all examples get run. RSpec also provides
57
+ # # aliases for `it`, `describe`, and `context` that include `:focus`
58
+ # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
59
+ # config.filter_run_when_matching :focus
60
+ #
61
+ # # Allows RSpec to persist some state between runs in order to support
62
+ # # the `--only-failures` and `--next-failure` CLI options. We recommend
63
+ # # you configure your source control system to ignore this file.
64
+ # config.example_status_persistence_file_path = "spec/examples.txt"
65
+ #
66
+ # # Limits the available syntax to the non-monkey patched syntax that is
67
+ # # recommended. For more details, see:
68
+ # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
69
+ # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
70
+ # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
71
+ # config.disable_monkey_patching!
72
+ #
73
+ # # This setting enables warnings. It's recommended, but in some cases may
74
+ # # be too noisy due to issues in dependencies.
75
+ # config.warnings = true
76
+ #
77
+ # # Many RSpec users commonly either run the entire suite or an individual
78
+ # # file, and it's useful to allow more verbose output when running an
79
+ # # individual spec file.
80
+ # if config.files_to_run.one?
81
+ # # Use the documentation formatter for detailed output,
82
+ # # unless a formatter has already been configured
83
+ # # (e.g. via a command-line flag).
84
+ # config.default_formatter = "doc"
85
+ # end
86
+ #
87
+ # # Print the 10 slowest examples and example groups at the
88
+ # # end of the spec run, to help surface which specs are running
89
+ # # particularly slow.
90
+ # config.profile_examples = 10
91
+ #
92
+ # # Run specs in random order to surface order dependencies. If you find an
93
+ # # order dependency and want to debug it, you can fix the order by providing
94
+ # # the seed, which is printed after each run.
95
+ # # --seed 1234
96
+ # config.order = :random
97
+ #
98
+ # # Seed global randomization in this process using the `--seed` CLI option.
99
+ # # Setting this allows you to use `--seed` to deterministically reproduce
100
+ # # test failures related to randomization by passing the same `--seed` value
101
+ # # as the one that triggered the failure.
102
+ # Kernel.srand config.seed
103
+ end
metadata CHANGED
@@ -1,30 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_api_preloader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kiryl Karetnikau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-03 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 3.9.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 5.0.0.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '5.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 5.0.0.1
13
47
  description:
14
48
  email: kiryl.karetnikau@gmail.com
15
49
  executables: []
16
50
  extensions: []
17
51
  extra_rdoc_files: []
18
52
  files:
53
+ - ".github/workflows/ci.yml"
54
+ - ".gitignore"
55
+ - ".rspec"
19
56
  - ".rubocop.yml"
20
57
  - Gemfile
21
58
  - Gemfile.lock
59
+ - Makefile
60
+ - Readme.md
22
61
  - json_api_preloader.gemspec
23
62
  - lib/json_api_preloader.rb
24
63
  - lib/json_api_preloader/associations_builder.rb
25
64
  - lib/json_api_preloader/associations_checker.rb
65
+ - lib/json_api_preloader/configuration.rb
26
66
  - lib/json_api_preloader/core.rb
67
+ - lib/json_api_preloader/models_preload_checker.rb
27
68
  - lib/json_api_preloader/models_preloader.rb
69
+ - lib/json_api_preloader/version.rb
70
+ - spec/json_api_preloader/core_spec.rb
71
+ - spec/spec_helper.rb
28
72
  homepage: https://github.com/koryushka/json_api_preloader
29
73
  licenses:
30
74
  - MIT