azeroth 0.7.2 → 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: dbddea8e78679a5a20ccb7c04fd94da0f55718713add9d352d97bff07921df9c
4
- data.tar.gz: e5cc1161a4b36df822458101ce8e4f443a8be05eaf5a0430a0ae09db313e8794
3
+ metadata.gz: 60f05e09418f7fc0e6155ee3c4e7349e3a80638295eb01032dc0c284a5ccbaa5
4
+ data.tar.gz: 97e333436d04d1cfb255c2dc26751e43aa9da6fad9a383f4c26de33c1df70ffe
5
5
  SHA512:
6
- metadata.gz: dd4a272074e69969eddf5d7c3fa3b96d1b0154e117d81b6be419b59573169e100773ecbd97d96f2465a72a5c5e0458c3d7e13d12b5e2c1ed710412a8139e7b4c
7
- data.tar.gz: 0eb07f9c6da10355a9c9db82e555d0eecfaefa75abce57603109efa8aa841a53a70f372afeef6dafe5df9e88504a4180e76f66a8060cbf5841dbdeb6895f6a9f
6
+ metadata.gz: 2d01f8321b172c0f3d6aedde71ae3e34de04ba261bcacaa4f9157bf8223a75390378167dee429e704a67c38d9d8bb21e695d00faaf612b32dd09d2f53aff9927
7
+ data.tar.gz: b73a0aee9cc39faff3f6e7a3281987028a27bee1034ecc22e0176e36bd8113fa784800d0460966e16fe973384e081112a74472c7e5878595a4156375b09d0ce2
data/.circleci/config.yml CHANGED
@@ -18,7 +18,7 @@ workflows:
18
18
  jobs:
19
19
  test:
20
20
  docker:
21
- - image: darthjee/circleci_rails_gems:0.5.4
21
+ - image: darthjee/circleci_rails_gems:0.6.3
22
22
  environment:
23
23
  PROJECT: azeroth
24
24
  steps:
@@ -52,7 +52,7 @@ jobs:
52
52
  command: check_specs
53
53
  build-and-release:
54
54
  docker:
55
- - image: darthjee/circleci_rails_gems:0.5.4
55
+ - image: darthjee/circleci_rails_gems:0.6.3
56
56
  environment:
57
57
  PROJECT: azeroth
58
58
  steps:
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM darthjee/rails_gems:0.5.4 as base
1
+ FROM darthjee/rails_gems:0.7.0 as base
2
2
  FROM darthjee/scripts:0.1.8 as scripts
3
3
 
4
4
  ######################################
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.7.1](https://www.rubydoc.info/gems/azeroth/0.7.2)
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
@@ -59,7 +59,10 @@ It accepts options
59
59
  - except: List of actions to not to be built
60
60
  - decorator: Decorator class or flag allowing/disallowing decorators
61
61
  - before_save: Method/Proc to be ran before saving the resource on create or update
62
+ - after_save: Method/Proc to be ran after saving the resource on create or update
62
63
  - build_with: Method/Block to be ran when building the reource on create
64
+ - paginated: Flag when pagination should be applied
65
+ - per_page: Number of items returned when pagination is active
63
66
 
64
67
  ```ruby
65
68
  # publishers_controller.rb
data/azeroth.gemspec CHANGED
@@ -18,33 +18,35 @@ Gem::Specification.new do |gem|
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
19
  gem.require_paths = ['lib']
20
20
 
21
- gem.add_runtime_dependency 'activesupport', '~> 5.2.4.3'
21
+ gem.add_runtime_dependency 'activesupport', '~> 5.2.x'
22
22
  gem.add_runtime_dependency 'darthjee-active_ext', '>= 1.3.2'
23
23
  gem.add_runtime_dependency 'jace', '>= 0.0.3'
24
- gem.add_runtime_dependency 'sinclair', '>= 1.6.5'
24
+ gem.add_runtime_dependency 'sinclair', '>= 1.6.7'
25
25
 
26
- gem.add_development_dependency 'actionpack', '5.2.4.3'
27
- gem.add_development_dependency 'activerecord', '5.2.4.3'
28
- gem.add_development_dependency 'bundler', '1.16.1'
29
- gem.add_development_dependency 'factory_bot', '5.2.0'
30
- gem.add_development_dependency 'nokogiri', '1.10.9'
31
- gem.add_development_dependency 'pry', '0.12.2'
32
- gem.add_development_dependency 'pry-nav', '0.3.0'
33
- gem.add_development_dependency 'rails', '5.2.4.3'
34
- gem.add_development_dependency 'rails-controller-testing', '1.0.4'
35
- gem.add_development_dependency 'rake', '13.0.1'
36
- gem.add_development_dependency 'reek', '5.6.0'
37
- gem.add_development_dependency 'rspec', '3.9.0'
38
- gem.add_development_dependency 'rspec-core', '3.9.1'
39
- gem.add_development_dependency 'rspec-expectations', '3.9.1'
40
- gem.add_development_dependency 'rspec-mocks', '3.9.1'
41
- gem.add_development_dependency 'rspec-rails', '3.9.0'
42
- gem.add_development_dependency 'rspec-support', '3.9.2'
43
- gem.add_development_dependency 'rubocop', '0.80.1'
44
- gem.add_development_dependency 'rubocop-rspec', '1.38.1'
45
- gem.add_development_dependency 'rubycritic', '4.4.1'
46
- gem.add_development_dependency 'simplecov', '0.17.1'
47
- gem.add_development_dependency 'sqlite3', '1.4.2'
48
- gem.add_development_dependency 'yard', '0.9.24'
49
- gem.add_development_dependency 'yardstick', '0.9.9'
26
+ gem.add_development_dependency 'actionpack', '~> 5.2.x'
27
+ gem.add_development_dependency 'activerecord', '~> 5.2.x'
28
+ gem.add_development_dependency 'bundler', '1.16.1'
29
+ gem.add_development_dependency 'factory_bot', '5.2.0'
30
+ gem.add_development_dependency 'nokogiri', '1.11.4'
31
+ gem.add_development_dependency 'pry', '0.12.2'
32
+ gem.add_development_dependency 'pry-nav', '0.3.0'
33
+ gem.add_development_dependency 'rails', '~> 5.2.x'
34
+ gem.add_development_dependency 'rails-controller-testing', '1.0.4'
35
+ gem.add_development_dependency 'rake', '13.0.3'
36
+ gem.add_development_dependency 'reek', '6.0.3'
37
+ gem.add_development_dependency 'rspec', '3.9.0'
38
+ gem.add_development_dependency 'rspec-collection_matchers', '1.2.0'
39
+ gem.add_development_dependency 'rspec-core', '3.9.3'
40
+ gem.add_development_dependency 'rspec-expectations', '3.9.4'
41
+ gem.add_development_dependency 'rspec-mocks', '3.9.1'
42
+ gem.add_development_dependency 'rspec-rails', '3.9.0'
43
+ gem.add_development_dependency 'rspec-support', '3.9.4'
44
+ gem.add_development_dependency 'rubocop', '0.80.1'
45
+ gem.add_development_dependency 'rubocop-rspec', '1.38.1'
46
+ gem.add_development_dependency 'rubycritic', '4.6.1'
47
+ gem.add_development_dependency 'shoulda-matchers', '4.3.0'
48
+ gem.add_development_dependency 'simplecov', '0.17.1'
49
+ gem.add_development_dependency 'sqlite3', '1.4.2'
50
+ gem.add_development_dependency 'yard', '0.9.26'
51
+ gem.add_development_dependency 'yardstick', '0.9.9'
50
52
  end
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
@@ -42,6 +42,7 @@ module Azeroth
42
42
  class Decorator
43
43
  autoload :HashBuilder, 'azeroth/decorator/hash_builder'
44
44
  autoload :KeyValueExtractor, 'azeroth/decorator/key_value_extractor'
45
+ autoload :MethodBuilder, 'azeroth/decorator/method_builder'
45
46
  autoload :Options, 'azeroth/decorator/options'
46
47
 
47
48
  class << self
@@ -228,9 +229,7 @@ module Azeroth
228
229
  def expose(attribute, **options_hash)
229
230
  options = Decorator::Options.new(options_hash)
230
231
 
231
- builder = Sinclair.new(self)
232
- builder.add_method(attribute, "@object.#{attribute}")
233
- builder.build
232
+ MethodBuilder.build_reader(self, attribute)
234
233
 
235
234
  attributes_map[attribute] = options
236
235
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinclair'
4
+
5
+ module Azeroth
6
+ class Decorator
7
+ # Responsible for building readers for attributes
8
+ # @api private
9
+ class MethodBuilder < Sinclair
10
+ # Builds reader
11
+ #
12
+ # reaader delegate method calls to @object
13
+ #
14
+ # @return [Array<Sinclair::MethodDefinition>]
15
+ def self.build_reader(klass, attribute)
16
+ new(klass).build_reader(attribute)
17
+ end
18
+
19
+ # (see MethodBuilder.build_reader)
20
+ def build_reader(attribute)
21
+ add_method(attribute, "@object.#{attribute}")
22
+ build
23
+ end
24
+ end
25
+ end
26
+ end
@@ -19,7 +19,10 @@ module Azeroth
19
19
  except: [],
20
20
  decorator: true,
21
21
  before_save: nil,
22
- build_with: nil
22
+ after_save: nil,
23
+ build_with: nil,
24
+ paginated: false,
25
+ per_page: 20
23
26
  }.freeze
24
27
 
25
28
  with_options DEFAULT_OPTIONS
@@ -40,10 +43,18 @@ module Azeroth
40
43
  # @return [Jace::Dispatcher]
41
44
  def event_dispatcher(event)
42
45
  Jace::Dispatcher.new(
43
- before: try("before_#{event}")
46
+ before: try("before_#{event}"),
47
+ after: try("after_#{event}")
44
48
  )
45
49
  end
46
50
 
51
+ alias paginated? paginated
52
+ # @method paginated?
53
+ # @api private
54
+ #
55
+ # @see paginated
56
+ # @return [TrueClass,FalseClass]
57
+
47
58
  # @method only
48
59
  # @api private
49
60
  #
@@ -81,11 +92,36 @@ module Azeroth
81
92
  #
82
93
  # @return [Symbol,Proc]
83
94
 
95
+ # @method after_save
96
+ # @api private
97
+ #
98
+ # Block or method name to be run after save
99
+ #
100
+ # The given method or block will be ran
101
+ # after committing changes in models
102
+ # to database
103
+ #
104
+ # @return [Symbol,Proc]
105
+
84
106
  # @method build_with
85
107
  # @api private
86
108
  #
87
109
  # Block or method name to be ran when building the resource
88
110
  #
89
111
  # @return [Symbol,Proc]
112
+
113
+ # @method paginated
114
+ # @api private
115
+ #
116
+ # Boolean indicating if pagination should or not be used
117
+ #
118
+ # @return [TrueClass,FalseClass]
119
+
120
+ # @method per_page
121
+ # @api private
122
+ #
123
+ # Number of elements when pagination is active
124
+ #
125
+ # @return [Integer]
90
126
  end
91
127
  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)
@@ -8,14 +8,92 @@ module Azeroth
8
8
  class Index < RequestHandler
9
9
  private
10
10
 
11
+ delegate :paginated?, :per_page, to: :options
12
+
11
13
  # @private
12
14
  #
13
15
  # return a collection of the model
14
16
  #
15
17
  # @return [Enumerable<Object>]
16
18
  def resource
19
+ return scoped_entries unless paginated?
20
+
21
+ paginated_entries
22
+ end
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
+
39
+ # @private
40
+ #
41
+ # paginated collection of the model
42
+ #
43
+ # @return [Enumerable<Object>]
44
+ def paginated_entries
45
+ scoped_entries.offset(offset).limit(limit)
46
+ end
47
+
48
+ # @private
49
+ #
50
+ # offest used in pagination
51
+ #
52
+ # offset is retrieved from +params[:per_page]+
53
+ # or +options.per_page+
54
+ #
55
+ # @return [Integer]
56
+ def offset
57
+ (current_page - 1) * limit
58
+ end
59
+
60
+ # @private
61
+ #
62
+ # limit used in pagination
63
+ #
64
+ # limit is retrieved from +params[:page]+
65
+ #
66
+ # @return [Integer]
67
+ def limit
68
+ (params[:per_page] || per_page).to_i
69
+ end
70
+
71
+ # @private
72
+ #
73
+ # default scope of elements
74
+ #
75
+ # @return [Enumerable<Object>]
76
+ def scoped_entries
17
77
  controller.send(model.plural)
18
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
19
97
  end
20
98
  end
21
99
  end