azeroth 0.7.2 → 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: 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