azeroth 0.8.0 → 0.8.1

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: '09152b8053d40bd19405c5b7165458483d4304310fa5ec64c0d2b5723dda0067'
4
- data.tar.gz: 1a1039542352929720e5cc7ae1242932b7d2a65856e2156b14a36d1a8bb1722b
3
+ metadata.gz: 60f05e09418f7fc0e6155ee3c4e7349e3a80638295eb01032dc0c284a5ccbaa5
4
+ data.tar.gz: 97e333436d04d1cfb255c2dc26751e43aa9da6fad9a383f4c26de33c1df70ffe
5
5
  SHA512:
6
- metadata.gz: 2ae5257e2851ccbbadbd79d9a0c0a13be63e392b2af16c6e1f66be399ee00bc51b06f9682f25d88648f3a32d2c07451d456d80035f04b48a4cc471d27a572e59
7
- data.tar.gz: d7c01b81ce09615d65cc451d2a1669ac9d843d18d75fbb0c12c2e4356507fce62288145bd30295674619a0649327b1b69568fede8adb452e602073f67659235e
6
+ metadata.gz: 2d01f8321b172c0f3d6aedde71ae3e34de04ba261bcacaa4f9157bf8223a75390378167dee429e704a67c38d9d8bb21e695d00faaf612b32dd09d2f53aff9927
7
+ data.tar.gz: b73a0aee9cc39faff3f6e7a3281987028a27bee1034ecc22e0176e36bd8113fa784800d0460966e16fe973384e081112a74472c7e5878595a4156375b09d0ce2
data/README.md CHANGED
@@ -11,7 +11,7 @@ Azeroth
11
11
 
12
12
  Yard Documentation
13
13
  -------------------
14
- [https://www.rubydoc.info/gems/azeroth/0.8.0](https://www.rubydoc.info/gems/azeroth/0.8.0)
14
+ [https://www.rubydoc.info/gems/azeroth/0.8.1](https://www.rubydoc.info/gems/azeroth/0.8.1)
15
15
 
16
16
  Azeroth has been designed making the coding of controllers easier
17
17
  as routes in controllers are usually copy, paste and replace of same
data/config/yardstick.yml CHANGED
@@ -23,6 +23,7 @@ rules:
23
23
  Summary::Presence:
24
24
  enabled: true
25
25
  exclude:
26
+ - Azeroth::ControllerInterface#initialize
26
27
  - Azeroth::Decorator#initialize
27
28
  - Azeroth::Decorator::HashBuilder#initialize
28
29
  - Azeroth::Decorator::KeyValueExtractor#initialize
data/lib/azeroth.rb CHANGED
@@ -11,12 +11,13 @@ require 'jace'
11
11
  #
12
12
  # @see Resourceable
13
13
  module Azeroth
14
- autoload :Decorator, 'azeroth/decorator'
15
- autoload :DummyDecorator, 'azeroth/dummy_decorator'
16
- autoload :Model, 'azeroth/model'
17
- autoload :RequestHandler, 'azeroth/request_handler'
18
- autoload :Resourceable, 'azeroth/resourceable'
19
- autoload :ResourceBuilder, 'azeroth/resource_builder'
20
- autoload :RoutesBuilder, 'azeroth/routes_builder'
21
- autoload :Options, 'azeroth/options'
14
+ autoload :ControllerInterface, 'azeroth/controller_interface'
15
+ autoload :Decorator, 'azeroth/decorator'
16
+ autoload :DummyDecorator, 'azeroth/dummy_decorator'
17
+ autoload :Model, 'azeroth/model'
18
+ autoload :RequestHandler, 'azeroth/request_handler'
19
+ autoload :Resourceable, 'azeroth/resourceable'
20
+ autoload :ResourceBuilder, 'azeroth/resource_builder'
21
+ autoload :RoutesBuilder, 'azeroth/routes_builder'
22
+ autoload :Options, 'azeroth/options'
22
23
  end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Azeroth
4
+ # @api private
5
+ #
6
+ # Interface for using the controller
7
+ class ControllerInterface
8
+ # @param controller [ApplicationController]
9
+ def initialize(controller)
10
+ @controller = controller
11
+ end
12
+
13
+ # Set response headers
14
+ #
15
+ # @param headers_hash [Hash] headers to be set
16
+ #
17
+ # @return [Hash]
18
+ def add_headers(headers_hash)
19
+ controller.instance_eval do
20
+ headers_hash.each do |key, value|
21
+ headers[key.to_s] = value
22
+ end
23
+ end
24
+ end
25
+
26
+ # Renders response json
27
+ #
28
+ # @return [String]
29
+ def render_json(json, status)
30
+ controller.instance_eval do
31
+ render(json: json, status: status)
32
+ end
33
+ end
34
+
35
+ # Set a variable in the controller
36
+ #
37
+ # @param variable [String,Symbol] variable name
38
+ # @param value [Object] value to be set
39
+ #
40
+ # @return [Object]
41
+ def set(variable, value)
42
+ controller.instance_variable_set("@#{variable}", value)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :controller
48
+ # @method controller
49
+ # @private
50
+ # @api private
51
+ #
52
+ # Controller where methods will be called
53
+ #
54
+ # @return [ApplicationController]
55
+
56
+ # @private
57
+ #
58
+ # Dispatcher to delegate all methods call to controller
59
+ #
60
+ # @param method_name [Symbol] name of the method
61
+ # called
62
+ # @param args [Array<Object>] arguments of the
63
+ # method called
64
+ #
65
+ # @return [Object]
66
+ def method_missing(method_name, *args)
67
+ if controller.respond_to?(method_name, true)
68
+ controller.send(method_name, *args)
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ # @private
75
+ #
76
+ # Checks if a controller responds to a method
77
+ #
78
+ # @param method_name [Symbol] name of the method checked
79
+ # @param include_private [TrueClass,FalseClass] flag
80
+ # indicating if private methods should be included
81
+ #
82
+ # @return [TrueClass,FalseClass]
83
+ def respond_to_missing?(method_name, include_private)
84
+ controller.respond_to?(method_name, include_private)
85
+ end
86
+ end
87
+ end
@@ -11,7 +11,7 @@ module Azeroth
11
11
  #
12
12
  # reaader delegate method calls to @object
13
13
  #
14
- # @return (see Sinclair#build)
14
+ # @return [Array<Sinclair::MethodDefinition>]
15
15
  def self.build_reader(klass, attribute)
16
16
  new(klass).build_reader(attribute)
17
17
  end
@@ -19,7 +19,7 @@ module Azeroth
19
19
  # @param controller [ApplicationController]
20
20
  # @param model [Azeroth::Model]
21
21
  def initialize(controller, model, options)
22
- @controller = controller
22
+ @controller = ControllerInterface.new(controller)
23
23
  @model = model
24
24
  @options = options
25
25
  end
@@ -35,12 +35,11 @@ module Azeroth
35
35
  def process
36
36
  return unless json?
37
37
 
38
- json = model.decorate(resource)
39
- response_status = status
40
-
41
- controller.instance_eval do
42
- render(json: json, status: response_status)
43
- end
38
+ controller.add_headers(headers)
39
+ controller.render_json(
40
+ model.decorate(resource),
41
+ status
42
+ )
44
43
  end
45
44
 
46
45
  private
@@ -141,5 +140,15 @@ module Azeroth
141
140
  def collection
142
141
  @collection = controller.send(model.plural)
143
142
  end
143
+
144
+ # @private
145
+ # @abstract
146
+ #
147
+ # Headers to be added
148
+ #
149
+ # @return [Hash]
150
+ def headers
151
+ {}
152
+ end
144
153
  end
145
154
  end
@@ -29,7 +29,7 @@ module Azeroth
29
29
  # @return [Object]
30
30
  def build_and_save_resource
31
31
  @resource = build_resource
32
- controller.instance_variable_set("@#{model.name}", resource)
32
+ controller.set(model.name, resource)
33
33
 
34
34
  trigger_event(:save) do
35
35
  resource.tap(&:save)
@@ -21,6 +21,21 @@ module Azeroth
21
21
  paginated_entries
22
22
  end
23
23
 
24
+ # @private
25
+ #
26
+ # returns pagination headers
27
+ #
28
+ # @return [Hash] heders
29
+ def headers
30
+ return {} unless paginated?
31
+
32
+ {
33
+ pages: pages,
34
+ page: current_page,
35
+ per_page: limit
36
+ }
37
+ end
38
+
24
39
  # @private
25
40
  #
26
41
  # paginated collection of the model
@@ -39,8 +54,7 @@ module Azeroth
39
54
  #
40
55
  # @return [Integer]
41
56
  def offset
42
- page = (params[:page] || 1).to_i - 1
43
- page * limit
57
+ (current_page - 1) * limit
44
58
  end
45
59
 
46
60
  # @private
@@ -62,6 +76,24 @@ module Azeroth
62
76
  def scoped_entries
63
77
  controller.send(model.plural)
64
78
  end
79
+
80
+ # @private
81
+ #
82
+ # calculates current page
83
+ #
84
+ # @return [Integer]
85
+ def current_page
86
+ (params[:page] || 1).to_i
87
+ end
88
+
89
+ # @private
90
+ #
91
+ # calculates how many pages are there
92
+ #
93
+ # @return [Integer]
94
+ def pages
95
+ (scoped_entries.count.to_f / limit).ceil
96
+ end
65
97
  end
66
98
  end
67
99
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Azeroth
4
- VERSION = '0.8.0'
4
+ VERSION = '0.8.1'
5
5
  end
@@ -38,6 +38,18 @@ describe PaginatedDocumentsController do
38
38
  it 'renders documents json' do
39
39
  expect(parsed_response).to eq(expected_json)
40
40
  end
41
+
42
+ it 'adds total pages header' do
43
+ expect(response.headers['pages']).to eq(1)
44
+ end
45
+
46
+ it 'adds current page header' do
47
+ expect(response.headers['page']).to eq(1)
48
+ end
49
+
50
+ it 'adds per page header' do
51
+ expect(response.headers['per_page']).to eq(20)
52
+ end
41
53
  end
42
54
 
43
55
  context 'when there are more documents than expected pagination' do
@@ -54,6 +66,18 @@ describe PaginatedDocumentsController do
54
66
  expect(parsed_response)
55
67
  .to have(20).elements
56
68
  end
69
+
70
+ it 'adds total pages header' do
71
+ expect(response.headers['pages']).to eq(2)
72
+ end
73
+
74
+ it 'adds current page header' do
75
+ expect(response.headers['page']).to eq(1)
76
+ end
77
+
78
+ it 'adds per page header' do
79
+ expect(response.headers['per_page']).to eq(20)
80
+ end
57
81
  end
58
82
 
59
83
  context 'when page is given' do
@@ -72,6 +96,18 @@ describe PaginatedDocumentsController do
72
96
  .to have(documents_count - 20)
73
97
  .elements
74
98
  end
99
+
100
+ it 'adds total pages header' do
101
+ expect(response.headers['pages']).to eq(2)
102
+ end
103
+
104
+ it 'adds current page header' do
105
+ expect(response.headers['page']).to eq(2)
106
+ end
107
+
108
+ it 'adds per page header' do
109
+ expect(response.headers['per_page']).to eq(20)
110
+ end
75
111
  end
76
112
 
77
113
  context 'when per_page is given' do
@@ -91,6 +127,19 @@ describe PaginatedDocumentsController do
91
127
  .to have(per_page)
92
128
  .elements
93
129
  end
130
+
131
+ it 'adds total pages header' do
132
+ expect(response.headers['pages'])
133
+ .to eq((documents_count.to_f / per_page).ceil)
134
+ end
135
+
136
+ it 'adds current page header' do
137
+ expect(response.headers['page']).to eq(1)
138
+ end
139
+
140
+ it 'adds per page header' do
141
+ expect(response.headers['per_page']).to eq(per_page)
142
+ end
94
143
  end
95
144
  end
96
145
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Azeroth::ControllerInterface do
6
+ subject(:interface) { described_class.new(controller) }
7
+
8
+ let(:controller) { controller_class.new }
9
+ let(:controller_class) { RequestHandlerController }
10
+
11
+ describe '#add_headers' do
12
+ let(:controller_headers) do
13
+ {
14
+ 'old_key': 100
15
+ }
16
+ end
17
+
18
+ let(:headers) do
19
+ {
20
+ key1: 10,
21
+ key2: 20
22
+ }
23
+ end
24
+
25
+ before do
26
+ allow(controller)
27
+ .to receive(:headers)
28
+ .and_return(controller_headers)
29
+ end
30
+
31
+ it 'sets controller headers' do
32
+ expect { interface.add_headers(headers) }
33
+ .to change { controller_headers }
34
+ .from(controller_headers)
35
+ .to(controller_headers.merge(headers.stringify_keys))
36
+ end
37
+ end
38
+
39
+ describe '#render_json' do
40
+ let(:json) { { key: 'value' } }
41
+ let(:status) { 200 }
42
+
43
+ before do
44
+ allow(controller)
45
+ .to receive(:render)
46
+ .with(json: json, status: status)
47
+ end
48
+
49
+ it 'renders json' do
50
+ interface.render_json(json, status)
51
+
52
+ expect(controller).to have_received(:render)
53
+ end
54
+ end
55
+
56
+ describe '#set' do
57
+ it 'sets instance variable' do
58
+ expect { interface.set(:name, 20) }
59
+ .to change { controller.instance_variable_get('@name') }
60
+ .from(nil)
61
+ .to(20)
62
+ end
63
+ end
64
+
65
+ describe 'method missing' do
66
+ before do
67
+ create(:document)
68
+ end
69
+
70
+ it 'delegates call to controller' do
71
+ expect(interface.documents)
72
+ .to eq(Document.all)
73
+ end
74
+
75
+ context 'when method is not defined' do
76
+ it do
77
+ expect { interface.pokemons }
78
+ .to raise_error(NoMethodError)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -14,6 +14,21 @@ describe Azeroth::RequestHandler::Index do
14
14
  let(:documents_count) { Random.rand(21..30) }
15
15
  let(:expected_resource) { Document.all.limit(20) }
16
16
  let(:options_hash) { { paginated: true } }
17
+
18
+ it 'adds total pages header' do
19
+ handler.process
20
+ expect(controller_headers['pages']).to eq(2)
21
+ end
22
+
23
+ it 'adds current page header' do
24
+ handler.process
25
+ expect(controller_headers['page']).to eq(1)
26
+ end
27
+
28
+ it 'adds per page header' do
29
+ handler.process
30
+ expect(controller_headers['per_page']).to eq(20)
31
+ end
17
32
  end
18
33
 
19
34
  context 'when page is given' do
@@ -22,6 +37,21 @@ describe Azeroth::RequestHandler::Index do
22
37
  let(:expected_resource) { Document.all.offset(20).limit(20) }
23
38
  let(:options_hash) { { paginated: true } }
24
39
  let(:extra_params) { { page: '2' } }
40
+
41
+ it 'adds total pages header' do
42
+ handler.process
43
+ expect(controller_headers['pages']).to eq(3)
44
+ end
45
+
46
+ it 'adds current page header' do
47
+ handler.process
48
+ expect(controller_headers['page']).to eq(2)
49
+ end
50
+
51
+ it 'adds per page header' do
52
+ handler.process
53
+ expect(controller_headers['per_page']).to eq(20)
54
+ end
25
55
  end
26
56
  end
27
57
 
@@ -31,6 +61,21 @@ describe Azeroth::RequestHandler::Index do
31
61
  let(:expected_resource) { Document.all.offset(40) }
32
62
  let(:options_hash) { { paginated: true } }
33
63
  let(:extra_params) { { page: '3' } }
64
+
65
+ it 'adds total pages header' do
66
+ handler.process
67
+ expect(controller_headers['pages']).to eq(3)
68
+ end
69
+
70
+ it 'adds current page header' do
71
+ handler.process
72
+ expect(controller_headers['page']).to eq(3)
73
+ end
74
+
75
+ it 'adds per page header' do
76
+ handler.process
77
+ expect(controller_headers['per_page']).to eq(20)
78
+ end
34
79
  end
35
80
  end
36
81
 
@@ -39,15 +84,45 @@ describe Azeroth::RequestHandler::Index do
39
84
  let(:documents_count) { Random.rand(21..30) }
40
85
  let(:expected_resource) { Document.all.limit(10) }
41
86
  let(:options_hash) { { paginated: true, per_page: 10 } }
87
+
88
+ it 'adds total pages header' do
89
+ handler.process
90
+ expect(controller_headers['pages']).to eq(3)
91
+ end
92
+
93
+ it 'adds current page header' do
94
+ handler.process
95
+ expect(controller_headers['page']).to eq(1)
96
+ end
97
+
98
+ it 'adds per page header' do
99
+ handler.process
100
+ expect(controller_headers['per_page']).to eq(10)
101
+ end
42
102
  end
43
103
  end
44
104
 
45
105
  context 'when per page is given in params' do
46
106
  it_behaves_like 'a request handler' do
47
107
  let(:documents_count) { Random.rand(41..50) }
48
- let(:expected_resource) { Document.all.offset(15).limit(15) }
49
- let(:options_hash) { { paginated: true, per_page: 10 } }
50
- let(:extra_params) { { page: '2', per_page: '15' } }
108
+ let(:expected_resource) { Document.all.offset(10).limit(10) }
109
+ let(:options_hash) { { paginated: true, per_page: 15 } }
110
+ let(:extra_params) { { page: '2', per_page: '10' } }
111
+
112
+ it 'adds total pages header' do
113
+ handler.process
114
+ expect(controller_headers['pages']).to eq(5)
115
+ end
116
+
117
+ it 'adds current page header' do
118
+ handler.process
119
+ expect(controller_headers['page']).to eq(2)
120
+ end
121
+
122
+ it 'adds per page header' do
123
+ handler.process
124
+ expect(controller_headers['per_page']).to eq(10)
125
+ end
51
126
  end
52
127
  end
53
128
  end
@@ -24,6 +24,8 @@ shared_examples 'a request handler' do |status: :ok|
24
24
  { format: format }.merge(extra_params)
25
25
  end
26
26
 
27
+ let(:controller_headers) { {} }
28
+
27
29
  before do
28
30
  create_list(:document, documents_count)
29
31
 
@@ -33,6 +35,9 @@ shared_examples 'a request handler' do |status: :ok|
33
35
  allow(controller).to receive(:render)
34
36
  .with(json: expected_json, status: status)
35
37
  .and_return(expected_json)
38
+
39
+ allow(controller).to receive(:headers)
40
+ .and_return(controller_headers)
36
41
  end
37
42
 
38
43
  it 'returns all documents json' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: azeroth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darthjee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-11 00:00:00.000000000 Z
11
+ date: 2021-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -456,6 +456,7 @@ files:
456
456
  - config/yardstick.yml
457
457
  - docker-compose.yml
458
458
  - lib/azeroth.rb
459
+ - lib/azeroth/controller_interface.rb
459
460
  - lib/azeroth/decorator.rb
460
461
  - lib/azeroth/decorator/hash_builder.rb
461
462
  - lib/azeroth/decorator/key_value_extractor.rb
@@ -583,6 +584,7 @@ files:
583
584
  - spec/integration/readme/controllers/games_controller_spec.rb
584
585
  - spec/integration/yard/azeroth/decorator_spec.rb
585
586
  - spec/integration/yard/controllers/games_controller_spec.rb
587
+ - spec/lib/azeroth/controller_interface_spec.rb
586
588
  - spec/lib/azeroth/decorator/hash_builder_spec.rb
587
589
  - spec/lib/azeroth/decorator/key_value_extractor_spec.rb
588
590
  - spec/lib/azeroth/decorator/method_builder_spec.rb
@@ -748,6 +750,7 @@ test_files:
748
750
  - spec/integration/readme/controllers/games_controller_spec.rb
749
751
  - spec/integration/yard/azeroth/decorator_spec.rb
750
752
  - spec/integration/yard/controllers/games_controller_spec.rb
753
+ - spec/lib/azeroth/controller_interface_spec.rb
751
754
  - spec/lib/azeroth/decorator/hash_builder_spec.rb
752
755
  - spec/lib/azeroth/decorator/key_value_extractor_spec.rb
753
756
  - spec/lib/azeroth/decorator/method_builder_spec.rb