json_api_preloader 0.0.2 → 0.0.3

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