re_sorcery 0.1.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/.gitignore +8 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +21 -0
- data/README.md +120 -0
- data/Rakefile +10 -0
- data/bin/console +98 -0
- data/bin/setup +8 -0
- data/lib/re_sorcery/arg_check.rb +14 -0
- data/lib/re_sorcery/configuration.rb +54 -0
- data/lib/re_sorcery/decoder/builtin_decoders.rb +124 -0
- data/lib/re_sorcery/decoder.rb +126 -0
- data/lib/re_sorcery/error.rb +33 -0
- data/lib/re_sorcery/fielded/expand_internal_fields.rb +49 -0
- data/lib/re_sorcery/fielded.rb +52 -0
- data/lib/re_sorcery/helpers.rb +29 -0
- data/lib/re_sorcery/linked/link_class_factory.rb +62 -0
- data/lib/re_sorcery/linked.rb +73 -0
- data/lib/re_sorcery/maybe/just.rb +50 -0
- data/lib/re_sorcery/maybe/nothing.rb +41 -0
- data/lib/re_sorcery/maybe.rb +6 -0
- data/lib/re_sorcery/result/err.rb +46 -0
- data/lib/re_sorcery/result/ok.rb +49 -0
- data/lib/re_sorcery/result.rb +9 -0
- data/lib/re_sorcery/version.rb +5 -0
- data/lib/re_sorcery.rb +40 -0
- data/re_sorcery.gemspec +34 -0
- metadata +128 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Fielded
|
5
|
+
module ExpandInternalFields
|
6
|
+
extend Helpers
|
7
|
+
|
8
|
+
# Used internally to expand deeply nested `Fielded` structures
|
9
|
+
#
|
10
|
+
# `Hash` is intentionally *not* expanded. Create a `Fielded` class instead.
|
11
|
+
#
|
12
|
+
# Similarly, `nil` is intentionally rejected here. Use a type that more
|
13
|
+
# meaningfully represents an empty value instead.
|
14
|
+
def self.expand(obj)
|
15
|
+
case obj
|
16
|
+
when ReSorcery
|
17
|
+
obj.resource
|
18
|
+
when Fielded
|
19
|
+
obj.fields
|
20
|
+
when Linked
|
21
|
+
obj.links
|
22
|
+
when String, Numeric, Symbol, TrueClass, FalseClass
|
23
|
+
ok(obj)
|
24
|
+
when Array
|
25
|
+
expand_for_array(obj)
|
26
|
+
when URI
|
27
|
+
ok(obj.to_s)
|
28
|
+
when Hash
|
29
|
+
err("`Hash` cannot be safely expanded as a `field`. Use a `Fielded` class instead.")
|
30
|
+
when NilClass
|
31
|
+
err("`nil` cannot be returned as a `field`")
|
32
|
+
else
|
33
|
+
err("Cannot deeply expand fields of class #{obj.class}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.expand_for_array(array)
|
38
|
+
array.each_with_index.inject(ok([])) do |result_array, (element, index)|
|
39
|
+
result_array.and_then do |ok_array|
|
40
|
+
expand(element)
|
41
|
+
.map { |good| ok_array << good }
|
42
|
+
.map_error { |error| "Error at index `#{index}` of Array: #{error}" }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
private_constant :ExpandInternalFields
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 're_sorcery/fielded/expand_internal_fields'
|
4
|
+
|
5
|
+
module ReSorcery
|
6
|
+
module Fielded
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
include Decoder::BuiltinDecoders
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Set a field for instances of a class
|
15
|
+
#
|
16
|
+
# There is intentionally no way to make fields optionally nil. Use a type
|
17
|
+
# that more meaningfully represents an empty value instead, such as a
|
18
|
+
# `Maybe` type or discriminated unions.
|
19
|
+
#
|
20
|
+
# @param [Symbol] name
|
21
|
+
# @param [arg of Decoder.is] type @see `ReSorcery::Decoder.is` for details
|
22
|
+
# @param [Proc] pro: in the context of an instance of the class, return the value of the field
|
23
|
+
def field(name, type, pro = -> { send(name) })
|
24
|
+
ArgCheck['name', name, Symbol]
|
25
|
+
ArgCheck['pro', pro, Proc]
|
26
|
+
|
27
|
+
(@fields ||= {})[name] = { type: is(type), pro: pro }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.included(base)
|
32
|
+
base.extend(ClassMethods)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the `Decoder#test`ed fields of the object, wrapped in a `Result`
|
36
|
+
#
|
37
|
+
# If all the `Decoder`s pass, this will return an `Ok`. If any of them
|
38
|
+
# fail, it will return an `Err` instead.
|
39
|
+
#
|
40
|
+
# @return [Result<String, Hash>]
|
41
|
+
def fields
|
42
|
+
self.class.instance_exec { @fields ||= [] }.inject(ok({})) do |result_hash, (name, field_hash)|
|
43
|
+
result_hash.and_then do |ok_hash|
|
44
|
+
field_hash[:type].test(instance_exec(&field_hash[:pro]))
|
45
|
+
.and_then { |tested| ExpandInternalFields.expand(tested) }
|
46
|
+
.map { |fielded| ok_hash.merge(name => fielded) }
|
47
|
+
.map_error { |error| "Error at field `#{name}` of `#{self.class}`: #{error}" }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ReSorcery
|
2
|
+
module Helpers
|
3
|
+
private
|
4
|
+
|
5
|
+
def just(value)
|
6
|
+
Maybe::Just.new(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def nothing
|
10
|
+
Maybe::Nothing.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Wrap a possibly-nil value in a `Maybe`
|
14
|
+
#
|
15
|
+
# @param value The value to wrap in a `Maybe`.
|
16
|
+
# @return [Maybe]
|
17
|
+
def nillable(value)
|
18
|
+
value.nil? ? nothing : just(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ok(value)
|
22
|
+
Result::Ok.new(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def err(e)
|
26
|
+
Result::Err.new(e)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Linked
|
5
|
+
class LinkClassFactory
|
6
|
+
extend Decoder::BuiltinDecoders
|
7
|
+
|
8
|
+
def self.valid_rels
|
9
|
+
ReSorcery.configuration.fetch(
|
10
|
+
:link_rels,
|
11
|
+
%w[
|
12
|
+
self
|
13
|
+
create
|
14
|
+
update
|
15
|
+
destroy
|
16
|
+
],
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.valid_methods
|
21
|
+
ReSorcery.configuration.fetch(
|
22
|
+
:link_methods,
|
23
|
+
%w[
|
24
|
+
get
|
25
|
+
post
|
26
|
+
patch
|
27
|
+
put
|
28
|
+
delete
|
29
|
+
],
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
URI_ABLE = is(String, URI).and do |s|
|
34
|
+
next true if s.is_a?(URI)
|
35
|
+
|
36
|
+
begin
|
37
|
+
ok(URI.parse(s))
|
38
|
+
rescue URI::InvalidURIError
|
39
|
+
err("Not a valid URI: #{s}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.make_link_class
|
44
|
+
default_method = valid_methods.first
|
45
|
+
this = self
|
46
|
+
|
47
|
+
Class.new do
|
48
|
+
include Fielded
|
49
|
+
|
50
|
+
def initialize(args)
|
51
|
+
@args = args
|
52
|
+
end
|
53
|
+
|
54
|
+
field :rel, is(*this.valid_rels), -> { @args[:rel] }
|
55
|
+
field :href, URI_ABLE, -> { @args[:href] }
|
56
|
+
field :method, is(*this.valid_methods), -> { @args.fetch(:method, default_method) }
|
57
|
+
field :type, String, -> { @args.fetch(:type, 'application/json') }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 're_sorcery/linked/link_class_factory'
|
4
|
+
|
5
|
+
module ReSorcery
|
6
|
+
module Linked
|
7
|
+
include Helpers
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
private
|
11
|
+
|
12
|
+
# Define a set of `Link`s for a class
|
13
|
+
#
|
14
|
+
# The block is evaluated in the context of an instance of the class, so
|
15
|
+
# the set of `Link`s can be contextualized. For example, if the current
|
16
|
+
# user doesn't have permissions to edit the object, the "update" `Link`
|
17
|
+
# can be left out:
|
18
|
+
#
|
19
|
+
# class MyObject
|
20
|
+
# include Linked
|
21
|
+
# attr_reader :id, :current_user
|
22
|
+
#
|
23
|
+
# def initialize(id, current_user)
|
24
|
+
# @id = id
|
25
|
+
# @current_user = current_user
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# links do
|
29
|
+
# link 'self', "/my_objects/#{id}"
|
30
|
+
# link 'update', "/my_objects/#{id}", 'put' if current_user.can_update?(self)
|
31
|
+
# link 'destroy', "/my_objects/#{id}", 'delete' if current_user.can_destroy?(self)
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# The result of calling the block is not cached.
|
36
|
+
def links(&block)
|
37
|
+
@links_proc = block
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.included(base)
|
42
|
+
base.extend(ClassMethods)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.link_class
|
46
|
+
@link_class ||= LinkClassFactory.make_link_class
|
47
|
+
end
|
48
|
+
|
49
|
+
def links
|
50
|
+
instance_exec(&self.class.instance_exec { @links_proc ||= -> {} })
|
51
|
+
created_links = (@_created_links ||= [])
|
52
|
+
@_created_links = [] # Clear out so `links` can run cleanly next time
|
53
|
+
|
54
|
+
created_links.each_with_index.inject(ok([])) do |result_array, (link_result, index)|
|
55
|
+
result_array.and_then do |ok_array|
|
56
|
+
link_result
|
57
|
+
.map { |link| ok_array << link }
|
58
|
+
.map_error { |error| "Error with Link at index #{index}: #{error}" }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# Define a `Link` for an object
|
66
|
+
#
|
67
|
+
# @see `ReSorcery::Linked::Link#initialize` for param types
|
68
|
+
def link(rel, href, method = 'get', type = 'application/json')
|
69
|
+
klass = Linked.link_class
|
70
|
+
(@_created_links ||= []) << klass.new(rel: rel, href: href, method: method, type: type).fields
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Maybe
|
5
|
+
class Just
|
6
|
+
include Fielded
|
7
|
+
|
8
|
+
field :kind, :just, -> { :just }
|
9
|
+
field :value, Decoder.new { true }, -> { @value }
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def and_then(&block)
|
16
|
+
ArgCheck['block', block.call(@value), Just, Nothing]
|
17
|
+
end
|
18
|
+
|
19
|
+
def map(&block)
|
20
|
+
Just.new(block.call(@value))
|
21
|
+
end
|
22
|
+
|
23
|
+
def or_else
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_or_else
|
28
|
+
@value
|
29
|
+
end
|
30
|
+
|
31
|
+
def assign(name, &block)
|
32
|
+
raise Error::NonHashAssignError, @value unless @value.is_a?(Hash)
|
33
|
+
|
34
|
+
ArgCheck['block', block.call(@value), Just, Nothing]
|
35
|
+
.map { |k| @value.merge(name => k) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(other)
|
39
|
+
other.class == Just && other.instance_eval { @value } == @value
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_json(*)
|
43
|
+
{
|
44
|
+
kind: :just,
|
45
|
+
value: @value,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Maybe
|
5
|
+
class Nothing
|
6
|
+
include Fielded
|
7
|
+
|
8
|
+
field :kind, :nothing, -> { :nothing }
|
9
|
+
|
10
|
+
def and_then
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def map
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def or_else(&block)
|
19
|
+
ArgCheck['block', block.call, Just, Nothing]
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_or_else(&block)
|
23
|
+
block.call
|
24
|
+
end
|
25
|
+
|
26
|
+
def assign(_name)
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
other.class == Nothing
|
32
|
+
end
|
33
|
+
|
34
|
+
def as_json(*)
|
35
|
+
{
|
36
|
+
kind: :nothing,
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Result
|
5
|
+
class Err
|
6
|
+
def initialize(err)
|
7
|
+
@err = err
|
8
|
+
end
|
9
|
+
|
10
|
+
def and_then
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def map
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def map_error(&block)
|
19
|
+
Err.new(block.call(@err))
|
20
|
+
end
|
21
|
+
|
22
|
+
def or_else(&block)
|
23
|
+
ArgCheck['block', block.call(@err), Ok, Err]
|
24
|
+
end
|
25
|
+
|
26
|
+
def assign(_name)
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def cata(ok:, err:)
|
31
|
+
err.call(@err)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ==(other)
|
35
|
+
other.class == Err && other.instance_eval { @err } == @err
|
36
|
+
end
|
37
|
+
|
38
|
+
def as_json(*)
|
39
|
+
{
|
40
|
+
kind: :err,
|
41
|
+
value: @err,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ReSorcery
|
4
|
+
module Result
|
5
|
+
class Ok
|
6
|
+
def initialize(value)
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def and_then(&block)
|
11
|
+
ArgCheck['block', block.call(@value), Ok, Err]
|
12
|
+
end
|
13
|
+
|
14
|
+
def map(&block)
|
15
|
+
Ok.new(block.call(@value))
|
16
|
+
end
|
17
|
+
|
18
|
+
def map_error
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def or_else
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def assign(name, &block)
|
27
|
+
raise Error::NonHashAssignError, @value unless @value.is_a?(Hash)
|
28
|
+
|
29
|
+
ArgCheck['block', block.call(@value), Ok, Err]
|
30
|
+
.map { |k| @value.merge(name => k) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def cata(ok:, err:)
|
34
|
+
ok.call(@value)
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
other.class == Ok && other.instance_eval { @value } == @value
|
39
|
+
end
|
40
|
+
|
41
|
+
def as_json(*)
|
42
|
+
{
|
43
|
+
kind: :ok,
|
44
|
+
value: @value,
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/re_sorcery.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 're_sorcery/version'
|
4
|
+
require 're_sorcery/error'
|
5
|
+
require 're_sorcery/arg_check'
|
6
|
+
require 're_sorcery/maybe'
|
7
|
+
require 're_sorcery/result'
|
8
|
+
require 're_sorcery/helpers'
|
9
|
+
require 're_sorcery/decoder'
|
10
|
+
require 're_sorcery/fielded'
|
11
|
+
require 're_sorcery/maybe/just'
|
12
|
+
require 're_sorcery/maybe/nothing'
|
13
|
+
require 're_sorcery/linked'
|
14
|
+
require 're_sorcery/configuration'
|
15
|
+
|
16
|
+
module ReSorcery
|
17
|
+
include Fielded
|
18
|
+
include Linked
|
19
|
+
include Helpers
|
20
|
+
extend Configuration
|
21
|
+
|
22
|
+
def self.included(base)
|
23
|
+
base.extend Fielded::ClassMethods
|
24
|
+
base.extend Linked::ClassMethods
|
25
|
+
@configured = "included at #{caller_locations.first}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource
|
29
|
+
Result::Ok.new({})
|
30
|
+
.assign(:payload) { fields }
|
31
|
+
.assign(:links) { links }
|
32
|
+
end
|
33
|
+
|
34
|
+
def as_json(*)
|
35
|
+
resource.cata(
|
36
|
+
ok: ->(r) { r },
|
37
|
+
err: ->(e) { raise Error::InvalidResourceError, e },
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
data/re_sorcery.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "re_sorcery/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "re_sorcery"
|
7
|
+
spec.version = ReSorcery::VERSION
|
8
|
+
spec.authors = ["Spencer Christiansen"]
|
9
|
+
spec.email = ["jc.spencer92@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Create resources with run-time payload type checking and link validation"
|
12
|
+
spec.homepage = "https://github.com/spejamchr/re_sorcery"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
19
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
31
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
32
|
+
spec.add_development_dependency "pry"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: re_sorcery
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Spencer Christiansen
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- jc.spencer92@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- lib/re_sorcery.rb
|
86
|
+
- lib/re_sorcery/arg_check.rb
|
87
|
+
- lib/re_sorcery/configuration.rb
|
88
|
+
- lib/re_sorcery/decoder.rb
|
89
|
+
- lib/re_sorcery/decoder/builtin_decoders.rb
|
90
|
+
- lib/re_sorcery/error.rb
|
91
|
+
- lib/re_sorcery/fielded.rb
|
92
|
+
- lib/re_sorcery/fielded/expand_internal_fields.rb
|
93
|
+
- lib/re_sorcery/helpers.rb
|
94
|
+
- lib/re_sorcery/linked.rb
|
95
|
+
- lib/re_sorcery/linked/link_class_factory.rb
|
96
|
+
- lib/re_sorcery/maybe.rb
|
97
|
+
- lib/re_sorcery/maybe/just.rb
|
98
|
+
- lib/re_sorcery/maybe/nothing.rb
|
99
|
+
- lib/re_sorcery/result.rb
|
100
|
+
- lib/re_sorcery/result/err.rb
|
101
|
+
- lib/re_sorcery/result/ok.rb
|
102
|
+
- lib/re_sorcery/version.rb
|
103
|
+
- re_sorcery.gemspec
|
104
|
+
homepage: https://github.com/spejamchr/re_sorcery
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata:
|
108
|
+
homepage_uri: https://github.com/spejamchr/re_sorcery
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubygems_version: 3.0.3.1
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Create resources with run-time payload type checking and link validation
|
128
|
+
test_files: []
|