azeroth 0.8.0 → 0.8.1

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