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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c176b6593b9e570169fa5ec6103bfd635c8bae751342ce7b8c986ec3fa43df3d
4
- data.tar.gz: e84fe608e7b15263084b9f3f745eba7e9cf47d8460ecb02032ad930fe85e1c14
3
+ metadata.gz: 2bf8909dd9e8de12aa8fe7a7f93fcf3a414f8c8bc850bea7ff032bfcfd150d3e
4
+ data.tar.gz: 02ac2b0dccafc25969a9fc861a88bbaba468b932c014fe898c14e31f42db177d
5
5
  SHA512:
6
- metadata.gz: b6b421c3efe426c48c934ccfc9ba2ae385a74fd97cc63fc0c4fbca14070f547ab0003d09abc6fe724ea6dd064d8d49d00a08bf268193850337566b945760be7a
7
- data.tar.gz: 45fa852395860e6b3ade5d413518d2cca268cefbd9faeb21aa83d269e8c74d5d3d5ed9ba2c7fc27906d9d55222acea5d6f53396f0945ae6e54374704a2c14e05
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
- name Taksi::Dynamic
25
+ static :profile_kind, 'resume' # same as `field :profile_kind, Taksi::Static`
26
26
 
27
- details do
28
- age Taksi::Dynamic
29
- email Taksi::Dynamic
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
@@ -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.name}.#{name}"
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.static?
32
+ return value.as_json if value&.static?
28
33
 
29
- return data[name] if parent.nil? || parent.root?
34
+ return data.fetch(name) if parent.nil? || parent.root?
30
35
 
31
- parent.fetch_from(data)[name]
32
- rescue NoMethodError
33
- raise NameError, "Couldn't fetch #{key.inspect} from data: #{data.inspect}"
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 method_missing(name, *args, &block)
63
- return super if @defined
72
+ def dynamic?
73
+ return @nested_fields.any?(&:dynamic?) if @value.nil?
74
+
75
+ @value.dynamic?
76
+ end
64
77
 
65
- @nested_fields << self.class.new(skeleton, name, *args, parent: self, &block)
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 respond_to_missing?(name)
69
- return super if @defined
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
- true
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
@@ -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)
@@ -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.blank?
50
+ next true if interface.alternatives.nil?
45
51
 
46
52
  next true if interface.alternatives.include?(alternative)
47
53
 
@@ -3,18 +3,11 @@
3
3
  module Taksi
4
4
  module Values
5
5
  class Dynamic
6
- attr_reader :component, :name, :field
6
+ attr_reader :component, :name
7
7
 
8
- def initialize(component, name, field = nil)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taksi
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.3'
5
5
  end
data/lib/taksi.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'singleton'
4
+ require 'forwardable'
4
5
 
5
6
  require 'taksi/version'
6
7
 
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.1
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 00:00:00.000000000 Z
11
+ date: 2023-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler