snfoil 0.5.0 → 0.7.0

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: 8243d9d711a164c99818bd9217d002a4bbeda113d6c68d45dad064bea6a04618
4
- data.tar.gz: 53c8ee7b0b44bf7411eb98aebb23793ebf5dd69fab16a278abb2895062edabc6
3
+ metadata.gz: 47df13555f0efd4bd9ad506a79f9af2d3955f209bd4fabc0e086f6f5e7b7d953
4
+ data.tar.gz: 74a0a9556cfeed6b434ba40319b7bea0329ddffbcd31f3155aec2b37f0474b71
5
5
  SHA512:
6
- metadata.gz: 25527b584b0d1c3360ef226ecf16a4934ae209bbc96aed912f4131b056303a16e4bdbdfd801fb0adb2b1d2b47ec120e021990c764fb9ca34886269d68804d921
7
- data.tar.gz: 67e8a71e82d49cc5fe3aa45b4fad9140cb234f3d48151af1930279b9109603dcece1bbdbecfe8dd8fe1d99c11252e01ae454435184b3e4e8c34754f6b877de8a
6
+ metadata.gz: d76ecf6affbc2be179ccd3fef9c28941f4217ff6ad4a0b708605749cf2f89b0108e409fd51cd792fd53915e1f4db00324cce3f9aa430dadd5a6b42315d432b21
7
+ data.tar.gz: 2acfb8773a4f31bce92c81b66eb9024800990a10804cf9e7d9d72a53ea0bc631b4b9f5ed44af5e7218c668d55c634ae43b5d919e91af32015415326f1994bece
data/TODO.md ADDED
@@ -0,0 +1,5 @@
1
+ # TODO
2
+ ## Tests
3
+ ### Contexts
4
+ - Add tests for propagation of :authorize in options aggregate
5
+ - Add tests for Create now using Build
@@ -10,6 +10,8 @@ require_relative 'sn_foil/contexts/destroy_context'
10
10
  require_relative 'sn_foil/context'
11
11
  require_relative 'sn_foil/policy'
12
12
  require_relative 'sn_foil/searcher'
13
+ require_relative 'sn_foil/adapters/orms/base_adapter'
14
+ require_relative 'sn_foil/adapters/orms/active_record'
13
15
  require 'active_support/core_ext/module/attribute_accessors'
14
16
  require 'logger'
15
17
 
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'base_adapter'
4
+
3
5
  module SnFoil
4
6
  module Adapters
5
7
  module ORMs
6
8
  class ActiveRecord < SnFoil::Adapters::ORMs::BaseAdapter
7
- def new(*params)
8
- self.class.new(__getobj__.new(*params))
9
+ def new(**params)
10
+ self.class.new(__getobj__.new(params))
9
11
  end
10
12
 
11
13
  def all
@@ -21,9 +23,13 @@ module SnFoil
21
23
  __getobj__.destroyed?
22
24
  end
23
25
 
24
- def attributes=(*attributes)
26
+ def attributes=(attributes)
25
27
  __getobj__.attributes = attributes
26
28
  end
29
+
30
+ def is_a?(klass)
31
+ __getobj__.class.object_id == klass.object_id
32
+ end
27
33
  end
28
34
  end
29
35
  end
@@ -4,7 +4,7 @@ module SnFoil
4
4
  module Adapters
5
5
  module ORMs
6
6
  class BaseAdapter < SimpleDelegator
7
- def new(*_params)
7
+ def new(**_params)
8
8
  raise NotImplementedError, '#new not implemented in adapter'
9
9
  end
10
10
 
@@ -20,7 +20,7 @@ module SnFoil
20
20
  raise NotImplementedError, '#destroy not implemented in adapter'
21
21
  end
22
22
 
23
- def attributes=(**_attributes)
23
+ def attributes=(_attributes)
24
24
  raise NotImplementedError, '#attributes= not implemented in adapter'
25
25
  end
26
26
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'active_support/concern'
4
4
  require_relative './setup_context'
5
- require_relative './change_context'
6
5
 
7
6
  module SnFoil
8
7
  module Contexts
@@ -11,33 +10,58 @@ module SnFoil
11
10
 
12
11
  included do
13
12
  include SetupContext
14
- include ChangeContext
15
13
  end
16
14
 
17
15
  class_methods do
16
+ attr_reader :i_setup_build_hooks
17
+
18
18
  def build(params:, entity: nil, **options)
19
19
  new(entity).build(**options, params: params)
20
20
  end
21
+
22
+ def setup_build(method = nil, **options, &block)
23
+ raise ArgumentError, '#setup_build requires either a method name or a block' if method.nil? && block.nil?
24
+
25
+ (@i_setup_build_hooks ||= []) << { method: method, block: block, if: options[:if], unless: options[:unless] }
26
+ end
21
27
  end
22
28
 
23
29
  def setup_build_object(params: {}, object: nil, **options)
24
- SnFoil.logger.info 'Warning: Using build bypasses authorize. It is safer to interact with models through create' unless ENV['ISTEST']
25
- return wrap_object(object) if object
30
+ object = if object
31
+ wrap_object(object)
32
+ else
33
+ klass = options.fetch(:model) { model }
34
+ wrap_object(klass).new
35
+ end
26
36
 
27
- klass = options.fetch(:model) { model }
28
- options.merge! object: wrap_object(klass).new(**params)
37
+ object.attributes = params
38
+ options.merge! object: object
29
39
  end
30
40
 
31
41
  def build(**options)
32
42
  options[:action] = :build
33
- options = setup_build(setup_change(**options))
43
+ options = before_setup_build_object(**options)
34
44
  options = setup_build_object(**options)
45
+ authorize(options[:object], options[:authorize], **options) if options[:authorize]
35
46
  unwrap_object(options[:object])
36
47
  end
37
48
 
38
49
  def setup_build(**options)
39
50
  options
40
51
  end
52
+
53
+ def setup_build_hooks
54
+ self.class.i_setup_build_hooks || []
55
+ end
56
+
57
+ private
58
+
59
+ def before_setup_build_object(**options)
60
+ options = setup(**options)
61
+ options = setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
62
+ options = setup_build(**options)
63
+ setup_build_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
64
+ end
41
65
  end
42
66
  end
43
67
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/concern'
4
- require_relative './setup_context'
5
4
  require_relative './change_context'
6
5
 
7
6
  module SnFoil
@@ -10,8 +9,10 @@ module SnFoil
10
9
  extend ActiveSupport::Concern
11
10
 
12
11
  included do
13
- include SetupContext
12
+ include BuildContext
14
13
  include ChangeContext
14
+
15
+ alias_method :setup_create_object, :setup_build_object
15
16
  end
16
17
 
17
18
  class_methods do
@@ -52,25 +53,14 @@ module SnFoil
52
53
  end
53
54
  end
54
55
 
55
- def setup_create_object(params: {}, object: nil, **options)
56
- object = if object
57
- wrap_object(object)
58
- else
59
- klass = options.fetch(:model) { model }
60
- wrap_object(klass).new
61
- end
62
-
63
- object.attributes = params
64
- options.merge! object: object
65
- end
66
-
67
56
  def create(**options)
68
57
  options[:action] = :create
58
+ options = before_setup_build_object(**options)
69
59
  options = before_setup_create_object(**options)
70
60
  options = setup_create_object(**options)
71
- authorize(options[:object], :create?, **options)
61
+ authorize(options[:object], options.fetch(:authorize) { :create? }, **options)
72
62
  options = create_hooks(**options)
73
- unwrap_object(options[:object])
63
+ options[:object]
74
64
  end
75
65
 
76
66
  def setup_create(**options)
@@ -116,18 +106,18 @@ module SnFoil
116
106
  private
117
107
 
118
108
  def before_setup_create_object(**options)
119
- options = setup_create(**options)
120
- options = setup_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
121
109
  options = setup_change(**options)
122
110
  options = setup_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
123
- options = setup(**options)
124
- setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
111
+ options = setup_create(**options)
112
+ setup_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
125
113
  end
126
114
 
127
115
  # This method is private to help protect the order of execution of hooks
128
116
  def create_hooks(options)
129
117
  options = before_create_save(**options)
130
- options = if options[:object].save
118
+ save_successful = options[:object].save
119
+ options.merge!(object: unwrap_object(options[:object]))
120
+ options = if save_successful
131
121
  after_create_save_success(**options)
132
122
  else
133
123
  after_create_save_failure(**options)
@@ -136,31 +126,31 @@ module SnFoil
136
126
  end
137
127
 
138
128
  def before_create_save(**options)
139
- options = before_create(**options)
140
- options = before_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
141
129
  options = before_change(**options)
142
- before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
130
+ options = before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
131
+ options = before_create(**options)
132
+ before_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
143
133
  end
144
134
 
145
135
  def after_create_save(**options)
146
- options = after_create(**options)
147
- options = after_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
148
136
  options = after_change(**options)
149
- after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
137
+ options = after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
138
+ options = after_create(**options)
139
+ after_create_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
150
140
  end
151
141
 
152
142
  def after_create_save_success(**options)
153
- options = after_create_success(**options)
154
- options = after_create_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
155
143
  options = after_change_success(**options)
156
- after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
144
+ options = after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
145
+ options = after_create_success(**options)
146
+ after_create_success_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
157
147
  end
158
148
 
159
149
  def after_create_save_failure(**options)
160
- options = after_create_failure(**options)
161
- options = after_create_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
162
150
  options = after_change_failure(**options)
163
- after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
151
+ options = after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
152
+ options = after_create_failure(**options)
153
+ after_create_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
164
154
  end
165
155
  end
166
156
  end
@@ -62,9 +62,9 @@ module SnFoil
62
62
  options[:action] = :destroy
63
63
  options = before_setup_destroy_object(**options)
64
64
  options = setup_destroy_object(**options)
65
- authorize(options[:object], :destroy?, **options)
65
+ authorize(options[:object], options.fetch(:authorize) { :destroy? }, **options)
66
66
  options = destroy_hooks(**options)
67
- unwrap_object(options[:object])
67
+ options[:object]
68
68
  end
69
69
 
70
70
  def setup_destroy(**options)
@@ -110,18 +110,20 @@ module SnFoil
110
110
  private
111
111
 
112
112
  def before_setup_destroy_object(**options)
113
- options = setup_destroy(**options)
114
- options = setup_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
113
+ options = setup(**options)
114
+ options = setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
115
115
  options = setup_change(**options)
116
116
  options = setup_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
117
- options = setup(**options)
118
- setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
117
+ options = setup_destroy(**options)
118
+ setup_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
119
119
  end
120
120
 
121
121
  # This method is private to help protect the order of execution of hooks
122
122
  def destroy_hooks(options)
123
123
  options = before_destroy_save(options)
124
- options = if options[:object].destroy
124
+ destroy_successful = options[:object].destroy
125
+ options.merge!(object: unwrap_object(options[:object]))
126
+ options = if destroy_successful
125
127
  after_destroy_save_success(options)
126
128
  else
127
129
  after_destroy_save_failure(options)
@@ -130,31 +132,31 @@ module SnFoil
130
132
  end
131
133
 
132
134
  def before_destroy_save(options)
133
- options = before_destroy(**options)
134
- options = before_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
135
135
  options = before_change(**options)
136
- before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
136
+ options = before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
137
+ options = before_destroy(**options)
138
+ before_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
137
139
  end
138
140
 
139
141
  def after_destroy_save(options)
140
- options = after_destroy(**options)
141
- options = after_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
142
142
  options = after_change(**options)
143
- after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
143
+ options = after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
144
+ options = after_destroy(**options)
145
+ after_destroy_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
144
146
  end
145
147
 
146
148
  def after_destroy_save_success(options)
147
- options = after_destroy_success(**options)
148
- options = after_destroy_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
149
149
  options = after_change_success(**options)
150
- after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
150
+ options = after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
151
+ options = after_destroy_success(**options)
152
+ after_destroy_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
151
153
  end
152
154
 
153
155
  def after_destroy_save_failure(options)
154
- options = after_destroy_failure(**options)
155
- options = after_destroy_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
156
156
  options = after_change_failure(**options)
157
- after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
157
+ options = after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
158
+ options = after_destroy_failure(**options)
159
+ after_destroy_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
158
160
  end
159
161
  end
160
162
  end
@@ -54,10 +54,10 @@ module SnFoil
54
54
  private
55
55
 
56
56
  def before_setup_index(**options)
57
- options = setup_index(**options)
58
- options = setup_index_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
59
57
  options = setup(**options)
60
- setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
58
+ options = setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
59
+ options = setup_index(**options)
60
+ setup_index_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
61
61
  end
62
62
  end
63
63
  end
@@ -51,10 +51,10 @@ module SnFoil
51
51
  private
52
52
 
53
53
  def before_setup_show(**options)
54
- options = setup_show(**options)
55
- options = setup_show_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
56
54
  options = setup(**options)
57
- setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
55
+ options = setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
56
+ options = setup_show(**options)
57
+ setup_show_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
58
58
  end
59
59
  end
60
60
  end
@@ -56,7 +56,8 @@ module SnFoil
56
56
  raise ArgumentError, 'one of the following keywords is required: id, object' unless id || object
57
57
 
58
58
  object = wrap_object(object || scope.resolve.find(id))
59
- authorize(object, :update?, **options)
59
+ authorize(object, options.fetch(:authorize) { :update? }, **options)
60
+
60
61
  object.attributes = params
61
62
  options.merge! object: object
62
63
  end
@@ -65,9 +66,9 @@ module SnFoil
65
66
  options[:action] = :update
66
67
  options = before_setup_update_object(**options)
67
68
  options = setup_update_object(**options)
68
- authorize(options[:object], :update?, **options)
69
+ authorize(options[:object], options.fetch(:authorize) { :update? }, **options)
69
70
  options = update_hooks(**options)
70
- unwrap_object(options[:object])
71
+ options[:object]
71
72
  end
72
73
 
73
74
  def setup_update(**options)
@@ -113,18 +114,20 @@ module SnFoil
113
114
  private
114
115
 
115
116
  def before_setup_update_object(**options)
116
- options = setup_update(**options)
117
- options = setup_update_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
117
+ options = setup(**options)
118
+ options = setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
118
119
  options = setup_change(**options)
119
120
  options = setup_change_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
120
- options = setup(**options)
121
- setup_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
121
+ options = setup_update(**options)
122
+ setup_update_hooks.reduce(options) { |opts, hook| run_hook(hook, opts) }
122
123
  end
123
124
 
124
125
  # This method is private to help protect the order of execution of hooks
125
126
  def update_hooks(options)
126
127
  options = before_update_save(options)
127
- options = if options[:object].save
128
+ update_successful = options[:object].save
129
+ options.merge!(object: unwrap_object(options[:object]))
130
+ options = if update_successful
128
131
  after_update_save_success(options)
129
132
  else
130
133
  after_update_save_failure(options)
@@ -133,31 +136,31 @@ module SnFoil
133
136
  end
134
137
 
135
138
  def before_update_save(options)
136
- options = before_update(**options)
137
- options = before_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
138
139
  options = before_change(**options)
139
- before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
140
+ options = before_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
141
+ options = before_update(**options)
142
+ before_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
140
143
  end
141
144
 
142
145
  def after_update_save(options)
143
- options = after_update(**options)
144
- options = after_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
145
146
  options = after_change(**options)
146
- after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
147
+ options = after_change_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
148
+ options = after_update(**options)
149
+ after_update_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
147
150
  end
148
151
 
149
152
  def after_update_save_success(options)
150
- options = after_update_success(**options)
151
- options = after_update_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
152
153
  options = after_change_success(**options)
153
- after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
154
+ options = after_change_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
155
+ options = after_update_success(**options)
156
+ after_update_success_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
154
157
  end
155
158
 
156
159
  def after_update_save_failure(options)
157
- options = after_update_failure(**options)
158
- options = after_update_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
159
160
  options = after_change_failure(**options)
160
- after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
161
+ options = after_change_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
162
+ options = after_update_failure(**options)
163
+ after_update_failure_hooks.reduce(options) { |opts, hook| run_hook(hook, **opts) }
161
164
  end
162
165
  end
163
166
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SnFoil
4
- VERSION = '0.5.0'
4
+ VERSION = '0.7.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snfoil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Howes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-04-16 00:00:00.000000000 Z
12
+ date: 2020-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -17,14 +17,14 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '5.1'
20
+ version: 5.2.4.3
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '5.1'
27
+ version: 5.2.4.3
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: logger
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -162,6 +162,7 @@ files:
162
162
  - CODE_OF_CONDUCT.md
163
163
  - README.md
164
164
  - Rakefile
165
+ - TODO.md
165
166
  - lib/sn_foil.rb
166
167
  - lib/sn_foil/adapters/orms/active_record.rb
167
168
  - lib/sn_foil/adapters/orms/base_adapter.rb