taksi 0.2.1 → 0.2.3
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 +4 -4
- data/README.md +8 -4
- data/lib/taksi/component.rb +12 -1
- data/lib/taksi/components/field.rb +35 -13
- data/lib/taksi/components/skeleton.rb +8 -1
- data/lib/taksi/interface.rb +9 -1
- data/lib/taksi/registry.rb +8 -2
- data/lib/taksi/values/dynamic.rb +2 -9
- data/lib/taksi/version.rb +1 -1
- data/lib/taksi.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bf8909dd9e8de12aa8fe7a7f93fcf3a414f8c8bc850bea7ff032bfcfd150d3e
|
|
4
|
+
data.tar.gz: 02ac2b0dccafc25969a9fc861a88bbaba468b932c014fe898c14e31f42db177d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38cc7864f7dc6435e1b48d21f9f1d65b5f4d8ebb06c509d1101742d79e494f8b164fe0c133e873fd52f38570da9c21fd20c2e9ee632330a4f6e39777d70d3350
|
|
7
|
+
data.tar.gz: c9c0521ad137a949a57686e773eb04aedce5cefcf95e0bf79fe4fa05b89c4ef5f921c6596ec25ce6687bdaf7897b4e82372af84378139bbe5f224a14f51767f0
|
data/README.md
CHANGED
|
@@ -22,11 +22,13 @@ class Components::Users::ProfileResume
|
|
|
22
22
|
include Taksi::Component.new('users/profile_resume')
|
|
23
23
|
|
|
24
24
|
content do
|
|
25
|
-
|
|
25
|
+
static :profile_kind, 'resume' # same as `field :profile_kind, Taksi::Static`
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
dynamic :name
|
|
28
|
+
|
|
29
|
+
field :details do
|
|
30
|
+
field :age Taksi::Dynamic # same as `dynamic :age`
|
|
31
|
+
field :email Taksi::Dynamic
|
|
30
32
|
end
|
|
31
33
|
end
|
|
32
34
|
end
|
|
@@ -69,8 +71,10 @@ Which provide us:
|
|
|
69
71
|
{
|
|
70
72
|
"name": "users/profile_resume",
|
|
71
73
|
"identifier": "component$0",
|
|
74
|
+
"requires_data": true,
|
|
72
75
|
"content": {
|
|
73
76
|
"name": null,
|
|
77
|
+
"profile_kind": "resume",
|
|
74
78
|
"details": {
|
|
75
79
|
"age": null,
|
|
76
80
|
"email": null
|
data/lib/taksi/component.rb
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Taksi
|
|
4
|
+
# A custom module to turn a class into a component on taksi protocol
|
|
5
|
+
#
|
|
6
|
+
# ```ruby
|
|
7
|
+
# class CustomComponent
|
|
8
|
+
# include Taksi::Component.new('customs/component_name')
|
|
9
|
+
#
|
|
10
|
+
# content do
|
|
11
|
+
# field_name Taksi::Static
|
|
12
|
+
# end
|
|
13
|
+
# end
|
|
14
|
+
# ```
|
|
15
|
+
#
|
|
4
16
|
class Component < ::Module
|
|
5
17
|
attr_reader :identifier
|
|
6
18
|
|
|
@@ -61,7 +73,6 @@ module Taksi
|
|
|
61
73
|
def load_data_from_key_to_object(data, field, obj)
|
|
62
74
|
splitted_full_path = field.key.to_s.split('.')
|
|
63
75
|
setter_key = splitted_full_path.pop
|
|
64
|
-
splitted_full_path.shift # remove content root key, as it makes no sense in data object
|
|
65
76
|
|
|
66
77
|
relative_object = splitted_full_path.reduce(obj) do |memo, path_part|
|
|
67
78
|
memo[path_part.to_sym] ||= {}
|
|
@@ -10,35 +10,45 @@ module Taksi
|
|
|
10
10
|
@name = name.to_sym
|
|
11
11
|
@parent = parent
|
|
12
12
|
|
|
13
|
+
raise <<~MESSAGE unless args.size.positive? || block_given?
|
|
14
|
+
You must provide a value or a block definition to build field
|
|
15
|
+
MESSAGE
|
|
16
|
+
|
|
13
17
|
@value = args.shift.new(skeleton, name, *args) if args.size.positive?
|
|
14
18
|
@nested_fields = []
|
|
15
19
|
|
|
16
20
|
instance_exec(&block) if block_given?
|
|
17
|
-
@defined = true
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def key
|
|
21
24
|
return name if parent.nil? || parent.root?
|
|
22
25
|
|
|
23
|
-
"#{parent.
|
|
26
|
+
"#{parent.key}.#{name}"
|
|
24
27
|
end
|
|
25
28
|
|
|
29
|
+
# Fetches the data for in `data` for the current field
|
|
30
|
+
# @return any
|
|
26
31
|
def fetch_from(data)
|
|
27
|
-
return value.as_json if value
|
|
32
|
+
return value.as_json if value&.static?
|
|
28
33
|
|
|
29
|
-
return data
|
|
34
|
+
return data.fetch(name) if parent.nil? || parent.root?
|
|
30
35
|
|
|
31
|
-
parent.fetch_from(data)
|
|
32
|
-
rescue
|
|
33
|
-
raise
|
|
36
|
+
parent.fetch_from(data).fetch(name)
|
|
37
|
+
rescue ::KeyError
|
|
38
|
+
raise ::KeyError, "Couldn't fetch #{key.inspect} from data: #{data.inspect}"
|
|
34
39
|
end
|
|
35
40
|
|
|
41
|
+
# Turns the field into his json representation
|
|
42
|
+
# The returned hash is compatible with the skeleton json specification
|
|
43
|
+
# @return Hash
|
|
36
44
|
def as_json
|
|
37
45
|
return {name => @nested_fields.map(&:as_json).inject({}, &:merge)} if nested?
|
|
38
46
|
|
|
39
47
|
{name => value.as_json}
|
|
40
48
|
end
|
|
41
49
|
|
|
50
|
+
# Builds up a interator over all fields included nested ones
|
|
51
|
+
# @returns Enumerable
|
|
42
52
|
def fields
|
|
43
53
|
Enumerator.new do |yielder|
|
|
44
54
|
@nested_fields.each do |field|
|
|
@@ -59,16 +69,28 @@ module Taksi
|
|
|
59
69
|
@parent.nil?
|
|
60
70
|
end
|
|
61
71
|
|
|
62
|
-
def
|
|
63
|
-
return
|
|
72
|
+
def dynamic?
|
|
73
|
+
return @nested_fields.any?(&:dynamic?) if @value.nil?
|
|
74
|
+
|
|
75
|
+
@value.dynamic?
|
|
76
|
+
end
|
|
64
77
|
|
|
65
|
-
|
|
78
|
+
def field(name, *args, &block)
|
|
79
|
+
self.class.new(skeleton, name, *args, parent: self, &block).tap do |new_field|
|
|
80
|
+
@nested_fields << new_field
|
|
81
|
+
end
|
|
66
82
|
end
|
|
67
83
|
|
|
68
|
-
def
|
|
69
|
-
|
|
84
|
+
def nested(name, &block)
|
|
85
|
+
field(name, &block)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def static(name, value)
|
|
89
|
+
field(name, ::Taksi::Values::Static, value)
|
|
90
|
+
end
|
|
70
91
|
|
|
71
|
-
|
|
92
|
+
def dynamic(name)
|
|
93
|
+
field(name, ::Taksi::Values::Dynamic)
|
|
72
94
|
end
|
|
73
95
|
end
|
|
74
96
|
end
|
|
@@ -9,6 +9,8 @@ module Taksi
|
|
|
9
9
|
@parent = parent
|
|
10
10
|
@name = name
|
|
11
11
|
|
|
12
|
+
raise 'To build a component you need to provide a `content` block' unless block_given?
|
|
13
|
+
|
|
12
14
|
@content = ::Taksi::Components::Field.new(self, :content, &block)
|
|
13
15
|
end
|
|
14
16
|
|
|
@@ -20,10 +22,15 @@ module Taksi
|
|
|
20
22
|
content.fields
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def dynamic?
|
|
26
|
+
@content.dynamic?
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def as_json
|
|
24
30
|
{
|
|
25
31
|
name: name,
|
|
26
|
-
identifier: id
|
|
32
|
+
identifier: id,
|
|
33
|
+
requires_data: dynamic?
|
|
27
34
|
}.tap do |json|
|
|
28
35
|
json.merge!(content.as_json)
|
|
29
36
|
end
|
data/lib/taksi/interface.rb
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Taksi
|
|
4
|
+
# A custom module that turns a class into a interface on taksi protocol
|
|
5
|
+
#
|
|
4
6
|
class Interface < ::Module
|
|
5
7
|
attr_reader :interface_name, :version_pattern, :alternatives
|
|
6
8
|
|
|
9
|
+
# Finds for a interface by its name and the current version
|
|
10
|
+
# @param name [String]
|
|
11
|
+
# @param version [String] just like '0.2.1'
|
|
12
|
+
# @param alternatives: [Array]
|
|
13
|
+
# @raises`::Taksi::Registry::InterfaceNotFoundError`
|
|
14
|
+
# @return Class the class of interface
|
|
7
15
|
def self.find(name, version, alternative: nil)
|
|
8
16
|
::Taksi::Registry.find(name, version, alternative)
|
|
9
17
|
end
|
|
@@ -28,7 +36,7 @@ module Taksi
|
|
|
28
36
|
attr_reader :skeleton
|
|
29
37
|
|
|
30
38
|
def find(version, alternative = nil)
|
|
31
|
-
::Taksi::Registry.find(interface_name, version, alternative)
|
|
39
|
+
::Taksi::Registry.find(@interface_definition.interface_name, version, alternative)
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
def initiate(interface_definition)
|
data/lib/taksi/registry.rb
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'forwardable'
|
|
4
3
|
module Taksi
|
|
5
4
|
class Registry
|
|
6
5
|
include ::Singleton
|
|
7
6
|
|
|
7
|
+
NAME_REGEX = %r{^[a-z\-_/]{1,80}$}i
|
|
8
|
+
|
|
8
9
|
class << self
|
|
9
10
|
extend ::Forwardable
|
|
10
11
|
|
|
@@ -19,6 +20,11 @@ module Taksi
|
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
def add(klass, name)
|
|
23
|
+
unless name.to_s.match?(NAME_REGEX)
|
|
24
|
+
raise StandardError,
|
|
25
|
+
"Invalid interface name '#{name}', it must to match regex '#{NAME_REGEX.inspect}'"
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
sym_name = name.to_sym
|
|
23
29
|
|
|
24
30
|
@interfaces[sym_name] ||= []
|
|
@@ -41,7 +47,7 @@ module Taksi
|
|
|
41
47
|
|
|
42
48
|
next true if alternative.nil?
|
|
43
49
|
|
|
44
|
-
next true if interface.alternatives.
|
|
50
|
+
next true if interface.alternatives.nil?
|
|
45
51
|
|
|
46
52
|
next true if interface.alternatives.include?(alternative)
|
|
47
53
|
|
data/lib/taksi/values/dynamic.rb
CHANGED
|
@@ -3,18 +3,11 @@
|
|
|
3
3
|
module Taksi
|
|
4
4
|
module Values
|
|
5
5
|
class Dynamic
|
|
6
|
-
attr_reader :component, :name
|
|
6
|
+
attr_reader :component, :name
|
|
7
7
|
|
|
8
|
-
def initialize(component, name
|
|
8
|
+
def initialize(component, name)
|
|
9
9
|
@component = component
|
|
10
10
|
@name = name
|
|
11
|
-
@field = field
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def path
|
|
15
|
-
return field if field
|
|
16
|
-
|
|
17
|
-
"#{component.id}.#{name}"
|
|
18
11
|
end
|
|
19
12
|
|
|
20
13
|
def as_json
|
data/lib/taksi/version.rb
CHANGED
data/lib/taksi.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: taksi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Israel Trindade
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-07-
|
|
11
|
+
date: 2023-07-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|