azeroth 1.0.0 → 2.0.0

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +3 -3
  3. data/.rubocop.yml +15 -1
  4. data/Dockerfile +2 -2
  5. data/Gemfile +30 -0
  6. data/Makefile +6 -0
  7. data/README.md +13 -1
  8. data/azeroth.gemspec +6 -36
  9. data/config/check_specs.yml +1 -0
  10. data/lib/azeroth/controller_interface.rb +3 -2
  11. data/lib/azeroth/decorator/class_methods.rb +249 -0
  12. data/lib/azeroth/decorator/hash_builder.rb +1 -0
  13. data/lib/azeroth/decorator/method_builder.rb +23 -7
  14. data/lib/azeroth/decorator/options.rb +3 -1
  15. data/lib/azeroth/decorator.rb +35 -192
  16. data/lib/azeroth/model.rb +1 -0
  17. data/lib/azeroth/request_handler/index.rb +7 -33
  18. data/lib/azeroth/request_handler/pagination.rb +53 -0
  19. data/lib/azeroth/request_handler.rb +11 -9
  20. data/lib/azeroth/resourceable/builder.rb +3 -2
  21. data/lib/azeroth/version.rb +1 -1
  22. data/spec/dummy/app/models/website/decorator.rb +11 -0
  23. data/spec/dummy/app/models/website/with_location.rb +21 -0
  24. data/spec/dummy/app/models/website.rb +4 -0
  25. data/spec/dummy/config/environments/production.rb +2 -2
  26. data/spec/dummy/config/puma.rb +3 -3
  27. data/spec/dummy/db/schema.rb +6 -0
  28. data/spec/integration/readme/controllers/games_controller_spec.rb +1 -1
  29. data/spec/integration/yard/azeroth/decorator_spec.rb +15 -0
  30. data/spec/integration/yard/controllers/games_controller_spec.rb +1 -1
  31. data/spec/integration/yard/controllers/paginated_documents_controller_spec.rb +1 -1
  32. data/spec/lib/azeroth/controller_interface_spec.rb +1 -1
  33. data/spec/lib/azeroth/decorator/method_builder_spec.rb +61 -2
  34. data/spec/lib/azeroth/decorator_spec.rb +96 -5
  35. data/spec/lib/azeroth/request_handler/pagination_spec.rb +133 -0
  36. data/spec/lib/azeroth/request_handler/update_spec.rb +1 -1
  37. data/spec/spec_helper.rb +1 -1
  38. data/spec/support/app/controllers/controller.rb +1 -0
  39. data/spec/support/matchers/add_method.rb +6 -4
  40. data/spec/support/shared_examples/request_handler.rb +1 -5
  41. metadata +17 -569
@@ -3,21 +3,80 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Azeroth::Decorator::MethodBuilder do
6
+ subject(:build_reader) do
7
+ described_class.build_reader(decorator_class, :age, options)
8
+ end
9
+
6
10
  let(:decorator_class) { Class.new(Azeroth::Decorator) }
7
11
  let(:decorator) { decorator_class.new(object) }
8
12
  let(:model) { build(:dummy_model) }
9
13
  let(:object) { model }
14
+ let(:options) { Azeroth::Decorator::Options.new(options_hash) }
15
+ let(:options_hash) { {} }
10
16
 
11
17
  describe '.build_reader' do
12
18
  it do
13
- expect { described_class.build_reader(decorator_class, :age) }
19
+ expect { build_reader }
14
20
  .to add_method(:age).to(decorator)
15
21
  end
16
22
 
17
23
  it do
18
- described_class.build_reader(decorator_class, :age)
24
+ build_reader
19
25
 
20
26
  expect(decorator.age).to eq(model.age)
21
27
  end
28
+
29
+ context 'when passing reader option' do
30
+ context 'when passing true' do
31
+ let(:options_hash) { { reader: true } }
32
+
33
+ it do
34
+ expect { build_reader }
35
+ .to add_method(:age).to(decorator)
36
+ end
37
+ end
38
+
39
+ context 'when passing false' do
40
+ let(:options_hash) { { reader: false } }
41
+
42
+ it do
43
+ expect { build_reader }
44
+ .not_to add_method(:age).to(decorator)
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'when passing override option as true' do
50
+ let(:options_hash) { { override: false } }
51
+
52
+ it do
53
+ expect { build_reader }
54
+ .to add_method(:age).to(decorator)
55
+ end
56
+ end
57
+
58
+ context 'when method already existed' do
59
+ before do
60
+ decorator_class.define_method(:age) { 1 }
61
+ end
62
+
63
+ context 'when passing override option as true' do
64
+ let(:options_hash) { { override: true } }
65
+
66
+ it do
67
+ expect { build_reader }
68
+ .to change_method(:age).on(decorator)
69
+ end
70
+ end
71
+
72
+ context 'when passing override option as false' do
73
+ let(:options_hash) { { override: false } }
74
+
75
+ it do
76
+ expect { build_reader }
77
+ .not_to change_method(:age).on(decorator)
78
+ end
79
+ end
80
+ end
22
81
  end
23
82
  end
@@ -5,14 +5,16 @@ require 'spec_helper'
5
5
  describe Azeroth::Decorator do
6
6
  subject(:decorator) { DummyModel::Decorator.new(object) }
7
7
 
8
- let(:model) { build(:dummy_model) }
9
- let(:object) { model }
8
+ let(:model) { build(:dummy_model) }
9
+ let(:object) { model }
10
+ let(:instance) { decorator.new(object) }
10
11
 
11
12
  describe '.expose' do
12
13
  subject(:decorator) { Class.new(described_class) }
13
14
 
15
+ let(:options_hash) { {} }
14
16
  let(:expected_options) do
15
- Azeroth::Decorator::Options.new
17
+ Azeroth::Decorator::Options.new(options_hash)
16
18
  end
17
19
 
18
20
  it do
@@ -59,6 +61,97 @@ describe Azeroth::Decorator do
59
61
  .and raise_error(Sinclair::Exception::InvalidOptions)
60
62
  end
61
63
  end
64
+
65
+ context 'when decorator already has the method' do
66
+ before do
67
+ decorator.define_method(:name) do
68
+ 'some name'
69
+ end
70
+ end
71
+
72
+ context 'when not passing override' do
73
+ it do
74
+ expect { decorator.send(:expose, :name) }
75
+ .to change(decorator, :attributes_map)
76
+ .from({})
77
+ .to({ name: expected_options })
78
+ end
79
+
80
+ it do
81
+ expect { decorator.send(:expose, :name) }
82
+ .to change_method(:name)
83
+ .on(instance)
84
+ end
85
+ end
86
+
87
+ context 'when passing override as true' do
88
+ let(:options_hash) { { override: true } }
89
+
90
+ it do
91
+ expect { decorator.send(:expose, :name, **options_hash) }
92
+ .to change(decorator, :attributes_map)
93
+ .from({})
94
+ .to({ name: expected_options })
95
+ end
96
+
97
+ it do
98
+ expect { decorator.send(:expose, :name, **options_hash) }
99
+ .to change_method(:name)
100
+ .on(instance)
101
+ end
102
+ end
103
+
104
+ context 'when passing override as false' do
105
+ let(:options_hash) { { override: false } }
106
+
107
+ it do
108
+ expect { decorator.send(:expose, :name, **options_hash) }
109
+ .to change(decorator, :attributes_map)
110
+ .from({})
111
+ .to({ name: expected_options })
112
+ end
113
+
114
+ it do
115
+ expect { decorator.send(:expose, :name, **options_hash) }
116
+ .not_to change_method(:name)
117
+ .on(instance)
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'when passing reader option' do
123
+ context 'when option is true' do
124
+ let(:options_hash) { { reader: true } }
125
+
126
+ it do
127
+ expect { decorator.send(:expose, :name, **options_hash) }
128
+ .to change(decorator, :attributes_map)
129
+ .from({})
130
+ .to({ name: expected_options })
131
+ end
132
+
133
+ it do
134
+ expect { decorator.send(:expose, :name, **options_hash) }
135
+ .to add_method(:name).to(decorator)
136
+ end
137
+ end
138
+
139
+ context 'when option is false' do
140
+ let(:options_hash) { { reader: false } }
141
+
142
+ it do
143
+ expect { decorator.send(:expose, :name, **options_hash) }
144
+ .to change(decorator, :attributes_map)
145
+ .from({})
146
+ .to({ name: expected_options })
147
+ end
148
+
149
+ it do
150
+ expect { decorator.send(:expose, :name, **options_hash) }
151
+ .not_to add_method(:name).to(decorator)
152
+ end
153
+ end
154
+ end
62
155
  end
63
156
 
64
157
  describe '#as_json' do
@@ -323,12 +416,10 @@ describe Azeroth::Decorator do
323
416
  end
324
417
 
325
418
  context 'when method is private and passing include_private' do
326
- # rubocop:disable RSpec/PredicateMatcher
327
419
  it do
328
420
  expect(decorator.respond_to?(:private_name, true))
329
421
  .to be_truthy
330
422
  end
331
- # rubocop:enable RSpec/PredicateMatcher
332
423
  end
333
424
 
334
425
  context 'when object does not respond to it' do
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Azeroth::RequestHandler::Pagination do
6
+ subject(:pagination) { described_class.new(params, options) }
7
+
8
+ let(:options) { Azeroth::Options.new(options_hash) }
9
+ let(:options_hash) { {} }
10
+ let(:params) { ActionController::Parameters.new(parameters) }
11
+ let(:parameters) { {} }
12
+
13
+ describe '#offset' do
14
+ context 'when nothing was defined' do
15
+ it do
16
+ expect(pagination.offset).to be_zero
17
+ end
18
+ end
19
+
20
+ context 'when parameters has page value' do
21
+ let(:parameters) { { page: page } }
22
+ let(:page) { Random.rand(1..10) }
23
+ let(:expected_offset) { (page - 1) * expected_per_page }
24
+ let(:expected_per_page) { 20 }
25
+
26
+ it 'returns value from request using default per_page' do
27
+ expect(pagination.offset).to eq(expected_offset)
28
+ end
29
+ end
30
+
31
+ context 'when parameters has per_page value' do
32
+ let(:parameters) { { per_page: per_page } }
33
+ let(:per_page) { Random.rand(1..10) }
34
+
35
+ it do
36
+ expect(pagination.offset).to be_zero
37
+ end
38
+ end
39
+
40
+ context 'when parameters has page and per page values' do
41
+ let(:parameters) { { page: page, per_page: per_page } }
42
+ let(:page) { Random.rand(1..10) }
43
+ let(:per_page) { Random.rand(1..10) }
44
+ let(:expected_offset) { (page - 1) * expected_per_page }
45
+ let(:expected_per_page) { per_page }
46
+
47
+ it 'returns value from request' do
48
+ expect(pagination.offset).to eq(expected_offset)
49
+ end
50
+ end
51
+
52
+ context 'when parameters has page and options per page values' do
53
+ let(:parameters) { { page: page } }
54
+ let(:options_hash) { { per_page: per_page } }
55
+ let(:page) { Random.rand(1..10) }
56
+ let(:per_page) { Random.rand(1..10) }
57
+ let(:expected_offset) { (page - 1) * expected_per_page }
58
+ let(:expected_per_page) { per_page }
59
+
60
+ it 'returns value from request and options' do
61
+ expect(pagination.offset).to eq(expected_offset)
62
+ end
63
+ end
64
+
65
+ context 'when params has page and per_page and options per page values' do
66
+ let(:parameters) { { page: page, per_page: per_page } }
67
+ let(:options_hash) { { per_page: options_per_page } }
68
+ let(:page) { Random.rand(1..10) }
69
+ let(:options_per_page) { Random.rand(1..10) }
70
+ let(:per_page) { Random.rand(1..10) }
71
+ let(:expected_offset) { (page - 1) * expected_per_page }
72
+ let(:expected_per_page) { per_page }
73
+
74
+ it 'returns value from request' do
75
+ expect(pagination.offset).to eq(expected_offset)
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#limit' do
81
+ context 'when nothing was defined' do
82
+ it 'returns default value' do
83
+ expect(pagination.limit).to eq(20)
84
+ end
85
+ end
86
+
87
+ context 'when parameters has per_page' do
88
+ let(:parameters) { { per_page: per_page } }
89
+ let(:per_page) { Random.rand(1..10) }
90
+
91
+ it 'returns value from request' do
92
+ expect(pagination.limit).to eq(per_page)
93
+ end
94
+ end
95
+
96
+ context 'when options has per_page' do
97
+ let(:options_hash) { { per_page: per_page } }
98
+ let(:per_page) { Random.rand(1..10) }
99
+
100
+ it 'returns value from options' do
101
+ expect(pagination.limit).to eq(per_page)
102
+ end
103
+ end
104
+
105
+ context 'when params and options have per_page' do
106
+ let(:parameters) { { per_page: per_page } }
107
+ let(:per_page) { Random.rand(1..10) }
108
+ let(:options_hash) { { per_page: options_per_page } }
109
+ let(:options_per_page) { Random.rand(1..10) }
110
+
111
+ it 'returns value from request' do
112
+ expect(pagination.limit).to eq(per_page)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe '#current_page' do
118
+ context 'when nothing was defined' do
119
+ it 'returns first page' do
120
+ expect(pagination.current_page).to eq(1)
121
+ end
122
+ end
123
+
124
+ context 'when parameters has page' do
125
+ let(:parameters) { { page: page } }
126
+ let(:page) { Random.rand(1..10) }
127
+
128
+ it 'returns value from request' do
129
+ expect(pagination.current_page).to eq(page)
130
+ end
131
+ end
132
+ end
133
+ end
@@ -30,7 +30,7 @@ describe Azeroth::RequestHandler::Update do
30
30
  end
31
31
  end
32
32
 
33
- context 'when update_with option is given ' do
33
+ context 'when update_with option is given' do
34
34
  context 'with block' do
35
35
  it_behaves_like 'a request handler' do
36
36
  let(:block) do
data/spec/spec_helper.rb CHANGED
@@ -22,7 +22,7 @@ require 'shoulda-matchers'
22
22
  require 'rspec/collection_matchers'
23
23
 
24
24
  support_files = File.expand_path('spec/support/**/*.rb')
25
- Dir[support_files].sort.each { |file| require file }
25
+ Dir[support_files].each { |file| require file }
26
26
 
27
27
  RSpec::Matchers.define_negated_matcher :not_change, :change
28
28
  RSpec::Matchers.define_negated_matcher :not_add_method, :add_method
@@ -4,6 +4,7 @@ require 'action_controller'
4
4
 
5
5
  class Controller < ActionController::Base
6
6
  def initialize(params = {})
7
+ super()
7
8
  @params = ActionController::Parameters.new(params)
8
9
  end
9
10
 
@@ -6,11 +6,12 @@ module RSpec
6
6
  attr_reader :method
7
7
 
8
8
  def initialize(method = nil)
9
+ super
9
10
  @method = method
10
11
  end
11
12
 
12
- def to(instance = nil, &block)
13
- AddMethodTo.new(instance, method, &block)
13
+ def to(instance = nil, &)
14
+ AddMethodTo.new(instance, method, &)
14
15
  end
15
16
  end
16
17
 
@@ -18,6 +19,7 @@ module RSpec
18
19
  attr_reader :method, :instance, :block
19
20
 
20
21
  def initialize(instance, method, &block)
22
+ super
21
23
  @instance = instance
22
24
  @method = method
23
25
  @block = block
@@ -68,8 +70,8 @@ module RSpec
68
70
 
69
71
  def raise_block_syntax_error
70
72
  raise SyntaxError, 'Block not received by the' \
71
- '`add_method_to` matcher. ' \
72
- 'Perhaps you want to use `{ ... }` instead of do/end?'
73
+ '`add_method_to` matcher. ' \
74
+ 'Perhaps you want to use `{ ... }` instead of do/end?'
73
75
  end
74
76
  end
75
77
  end
@@ -29,15 +29,11 @@ shared_examples 'a request handler' do |status: :ok|
29
29
  before do
30
30
  create_list(:document, documents_count)
31
31
 
32
- allow(controller).to receive(:params)
33
- .and_return(params)
34
-
35
32
  allow(controller).to receive(:render)
36
33
  .with(json: expected_json, status: status)
37
34
  .and_return(expected_json)
38
35
 
39
- allow(controller).to receive(:headers)
40
- .and_return(controller_headers)
36
+ allow(controller).to receive_messages(params: params, headers: controller_headers)
41
37
  end
42
38
 
43
39
  it 'returns all documents json' do