giri 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ce0c580bbf94b64b4aabe9b470cc631ea1ec0ce01bac6fe169b594022415a693
4
+ data.tar.gz: e78841c26884ad0d47df63e938fb04058123ee39b4aeeadc353cc2f4aa5a05a1
5
+ SHA512:
6
+ metadata.gz: 41e49781948e8d73d0c3b46a0a0bb645d5d23af55da76dcd4394b3b9202f6cc21ae044bbb6bbfa11be678027912acc347f3908f0d8a4df5ae4da36bfdaa0f1e8
7
+ data.tar.gz: 4d43d8b9db7be0184061ded67a1c2a417309af2da06baee4a2c436a729908c1117ee7a002e4858ab39ae97107ec4b7c9636c4e20b8dc808f227238fc96ceb35a
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # README
2
+
3
+ # DEVELOPMENT GUIDE
4
+
5
+ ## REPL
6
+
7
+ Since `Gemfile` has the line below, you just run `require "giri"` in `bundle exec irb` to start `Giri`.
8
+
9
+ ```
10
+ gem "giri", path: './'
11
+ ```
12
+
13
+ ```
14
+ bundle install
15
+ ```
16
+
17
+ ```
18
+ bundle exec irb
19
+
20
+ # (irb):> require "giri"
21
+ ```
22
+
23
+ ## Local Build
24
+
25
+ Since it has `Rakefile`, you just run the following command to make build and install it on your local.
26
+
27
+ ```
28
+ bundle exec rake build
29
+ bundle exec rake install
30
+ ```
31
+
32
+ Then you just run `require "giri"` in `irb` to start `Giri`.
33
+
34
+ ```
35
+ irb
36
+
37
+ (irb):> require "giri"
38
+ ```
39
+
40
+ ## Publish Gem
41
+
42
+ If you have the right to publish it to rubygems, run it.
43
+
44
+ ```
45
+ bundle exec rake build
46
+ gem push ./pkg/giri-${VERSION}.gem
47
+ ```
@@ -0,0 +1,7 @@
1
+ class Giri::BaseNode
2
+ extend Giri::Bud
3
+
4
+ def inspect
5
+ "#<#{self.class}:0x#{object_id.to_s(16)} @ref_name=#{@ref_name.inspect} parent_ref_name=#{parent_ref_name.inspect} @attributes=#{@attributes.inspect}>"
6
+ end
7
+ end
data/lib/giri/bud.rb ADDED
@@ -0,0 +1,185 @@
1
+ module Giri::Bud
2
+
3
+ def self.extended(base)
4
+ base.singleton_class.attr_accessor :xml_nodes, :xml_attributes, :with_name_default_for_node, :with_name_default_for_attribute
5
+
6
+ base.xml_nodes = {}
7
+ base.xml_attributes = []
8
+ # TODO: Set nil for default
9
+ base.with_name_default_for_node = :camelize
10
+ base.with_name_default_for_attribute = :lower_camelcase
11
+
12
+ base.class_eval do
13
+ attr_reader :node, :ref_name, :attributes, :parent
14
+ def initialize(*args)
15
+ initialize_setup(*args)
16
+ end
17
+
18
+ def initialize_setup(node, ref_name: nil, parent: nil)
19
+ @node = node
20
+ @ref_name = ref_name
21
+ @attributes = Hashie::Mash.new(build_attributes)
22
+ @parent = parent
23
+ end
24
+
25
+ def parent_ref_name
26
+ parent&.ref_name
27
+ end
28
+
29
+ def find_elements(name)
30
+ node.elements.select{|e| e.name == name}
31
+ end
32
+
33
+ def find_element(name)
34
+ node.elements.find{|e| e.name == name}
35
+ end
36
+
37
+ def where(&block)
38
+ block.call(node)
39
+ end
40
+
41
+ def build_attributes
42
+ self.class.xml_attributes.map do |col|
43
+ name = col[:name]
44
+ type = self.class.build_type(col[:type])
45
+ with_name = col[:with_name]
46
+
47
+ attr_name = self.class.build_attribute_name(name, with_name || self.class.with_name_default_for_attribute)
48
+ value = node.attributes[attr_name.to_s]&.value
49
+ value = if value
50
+ if type.is_a?(Class)
51
+ type.new(value)
52
+ elsif type.is_a?(Symbol)
53
+ "Giri::TextNode#{type.to_s.camelize}".constantize.build_value(value)
54
+ else
55
+ value
56
+ end
57
+ else
58
+ value
59
+ end
60
+ # value = (value && type) ? type.new(value) : value
61
+
62
+ [name.to_sym, value]
63
+ end.to_h
64
+ end
65
+ end
66
+ end
67
+
68
+ def inherited(base)
69
+ base.xml_nodes = xml_nodes.dup
70
+ base.xml_attributes = xml_attributes.dup
71
+ base.with_name_default_for_node = with_name_default_for_node
72
+ base.with_name_default_for_attribute = with_name_default_for_attribute
73
+ super
74
+ end
75
+
76
+ def spawn(&block)
77
+ Class.new(self, &block)
78
+ end
79
+
80
+ def text_node(name, **args, &block)
81
+ xml_node(name, type: "Giri::TextNodeString", **args, &block)
82
+ end
83
+
84
+ def integer_node(name, **args, &block)
85
+ xml_node(name, type: "Giri::TextNodeInteger", **args, &block)
86
+ end
87
+
88
+ def big_decimal_node(name, **args, &block)
89
+ xml_node(name, type: "Giri::TextNodeBigDecimal", **args, &block)
90
+ end
91
+
92
+ def date_time_node(name, **args, &block)
93
+ xml_node(name, type: "Giri::TextNodeDateTime", **args, &block)
94
+ end
95
+
96
+ def duration_node(name, **args, &block)
97
+ xml_node(name, type: "Giri::TextNodeDuration", **args, &block)
98
+ end
99
+
100
+ def xml_node_collection(name, **args, &block)
101
+ xml_node(name, collection: true, **args, &block)
102
+ end
103
+
104
+ def xml_node(name, type: nil, collection: nil, where: nil, with_name: nil, &block)
105
+ type = if block_given?
106
+ type = build_type(type || self.xml_nodes.dig(name.to_sym, :type) || "Giri::BaseNode")
107
+ type.spawn(&block)
108
+ else
109
+ build_type(type)
110
+ end
111
+
112
+ self.xml_nodes[name.to_sym] = {name: name, type: type, collection: collection}
113
+
114
+ class_eval do
115
+ define_method(name) do
116
+ var = instance_variable_get("@#{name}")
117
+ var || begin
118
+ attr_name = self.class.build_attribute_name(name, with_name || self.class.with_name_default_for_node)
119
+ elem = if where
120
+ where.call(node)
121
+ else
122
+ collection ?
123
+ find_elements(attr_name.to_s) :
124
+ find_element(attr_name.to_s)
125
+ end
126
+ elem = if collection
127
+ elem.empty? ? nil : elem
128
+ else
129
+ elem
130
+ end
131
+
132
+ if elem
133
+ # type = if block_given? # This block points the args in `xml_node` not method defined dynamically.
134
+ # type = self.class.build_type(type || "Giri::BaseNode")
135
+ # type.spawn(&block)
136
+ # else
137
+ # self.class.build_type(type)
138
+ # end
139
+ o = if collection
140
+ elem.map{|e| type ? type.new(e, ref_name: name, parent: self) : e}
141
+ else
142
+ type ? type.new(elem, ref_name: name, parent: self) : elem
143
+ end
144
+ instance_variable_set("@#{name}", o)
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ def xml_attribute(name, **args)
152
+ self.xml_attributes = self.xml_attributes.append(args.merge(name: name))
153
+
154
+ class_eval do
155
+ define_method(name) do
156
+ attributes.public_send(name)
157
+ end
158
+ end
159
+ end
160
+
161
+ def build_attribute_name(name, with_name)
162
+ if with_name.is_a?(String)
163
+ with_name
164
+ elsif [:underscore, :camelize, :camelcase].include?(with_name)
165
+ name.to_s.send(with_name).to_sym
166
+ elsif with_name == :lower_camelcase
167
+ name.to_s.camelize(:lower).to_sym
168
+ else
169
+ name
170
+ end
171
+ end
172
+
173
+ def build_type(type)
174
+ if type.is_a?(Class)
175
+ type
176
+ elsif type.is_a?(String)
177
+ # type.to_s.constantize
178
+ Object.const_get(type.to_s)
179
+ elsif type.is_a?(Symbol)
180
+ type
181
+ else
182
+ nil
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,15 @@
1
+ require "bigdecimal"
2
+ require "bigdecimal/util"
3
+
4
+ class Giri::TextNodeBigDecimal < DelegateClass(BigDecimal)
5
+ extend Giri::Bud
6
+
7
+ def self.build_value(str)
8
+ str.to_d
9
+ end
10
+
11
+ def initialize(*args)
12
+ initialize_setup(*args)
13
+ super(self.class.build_value(@node.text))
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ require "date"
2
+
3
+ class Giri::TextNodeDateTime < DelegateClass(DateTime)
4
+ extend Giri::Bud
5
+
6
+ def self.build_value(str)
7
+ DateTime.parse(str)
8
+ end
9
+
10
+ def initialize(*args)
11
+ initialize_setup(*args)
12
+ super(self.class.build_value(@node.text))
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # https://www.w3.org/TR/xmlschema-2/#duration
2
+ class Giri::TextNodeDuration < Giri::TextNodeString
3
+
4
+ def components
5
+ @components ||= begin
6
+ _, years, months, days, time_part, hours, minutes, seconds = self.match(/\AP(\d+Y)?(\d+M)?(\d+D)?(T(\d+H)?(\d+M)?(\d+S)?)?\z/).to_a
7
+ # Example of values "15H" and "15H".to_i will get 15.
8
+ {
9
+ years: years.to_i,
10
+ months: months.to_i,
11
+ days: days.to_i,
12
+ hours: hours.to_i,
13
+ minutes: minutes.to_i,
14
+ seconds: seconds.to_i,
15
+ }
16
+ end
17
+ end
18
+
19
+ def duration_time
20
+ components.reduce(0) do |acc,(k,v)|
21
+ acc + v.public_send(k)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ class Giri::TextNodeInteger < DelegateClass(Integer)
2
+ extend Giri::Bud
3
+
4
+ def self.build_value(str)
5
+ str.to_i
6
+ end
7
+
8
+ def initialize(*args)
9
+ initialize_setup(*args)
10
+ super(self.class.build_value(@node.text))
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ class Giri::TextNodeString < DelegateClass(String)
2
+ extend Giri::Bud
3
+
4
+ def initialize(*args)
5
+ initialize_setup(*args)
6
+ super(@node.text)
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Giri
2
+ VERSION = "0.0.3"
3
+ end
data/lib/giri.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "hashie/mash"
2
+ require "active_support"
3
+ require "active_support/inflector"
4
+ require "active_support/core_ext/integer"
5
+
6
+ require "giri/version"
7
+ require "giri/bud"
8
+ require "giri/base_node"
9
+ require "giri/text_node_string"
10
+ require "giri/text_node_integer"
11
+ require "giri/text_node_big_decimal"
12
+ require "giri/text_node_date_time"
13
+ require "giri/text_node_duration"
14
+
15
+ module Giri
16
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: giri
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - metheglin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hashie
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Giri
56
+ email: pigmybank@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - README.md
62
+ - lib/giri.rb
63
+ - lib/giri/base_node.rb
64
+ - lib/giri/bud.rb
65
+ - lib/giri/text_node_big_decimal.rb
66
+ - lib/giri/text_node_date_time.rb
67
+ - lib/giri/text_node_duration.rb
68
+ - lib/giri/text_node_integer.rb
69
+ - lib/giri/text_node_string.rb
70
+ - lib/giri/version.rb
71
+ homepage: https://rubygems.org/gems/giri
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '2.7'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.1.4
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Giri
94
+ test_files: []