snfoil-controller 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +201 -0
- data/README.md +537 -0
- data/lib/snfoil/controller/version.rb +21 -0
- data/lib/snfoil/controller.rb +153 -0
- data/lib/snfoil/deserializer/base.rb +128 -0
- data/lib/snfoil/deserializer/json.rb +98 -0
- data/lib/snfoil/deserializer/jsonapi.rb +116 -0
- data/snfoil-controller.gemspec +44 -0
- metadata +228 -0
@@ -0,0 +1,128 @@
|
|
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 'active_support/core_ext/string/inflections'
|
19
|
+
|
20
|
+
module SnFoil
|
21
|
+
module Deserializer
|
22
|
+
# ActiveSupport::Concern for base deserializer functionality
|
23
|
+
# Add the following class methods:
|
24
|
+
# * attribute
|
25
|
+
# * attributes
|
26
|
+
# * belongs_to
|
27
|
+
# * has_many
|
28
|
+
# * has_one
|
29
|
+
# * key_transform
|
30
|
+
#
|
31
|
+
# @author Matthew Howes
|
32
|
+
#
|
33
|
+
# @since 0.1.0
|
34
|
+
module Base
|
35
|
+
extend ActiveSupport::Concern
|
36
|
+
|
37
|
+
class_methods do
|
38
|
+
attr_reader :snfoil_attribute_transforms,
|
39
|
+
:snfoil_key_transform
|
40
|
+
|
41
|
+
def key_transform(transform = nil, &block)
|
42
|
+
@snfoil_key_transform = transform || block
|
43
|
+
end
|
44
|
+
|
45
|
+
def attribute(key, **options, &block)
|
46
|
+
(@snfoil_attribute_transforms ||= {})[key] = options.merge(transform_type: :attribute, block: block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def attributes(*fields, **options, &block)
|
50
|
+
fields.each { |field| attribute(field, **options, &block) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def belongs_to(key, deserializer:, **options, &block)
|
54
|
+
(@snfoil_attribute_transforms ||= {})[key] = options.merge(deserializer: deserializer, transform_type: :has_one, block: block)
|
55
|
+
end
|
56
|
+
alias_method :has_one, :belongs_to
|
57
|
+
|
58
|
+
def has_many(key, deserializer:, **options, &block) # rubocop:disable Naming/PredicateName
|
59
|
+
(@snfoil_attribute_transforms ||= {})[key] = options.merge(deserializer: deserializer, transform_type: :has_many, block: block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def inherited(subclass)
|
63
|
+
super
|
64
|
+
|
65
|
+
instance_variables.grep(/@snfoil_.+/).each do |i|
|
66
|
+
subclass.instance_variable_set(i, instance_variable_get(i).dup)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
included do
|
72
|
+
attr_reader :data, :config
|
73
|
+
|
74
|
+
def initialize(input, **config)
|
75
|
+
@data = normalize_keys(input)
|
76
|
+
@config = config
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse
|
80
|
+
raise '#parse not implemented'
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_hash
|
84
|
+
parse
|
85
|
+
end
|
86
|
+
|
87
|
+
alias_method :to_hash, :parse
|
88
|
+
alias_method :to_h, :parse
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def normalize_keys(input)
|
94
|
+
input = input.transform_keys do |key|
|
95
|
+
apply_key_normalize(key)
|
96
|
+
end
|
97
|
+
|
98
|
+
input.transform_values do |value|
|
99
|
+
check_deep_keys(value)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def check_deep_keys(value)
|
104
|
+
case value
|
105
|
+
when Hash
|
106
|
+
normalize_keys(value)
|
107
|
+
when Array
|
108
|
+
value.map { |v| check_deep_keys(v) }
|
109
|
+
else
|
110
|
+
value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def apply_key_normalize(key)
|
115
|
+
@snfoil_key_transform ||= self.class.snfoil_key_transform ||
|
116
|
+
:underscore
|
117
|
+
case @snfoil_key_transform
|
118
|
+
when Symbol
|
119
|
+
key.to_s.send(@snfoil_key_transform)
|
120
|
+
when Proc
|
121
|
+
@snfoil_key_transform.call(key.to_s)
|
122
|
+
else
|
123
|
+
key
|
124
|
+
end.to_sym
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,98 @@
|
|
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 'base'
|
19
|
+
|
20
|
+
module SnFoil
|
21
|
+
module Deserializer
|
22
|
+
# ActiveSupport::Concern for JSON deserializer functionality
|
23
|
+
# Initialize class with json payload and call #parse to output normalized hash
|
24
|
+
#
|
25
|
+
# @author Matthew Howes
|
26
|
+
#
|
27
|
+
# @since 0.1.0
|
28
|
+
module JSON
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
included do # rubocop:disable Metrics/BlockLength reason: These methods need to be in included to be overridable
|
32
|
+
include SnFoil::Deserializer::Base
|
33
|
+
|
34
|
+
def parse
|
35
|
+
apply_transforms({}, data)
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def apply_transforms(output, input)
|
41
|
+
(self.class.snfoil_attribute_transforms || {}).reduce(output) do |transformed_output, transform|
|
42
|
+
apply_transform(transformed_output, input, transform[0], **transform[1])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def apply_transform(output, input, key, **options)
|
47
|
+
case options[:transform_type]
|
48
|
+
when :attribute
|
49
|
+
parse_attribute_transform(output, input, key, **options)
|
50
|
+
when :has_one
|
51
|
+
parse_has_one_transform(output, input, key, **options)
|
52
|
+
when :has_many
|
53
|
+
parse_has_many_transform(output, input, key, **options)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_attribute_transform(output, input, key, **options)
|
58
|
+
value = find_attribute(input, key, **options)
|
59
|
+
return output unless value
|
60
|
+
|
61
|
+
output.merge key => value
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_has_one_transform(output, input, key, deserializer:, **options)
|
65
|
+
resource_data = find_attribute(input, key, **options)
|
66
|
+
return output unless resource_data
|
67
|
+
|
68
|
+
output[key] = deserializer.new(resource_data, **options).parse
|
69
|
+
output
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_has_many_transform(output, input, key, deserializer:, **options)
|
73
|
+
array_data = find_attribute(input, key, **options)
|
74
|
+
return output unless array_data
|
75
|
+
|
76
|
+
array_data = [array_data] if array_data.is_a? Hash
|
77
|
+
output[key] = array_data.map { |r| deserializer.new(r, **options).parse }
|
78
|
+
output
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_attribute(input, key, block: nil, with: nil, **options)
|
82
|
+
return unless input
|
83
|
+
|
84
|
+
if block
|
85
|
+
instance_exec(input, key, **options, &block)
|
86
|
+
elsif with
|
87
|
+
send(with, input, key, **options)
|
88
|
+
else
|
89
|
+
value_key = options.fetch(:key) { key }
|
90
|
+
value_key = "#{options[:prefix]}#{key}".to_sym if options[:prefix]
|
91
|
+
|
92
|
+
input[value_key.to_sym]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,116 @@
|
|
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 'json'
|
19
|
+
|
20
|
+
module SnFoil
|
21
|
+
module Deserializer
|
22
|
+
# ActiveSupport::Concern for JSONAPI deserializer functionality
|
23
|
+
# Initialize class with jsonapi payload and call #parse to output normalized hash
|
24
|
+
#
|
25
|
+
# @author Matthew Howes
|
26
|
+
#
|
27
|
+
# @since 0.1.0
|
28
|
+
module JSONAPI
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
included do # rubocop:disable Metrics/BlockLength reason: These methods need to be in included to be overridable
|
32
|
+
include SnFoil::Deserializer::JSON
|
33
|
+
|
34
|
+
module_eval do
|
35
|
+
def parse
|
36
|
+
input = data[:data] || data
|
37
|
+
return apply_transforms(data_id({}, input), input) unless input.is_a? Array
|
38
|
+
|
39
|
+
input.map { |d| apply_transforms(data_id({}, d), d) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def included
|
44
|
+
@included ||= config[:included] || data[:included]
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def data_id(output, data)
|
50
|
+
if data[:id]
|
51
|
+
output[:id] = data[:id]
|
52
|
+
elsif data[:'local:id']
|
53
|
+
output[:'local:id'] = data[:'local:id']
|
54
|
+
end
|
55
|
+
|
56
|
+
output
|
57
|
+
end
|
58
|
+
|
59
|
+
def parse_attribute_transform(output, input, key, **options)
|
60
|
+
value = find_attribute(input[:attributes], key, **options)
|
61
|
+
return output unless value
|
62
|
+
|
63
|
+
output.merge key => value
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_has_one_transform(output, input, key, deserializer:, **options)
|
67
|
+
resource_data = find_relationship(input, key, **options)
|
68
|
+
return output unless resource_data
|
69
|
+
|
70
|
+
output[key] = deserializer.new(resource_data, **options, included: included).parse
|
71
|
+
output
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_has_many_transform(output, input, key, deserializer:, **options)
|
75
|
+
resource_data = find_relationships(input, key, **options)
|
76
|
+
return output unless resource_data
|
77
|
+
|
78
|
+
output[key] = resource_data.map { |r| deserializer.new(r, **options, included: included).parse }
|
79
|
+
output
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_relationships(input, key, **options)
|
83
|
+
array_data = find_attribute(input[:relationships], key, **options)
|
84
|
+
return unless array_data
|
85
|
+
|
86
|
+
array_data = array_data[:data]
|
87
|
+
array_data = [array_data] unless array_data.is_a? Array
|
88
|
+
array_data.map do |resource_data|
|
89
|
+
lookup_relationship(**resource_data) || resource_data
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_relationship(input, key, **options)
|
94
|
+
resource_data = find_attribute(input[:relationships], key, **options)
|
95
|
+
return unless resource_data
|
96
|
+
|
97
|
+
lookup_relationship(**resource_data[:data]) || resource_data
|
98
|
+
end
|
99
|
+
|
100
|
+
def lookup_relationship(type:, **options)
|
101
|
+
id = options[:id]
|
102
|
+
lid = options[:'local:id']
|
103
|
+
|
104
|
+
included&.find do |x|
|
105
|
+
x[:type].eql?(type) &&
|
106
|
+
if id
|
107
|
+
x[:id].eql?(id)
|
108
|
+
elsif lid
|
109
|
+
x[:'local:id'].eql?(lid)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/snfoil/controller/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'snfoil-controller'
|
7
|
+
spec.version = SnFoil::Controller::VERSION
|
8
|
+
spec.authors = ['Matthew Howes', 'Cliff Campbell']
|
9
|
+
spec.email = ['howeszy@gmail.com', 'cliffcampbell@hey.com']
|
10
|
+
|
11
|
+
spec.summary = 'Seperate Display Logic from Business Logic'
|
12
|
+
spec.description = 'A context-like experience for your controllers'
|
13
|
+
spec.homepage = 'https://github.com/limited-effort/snfoil-controller'
|
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-controller/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 'jsonapi-serializer', '~> 2.2'
|
33
|
+
spec.add_dependency 'snfoil-context', '~> 1.0'
|
34
|
+
|
35
|
+
spec.add_development_dependency 'bundle-audit', '~> 0.1.0'
|
36
|
+
spec.add_development_dependency 'fasterer', '~> 0.10.0'
|
37
|
+
spec.add_development_dependency 'oj'
|
38
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.9'
|
39
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
40
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
41
|
+
spec.add_development_dependency 'rubocop', '1.29'
|
42
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.11'
|
43
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.5'
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: snfoil-controller
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Howes
|
8
|
+
- Cliff Campbell
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-05-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 5.2.6
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 5.2.6
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: jsonapi-serializer
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '2.2'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '2.2'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: snfoil-context
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: bundle-audit
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.1.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.1.0
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: fasterer
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.10.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.10.0
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: oj
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: pry-byebug
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '3.9'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '3.9'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rake
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '13.0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '13.0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rspec
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '3.10'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '3.10'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: rubocop
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - '='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '1.29'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - '='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '1.29'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rubocop-performance
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '1.11'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '1.11'
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rubocop-rspec
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '2.5'
|
175
|
+
type: :development
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - "~>"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '2.5'
|
182
|
+
description: A context-like experience for your controllers
|
183
|
+
email:
|
184
|
+
- howeszy@gmail.com
|
185
|
+
- cliffcampbell@hey.com
|
186
|
+
executables: []
|
187
|
+
extensions: []
|
188
|
+
extra_rdoc_files: []
|
189
|
+
files:
|
190
|
+
- CHANGELOG.md
|
191
|
+
- CODE_OF_CONDUCT.md
|
192
|
+
- Gemfile
|
193
|
+
- LICENSE.txt
|
194
|
+
- README.md
|
195
|
+
- lib/snfoil/controller.rb
|
196
|
+
- lib/snfoil/controller/version.rb
|
197
|
+
- lib/snfoil/deserializer/base.rb
|
198
|
+
- lib/snfoil/deserializer/json.rb
|
199
|
+
- lib/snfoil/deserializer/jsonapi.rb
|
200
|
+
- snfoil-controller.gemspec
|
201
|
+
homepage: https://github.com/limited-effort/snfoil-controller
|
202
|
+
licenses:
|
203
|
+
- Apache-2.0
|
204
|
+
metadata:
|
205
|
+
homepage_uri: https://github.com/limited-effort/snfoil-controller
|
206
|
+
source_code_uri: https://github.com/limited-effort/snfoil-controller
|
207
|
+
changelog_uri: https://github.com/limited-effort/snfoil-controller/blob/main/CHANGELOG.md
|
208
|
+
rubygems_mfa_required: 'true'
|
209
|
+
post_install_message:
|
210
|
+
rdoc_options: []
|
211
|
+
require_paths:
|
212
|
+
- lib
|
213
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
214
|
+
requirements:
|
215
|
+
- - ">="
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '2.7'
|
218
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
requirements: []
|
224
|
+
rubygems_version: 3.1.6
|
225
|
+
signing_key:
|
226
|
+
specification_version: 4
|
227
|
+
summary: Seperate Display Logic from Business Logic
|
228
|
+
test_files: []
|