snfoil 0.9.0 → 1.0.0

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE.txt +201 -0
  5. data/README.md +95 -505
  6. data/docs/build-context.md +56 -0
  7. data/docs/create-context.md +109 -0
  8. data/docs/destroy-context.md +102 -0
  9. data/docs/index-context.md +70 -0
  10. data/docs/show-context.md +71 -0
  11. data/docs/update-context.md +107 -0
  12. data/lib/{sn_foil → snfoil}/adapters/orms/active_record.rb +14 -0
  13. data/lib/{sn_foil → snfoil}/adapters/orms/base_adapter.rb +15 -1
  14. data/lib/snfoil/crud/build_context.rb +49 -0
  15. data/lib/snfoil/crud/change_context.rb +48 -0
  16. data/lib/snfoil/crud/context.rb +41 -0
  17. data/lib/snfoil/crud/create_context.rb +45 -0
  18. data/lib/snfoil/crud/destroy_context.rb +57 -0
  19. data/lib/snfoil/crud/index_context.rb +46 -0
  20. data/lib/snfoil/crud/setup_context.rb +90 -0
  21. data/lib/snfoil/crud/show_context.rb +52 -0
  22. data/lib/snfoil/crud/update_context.rb +60 -0
  23. data/lib/snfoil/version.rb +19 -0
  24. data/lib/snfoil.rb +69 -0
  25. data/snfoil.gemspec +47 -0
  26. metadata +100 -33
  27. data/Rakefile +0 -4
  28. data/lib/sn_foil/context.rb +0 -24
  29. data/lib/sn_foil/contexts/build_context.rb +0 -67
  30. data/lib/sn_foil/contexts/change_context.rb +0 -101
  31. data/lib/sn_foil/contexts/create_context.rb +0 -158
  32. data/lib/sn_foil/contexts/destroy_context.rb +0 -164
  33. data/lib/sn_foil/contexts/index_context.rb +0 -64
  34. data/lib/sn_foil/contexts/setup_context.rb +0 -119
  35. data/lib/sn_foil/contexts/show_context.rb +0 -61
  36. data/lib/sn_foil/contexts/update_context.rb +0 -168
  37. data/lib/sn_foil/policy.rb +0 -55
  38. data/lib/sn_foil/searcher.rb +0 -123
  39. data/lib/sn_foil/version.rb +0 -5
  40. data/lib/sn_foil.rb +0 -49
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+ require_relative './change_context'
19
+
20
+ module SnFoil
21
+ module CRUD
22
+ module CreateContext
23
+ extend ActiveSupport::Concern
24
+
25
+ included do
26
+ include BuildContext
27
+ include ChangeContext
28
+
29
+ action :create, with: :create_action
30
+
31
+ setup_create { |options| run_interval(:setup, **options) }
32
+ setup_create { |options| run_interval(:setup_build, **options) }
33
+ setup_create { |options| run_interval(:setup_change, **options) }
34
+ before_create { |options| run_interval(:before_change, **options) }
35
+ after_create_success { |options| run_interval(:after_change_success, **options) }
36
+ after_create_failure { |options| run_interval(:after_change_failure, **options) }
37
+ after_create { |options| run_interval(:after_change, **options) }
38
+
39
+ def create_action(options)
40
+ wrap_object(options[:object]).save
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+ require_relative './setup_context'
19
+ require_relative './change_context'
20
+
21
+ module SnFoil
22
+ module CRUD
23
+ module DestroyContext
24
+ extend ActiveSupport::Concern
25
+
26
+ included do
27
+ include SetupContext
28
+ include ChangeContext
29
+
30
+ action :destroy, with: :destroy_action
31
+
32
+ setup_destroy { |options| run_interval(:setup, **options) }
33
+ setup_destroy { |options| run_interval(:setup_change, **options) }
34
+ before_destroy { |options| run_interval(:before_change, **options) }
35
+ after_destroy_success { |options| run_interval(:after_change_success, **options) }
36
+ after_destroy_failure { |options| run_interval(:after_change_failure, **options) }
37
+ after_destroy { |options| run_interval(:after_change, **options) }
38
+
39
+ setup_destroy do |options|
40
+ raise ArgumentError, 'one of the following keywords is required: id, object' unless options[:id] || options[:object]
41
+
42
+ options
43
+ end
44
+
45
+ before_destroy do |options|
46
+ options[:object] ||= scope.resolve.find(options[:id])
47
+
48
+ options
49
+ end
50
+
51
+ def destroy_action(options)
52
+ wrap_object(options[:object]).destroy
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+ require_relative './change_context'
19
+
20
+ module SnFoil
21
+ module CRUD
22
+ module IndexContext
23
+ extend ActiveSupport::Concern
24
+
25
+ included do
26
+ include SetupContext
27
+
28
+ action :index, with: :index_action
29
+
30
+ setup_index { |options| run_interval(:setup, **options) }
31
+
32
+ before_index do |options|
33
+ options[:object] ||= options.fetch(:searcher) { self.class.snfoil_searcher }
34
+ .new(scope: scope.resolve)
35
+ .search(options.fetch(:params) { {} })
36
+
37
+ options
38
+ end
39
+
40
+ def index_action(**options)
41
+ options[:object]
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'snfoil/context'
18
+
19
+ require 'active_support/concern'
20
+ require 'active_support/core_ext/string/inflections'
21
+
22
+ module SnFoil
23
+ module CRUD
24
+ module SetupContext
25
+ extend ActiveSupport::Concern
26
+
27
+ included do
28
+ include SnFoil::Context
29
+
30
+ interval :setup
31
+
32
+ authorize do |options|
33
+ options.fetch(:policy) { policy }
34
+ .new(entity, options[:object], **options)
35
+ .send(options.fetch(:authorize) { "#{options[:action]}?" })
36
+ end
37
+ end
38
+
39
+ class_methods do
40
+ attr_reader :snfoil_model, :snfoil_policy, :snfoil_searcher
41
+
42
+ def searcher(klass = nil)
43
+ @snfoil_searcher = klass
44
+ end
45
+
46
+ def model(klass = nil)
47
+ @snfoil_model = klass
48
+ end
49
+
50
+ def policy(klass = nil)
51
+ @snfoil_policy = klass
52
+ end
53
+ end
54
+
55
+ def model
56
+ self.class.snfoil_model
57
+ end
58
+
59
+ def policy
60
+ self.class.snfoil_policy
61
+ end
62
+
63
+ def scope(_object_class = nil, **options)
64
+ "#{policy.name}::Scope".safe_constantize.new(wrap_object(model), entity, **options)
65
+ end
66
+
67
+ def wrap_object(object)
68
+ return object unless adapter
69
+
70
+ adapter.new(object)
71
+ end
72
+
73
+ def unwrap_object(object)
74
+ return object unless adapter
75
+
76
+ adapter?(object) ? object.__getobj__ : object
77
+ end
78
+
79
+ def adapter?(object)
80
+ return false unless adapter
81
+
82
+ object.instance_of? adapter
83
+ end
84
+
85
+ def adapter
86
+ @adapter ||= SnFoil.adapter
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+ require_relative './setup_context'
19
+
20
+ module SnFoil
21
+ module CRUD
22
+ module ShowContext
23
+ extend ActiveSupport::Concern
24
+
25
+ included do
26
+ include SetupContext
27
+
28
+ action :show, with: :show_action
29
+
30
+ setup_show do |options|
31
+ raise ArgumentError, 'one of the following keywords is required: id, object' unless options[:id] || options[:object]
32
+
33
+ options
34
+ end
35
+
36
+ setup_show do |options|
37
+ run_interval(:setup, **options)
38
+ end
39
+
40
+ before_show do |**options|
41
+ options[:object] ||= scope.resolve.find(options[:id])
42
+
43
+ options
44
+ end
45
+
46
+ def show_action(options)
47
+ options[:object]
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/concern'
18
+ require_relative './setup_context'
19
+ require_relative './change_context'
20
+
21
+ module SnFoil
22
+ module CRUD
23
+ module UpdateContext
24
+ extend ActiveSupport::Concern
25
+
26
+ included do
27
+ include SetupContext
28
+ include ChangeContext
29
+
30
+ action :update, with: :update_action
31
+
32
+ setup_update { |options| run_interval(:setup, **options) }
33
+ setup_update { |options| run_interval(:setup_change, **options) }
34
+ before_update { |options| run_interval(:before_change, **options) }
35
+ after_update_success { |options| run_interval(:after_change_success, **options) }
36
+ after_update_failure { |options| run_interval(:after_change_failure, **options) }
37
+ after_update { |options| run_interval(:after_change, **options) }
38
+
39
+ setup_update do |options|
40
+ raise ArgumentError, 'one of the following keywords is required: id, object' unless options[:id] || options[:object]
41
+
42
+ options
43
+ end
44
+
45
+ before_update do |options|
46
+ params = options.fetch(:params) { {} }
47
+ options[:object] ||= scope.resolve.find(options[:id])
48
+
49
+ wrap_object(options[:object]).attributes = params
50
+
51
+ options
52
+ end
53
+
54
+ def update_action(options)
55
+ wrap_object(options[:object]).save
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module SnFoil
18
+ VERSION = '1.0.0'
19
+ end
data/lib/snfoil.rb ADDED
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 Matthew Howes
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'active_support/core_ext/module/attribute_accessors'
18
+ require 'logger'
19
+ require 'snfoil/context'
20
+ require 'snfoil/policy'
21
+ require 'snfoil/searcher'
22
+
23
+ require_relative 'snfoil/version'
24
+
25
+ require_relative 'snfoil/crud/build_context'
26
+ require_relative 'snfoil/crud/change_context'
27
+ require_relative 'snfoil/crud/create_context'
28
+ require_relative 'snfoil/crud/destroy_context'
29
+ require_relative 'snfoil/crud/index_context'
30
+ require_relative 'snfoil/crud/setup_context'
31
+ require_relative 'snfoil/crud/show_context'
32
+ require_relative 'snfoil/crud/update_context'
33
+ require_relative 'snfoil/crud/context'
34
+
35
+ require_relative 'snfoil/adapters/orms/base_adapter'
36
+ require_relative 'snfoil/adapters/orms/active_record'
37
+
38
+ module SnFoil
39
+ class Error < StandardError; end
40
+
41
+ mattr_accessor :orm, default: 'active_record'
42
+ mattr_writer :logger
43
+
44
+ class << self
45
+ def logger
46
+ @logger ||= Logger.new($stdout).tap do |log|
47
+ log.progname = name
48
+ end
49
+ end
50
+
51
+ def adapter
52
+ return @adapter if @adapter
53
+
54
+ @adapter ||= if orm.instance_of?(String) || orm.instance_of?(Symbol)
55
+ if Object.const_defined?("SnFoil::Adapters::ORMs::#{orm.camelcase}")
56
+ "SnFoil::Adapters::ORMs::#{orm.camelcase}".constantize
57
+ else
58
+ orm.constantize
59
+ end
60
+ else
61
+ orm
62
+ end
63
+ end
64
+
65
+ def configure
66
+ yield self
67
+ end
68
+ end
69
+ end
data/snfoil.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/snfoil/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'snfoil'
7
+ spec.version = SnFoil::VERSION
8
+ spec.authors = ['Matthew Howes', 'Danny Murphy', 'Cliff Campbell']
9
+ spec.email = ['howeszy@gmail.com', 'dmurph24@gmail.com', 'cliffcampbell@hey.com']
10
+
11
+ spec.summary = 'A Toolbox of Context Behaviors'
12
+ spec.description = 'A collection of SnFoil gems and additional helper classes'
13
+ spec.homepage = 'https://github.com/limited-effort/snfoil'
14
+ spec.license = 'Apache-2.0'
15
+ spec.required_ruby_version = '>= 2.7'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = spec.homepage
19
+ spec.metadata['changelog_uri'] = 'https://github.com/limited-effort/snfoil/blob/main/CHANGELOG.md'
20
+ spec.metadata['rubygems_mfa_required'] = 'true'
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ ignore_list = %r{\A(?:test/|spec/|bin/|features/|Rakefile|\.\w)}
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) { `git ls-files -z`.split("\x0").reject { |f| f.match(ignore_list) } }
26
+
27
+ spec.bindir = 'exe'
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ['lib']
30
+
31
+ spec.add_dependency 'activesupport', '>= 5.2.6'
32
+ spec.add_dependency 'logger', '~> 1.0'
33
+ spec.add_dependency 'pundit', '~> 2.0'
34
+ spec.add_dependency 'snfoil-context', '~> 1.0'
35
+ spec.add_dependency 'snfoil-policy', '~> 1.0'
36
+ spec.add_dependency 'snfoil-searcher', '~> 1.0'
37
+
38
+ spec.add_development_dependency 'bundle-audit', '~> 0.1.0'
39
+ spec.add_development_dependency 'dry-struct', '~> 1.0'
40
+ spec.add_development_dependency 'fasterer', '~> 0.10.0'
41
+ spec.add_development_dependency 'pry-byebug', '~> 3.9'
42
+ spec.add_development_dependency 'rake', '~> 13.0'
43
+ spec.add_development_dependency 'rspec', '~> 3.9'
44
+ spec.add_development_dependency 'rubocop', '~> 1.29'
45
+ spec.add_development_dependency 'rubocop-performance', '~> 1.11'
46
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.4'
47
+ end