sumaki 0.3.0 → 0.5.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 +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +30 -0
- data/lib/sumaki/model/associations/reflection.rb +2 -2
- data/lib/sumaki/model/enum.rb +6 -7
- data/lib/sumaki/model/fields/reflection.rb +24 -0
- data/lib/sumaki/model/fields/type/boolean.rb +31 -0
- data/lib/sumaki/model/fields/type/date.rb +35 -0
- data/lib/sumaki/model/fields/type/date_time.rb +35 -0
- data/lib/sumaki/model/fields/type/float.rb +23 -0
- data/lib/sumaki/model/fields/type/integer.rb +23 -0
- data/lib/sumaki/model/fields/type/string.rb +23 -0
- data/lib/sumaki/model/fields/type/value.rb +32 -0
- data/lib/sumaki/model/fields/type.rb +50 -0
- data/lib/sumaki/model/fields.rb +137 -0
- data/lib/sumaki/model.rb +7 -5
- data/lib/sumaki/version.rb +1 -1
- metadata +14 -5
- data/lib/sumaki/model/attribute.rb +0 -81
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc2e15ea308cacd7c524ba33698734f08020c2c9d6fb9b39accb4c79bc108a67
|
4
|
+
data.tar.gz: 1090e186dd028117e5f6cb7df816004dcc9508313757e6af8b802d6eeef74a2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 720e0a53bf096093e5e25c5b2dbd2d562666e696d274147d1b3634e49a350309be22b1ada5e069c43f23025e4fdeafbde25c7a9f0b8a4f2d05ffc47fcc7a25d6
|
7
|
+
data.tar.gz: e00e0ef3b7f0af18c438e680e4bfdc40aa83b3409853c5cc587c529b43c9c2f73cd9ad72d0e383d738fbe8879247a8f25beb829001daa3d397e836f1486850a6
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sumaki (0.
|
5
|
-
minenum
|
4
|
+
sumaki (0.5.0)
|
5
|
+
minenum (>= 0.2.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
reline (>= 0.4.2)
|
20
20
|
json (2.7.2)
|
21
21
|
language_server-protocol (3.17.0.3)
|
22
|
-
minenum (0.
|
22
|
+
minenum (0.2.0)
|
23
23
|
parallel (1.24.0)
|
24
24
|
parser (3.3.1.0)
|
25
25
|
ast (~> 2.4.1)
|
data/README.md
CHANGED
@@ -111,6 +111,30 @@ anime.title #=> 'The Vampire Dies in No Time'
|
|
111
111
|
|
112
112
|
If the data contains attributes not declared in the field, it raises no error and is simply ignored.
|
113
113
|
|
114
|
+
#### Type casting
|
115
|
+
|
116
|
+
When a type is specified, it will be typecast.
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
class Character
|
120
|
+
include Sumaki::Model
|
121
|
+
|
122
|
+
field :age, :int
|
123
|
+
end
|
124
|
+
|
125
|
+
character = Character.new({ age: '208' })
|
126
|
+
character.age #=> 208
|
127
|
+
```
|
128
|
+
|
129
|
+
Types are:
|
130
|
+
|
131
|
+
* `:int`
|
132
|
+
* `:float`
|
133
|
+
* `:string`
|
134
|
+
* `:bool`
|
135
|
+
* `:date`
|
136
|
+
* `:datetime`
|
137
|
+
|
114
138
|
### Access to the sub object
|
115
139
|
|
116
140
|
By declaring `singular`, you can access the sub object.
|
@@ -274,6 +298,12 @@ character.type.familier? #=> true
|
|
274
298
|
character = Character.new({})
|
275
299
|
character.type = 1
|
276
300
|
character.type.name #=> :vampire
|
301
|
+
|
302
|
+
character.type = :vampire_hunter
|
303
|
+
character.type.name #=> :vampire_hunter
|
304
|
+
|
305
|
+
character.type.familier!
|
306
|
+
character.type.name #=> :familier
|
277
307
|
```
|
278
308
|
|
279
309
|
|
@@ -18,8 +18,8 @@ module Sumaki
|
|
18
18
|
def model_class
|
19
19
|
@model_class ||= begin
|
20
20
|
basename = @class_name&.to_s || classify(@name.to_s)
|
21
|
-
klass = if @owner_class.const_defined?(basename)
|
22
|
-
@owner_class.const_get(basename)
|
21
|
+
klass = if @owner_class.const_defined?(basename, false)
|
22
|
+
@owner_class.const_get(basename, false)
|
23
23
|
else
|
24
24
|
@owner_class.const_set(basename, Class.new { include Model })
|
25
25
|
end
|
data/lib/sumaki/model/enum.rb
CHANGED
@@ -11,15 +11,14 @@ module Sumaki
|
|
11
11
|
base.extend ClassMethods
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
def get
|
16
|
-
|
14
|
+
class EnumAttrAccessor < Minenum::Enum::Adapter::Base # :nodoc:
|
15
|
+
def get
|
16
|
+
@enum_object.get(@name)
|
17
17
|
end
|
18
18
|
|
19
|
-
def set(
|
20
|
-
|
19
|
+
def set(value)
|
20
|
+
@enum_object.set(@name, value)
|
21
21
|
end
|
22
|
-
module_function :get, :set
|
23
22
|
end
|
24
23
|
|
25
24
|
module ClassMethods # :nodoc:
|
@@ -47,7 +46,7 @@ module Sumaki
|
|
47
46
|
# character.type = 1
|
48
47
|
# character.type.name #=> :vampire
|
49
48
|
def enum(name, values)
|
50
|
-
super(name, values,
|
49
|
+
super(name, values, adapter_builder: EnumAttrAccessor)
|
51
50
|
end
|
52
51
|
|
53
52
|
private
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'type'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
module Fields
|
8
|
+
class Reflection # :nodoc:
|
9
|
+
def initialize(name, type = nil)
|
10
|
+
@name = name
|
11
|
+
@type = type
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
@name.to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
def type_class
|
19
|
+
@type_class ||= @type.nil? ? Type::Value : Type.lookup(@type)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
module Fields
|
8
|
+
module Type
|
9
|
+
class Boolean < Value # :nodoc:
|
10
|
+
def self.serialize(value)
|
11
|
+
return if value.nil?
|
12
|
+
|
13
|
+
case value
|
14
|
+
when true then true
|
15
|
+
when false then false
|
16
|
+
else
|
17
|
+
raise ArgumentError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.deserialize(value)
|
22
|
+
case value
|
23
|
+
when true then true
|
24
|
+
when false then false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
module Sumaki
|
7
|
+
module Model
|
8
|
+
module Fields
|
9
|
+
module Type
|
10
|
+
class DateError < Error; end
|
11
|
+
|
12
|
+
class Date < Value # :nodoc:
|
13
|
+
def self.serialize(value)
|
14
|
+
value.nil? ? nil : cast(value)
|
15
|
+
rescue ::Date::Error
|
16
|
+
raise DateError
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.deserialize(value)
|
20
|
+
value.nil? ? nil : cast(value)
|
21
|
+
rescue ::Date::Error
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.cast(value)
|
26
|
+
return value.to_date if value.respond_to?(:to_date)
|
27
|
+
|
28
|
+
::Date.parse(value.to_s)
|
29
|
+
end
|
30
|
+
private_class_method :cast
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
require 'date'
|
5
|
+
|
6
|
+
module Sumaki
|
7
|
+
module Model
|
8
|
+
module Fields
|
9
|
+
module Type
|
10
|
+
class DateError < Error; end
|
11
|
+
|
12
|
+
class DateTime < Value # :nodoc:
|
13
|
+
def self.serialize(value)
|
14
|
+
value.nil? ? nil : cast(value)
|
15
|
+
rescue ::Date::Error
|
16
|
+
raise DateError
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.deserialize(value)
|
20
|
+
value.nil? ? nil : cast(value)
|
21
|
+
rescue ::Date::Error
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.cast(value)
|
26
|
+
return value.to_datetime if value.respond_to?(:to_datetime)
|
27
|
+
|
28
|
+
::DateTime.parse(value.to_s)
|
29
|
+
end
|
30
|
+
private_class_method :cast
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
module Fields
|
8
|
+
module Type
|
9
|
+
class Float < Value # :nodoc:
|
10
|
+
def self.serialize(value)
|
11
|
+
try_casting do
|
12
|
+
value.nil? ? nil : Float(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.deserialize(value)
|
17
|
+
value.nil? ? nil : Float(value, exception: false)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
module Fields
|
8
|
+
module Type
|
9
|
+
class Integer < Value # :nodoc:
|
10
|
+
def self.serialize(value)
|
11
|
+
try_casting do
|
12
|
+
value.nil? ? nil : Integer(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.deserialize(value)
|
17
|
+
value.nil? ? nil : Integer(value, exception: false)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'value'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
module Fields
|
8
|
+
module Type
|
9
|
+
class String < Value # :nodoc:
|
10
|
+
def self.serialize(value)
|
11
|
+
try_casting do
|
12
|
+
value.nil? ? nil : String(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.deserialize(value)
|
17
|
+
value.nil? ? nil : String(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sumaki
|
4
|
+
module Model
|
5
|
+
module Fields
|
6
|
+
module Type
|
7
|
+
class Error < StandardError; end
|
8
|
+
class ArgumentError < Error; end
|
9
|
+
class TypeError < Error; end
|
10
|
+
|
11
|
+
class Value # :nodoc:
|
12
|
+
def self.serialize(value)
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.deserialize(value)
|
17
|
+
value
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.try_casting
|
21
|
+
yield
|
22
|
+
rescue ::ArgumentError
|
23
|
+
raise Type::ArgumentError
|
24
|
+
rescue ::TypeError
|
25
|
+
raise Type::TypeError
|
26
|
+
end
|
27
|
+
private_class_method :try_casting
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'type/value'
|
4
|
+
require_relative 'type/integer'
|
5
|
+
require_relative 'type/float'
|
6
|
+
require_relative 'type/string'
|
7
|
+
require_relative 'type/boolean'
|
8
|
+
require_relative 'type/date'
|
9
|
+
require_relative 'type/date_time'
|
10
|
+
|
11
|
+
module Sumaki
|
12
|
+
module Model
|
13
|
+
module Fields
|
14
|
+
module Type # :nodoc:
|
15
|
+
class Types # :nodoc:
|
16
|
+
def initialize
|
17
|
+
@types = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def register(name, type_class)
|
21
|
+
@types[name] = type_class
|
22
|
+
end
|
23
|
+
|
24
|
+
def lookup(type_name)
|
25
|
+
@types.fetch(type_name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@types = Types.new
|
30
|
+
|
31
|
+
def register(...)
|
32
|
+
@types.register(...)
|
33
|
+
end
|
34
|
+
|
35
|
+
def lookup(...)
|
36
|
+
@types.lookup(...)
|
37
|
+
end
|
38
|
+
|
39
|
+
module_function :register, :lookup
|
40
|
+
|
41
|
+
register(:int, Integer)
|
42
|
+
register(:float, Float)
|
43
|
+
register(:string, String)
|
44
|
+
register(:bool, Boolean)
|
45
|
+
register(:date, Date)
|
46
|
+
register(:datetime, DateTime)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'fields/reflection'
|
4
|
+
|
5
|
+
module Sumaki
|
6
|
+
module Model
|
7
|
+
# = Sumaki::Model::Fields
|
8
|
+
module Fields
|
9
|
+
def self.included(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.include InstanceMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
class FieldAccessor # :nodoc:
|
15
|
+
def initialize(model)
|
16
|
+
@model = model
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(field_name)
|
20
|
+
reflection = @model.class.field_reflections[field_name]
|
21
|
+
|
22
|
+
value = @model.get(reflection.name)
|
23
|
+
reflection.type_class.deserialize(value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set(field_name, value)
|
27
|
+
reflection = @model.class.field_reflections[field_name]
|
28
|
+
|
29
|
+
serialized = reflection.type_class.serialize(value)
|
30
|
+
@model.set(reflection.name, serialized)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module AccessorAdder # :nodoc:
|
35
|
+
def add(model_class, methods_module, reflection)
|
36
|
+
add_getter(methods_module, reflection.name)
|
37
|
+
add_setter(methods_module, reflection.name)
|
38
|
+
|
39
|
+
model_class.field_reflections[reflection.name] = reflection
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_getter(methods_module, field_name)
|
43
|
+
methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
44
|
+
def #{field_name} # def title
|
45
|
+
field_accessor.get(:'#{field_name}') # field_accessor.get(:'title')
|
46
|
+
end # end
|
47
|
+
RUBY
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_setter(methods_module, field_name)
|
51
|
+
methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
52
|
+
def #{field_name}=(value) # def title=(value)
|
53
|
+
field_accessor.set(:'#{field_name}', value) # field_accessor.set(:'title', value)
|
54
|
+
end # end
|
55
|
+
RUBY
|
56
|
+
end
|
57
|
+
module_function :add, :add_getter, :add_setter
|
58
|
+
end
|
59
|
+
|
60
|
+
module ClassMethods # :nodoc:
|
61
|
+
# Access to the field.
|
62
|
+
#
|
63
|
+
# class Anime
|
64
|
+
# include Sumaki::Model
|
65
|
+
# field :title
|
66
|
+
# field :url
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# anime = Anime.new({ title: 'The Vampire Dies in No Time', url: 'https://sugushinu-anime.jp/' })
|
70
|
+
# anime.title #=> 'The Vampire Dies in No Time'
|
71
|
+
# anime.url #=> 'https://sugushinu-anime.jp/'
|
72
|
+
#
|
73
|
+
# The Field value cam be set.
|
74
|
+
#
|
75
|
+
# anime = Anime.new({})
|
76
|
+
# anime.title = 'The Vampire Dies in No Time'
|
77
|
+
# anime.title #=> 'The Vampire Dies in No Time'
|
78
|
+
#
|
79
|
+
# == Type casting
|
80
|
+
#
|
81
|
+
# When a type is specified, it will be typecast.
|
82
|
+
#
|
83
|
+
# class Character
|
84
|
+
# include Sumaki::Model
|
85
|
+
#
|
86
|
+
# field :age, :int
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# character = Character.new({ age: '208' })
|
90
|
+
# character.age #=> 208
|
91
|
+
#
|
92
|
+
# Types are:
|
93
|
+
#
|
94
|
+
# * <tt>:int</tt>
|
95
|
+
# * <tt>:float</tt>
|
96
|
+
# * <tt>:string</tt>
|
97
|
+
# * <tt>:bool</tt>
|
98
|
+
# * <tt>:date</tt>
|
99
|
+
# * <tt>:datetime</tt>
|
100
|
+
def field(name, type = nil)
|
101
|
+
reflection = Reflection.new(name, type)
|
102
|
+
AccessorAdder.add(self, attribute_methods_module, reflection)
|
103
|
+
end
|
104
|
+
|
105
|
+
def field_names
|
106
|
+
field_reflections.keys
|
107
|
+
end
|
108
|
+
|
109
|
+
def field_reflections
|
110
|
+
@field_reflections ||= {}
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def attribute_methods_module
|
116
|
+
@attribute_methods_module ||= begin
|
117
|
+
mod = Module.new
|
118
|
+
include mod
|
119
|
+
mod
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
module InstanceMethods # :nodoc:
|
125
|
+
def fields
|
126
|
+
self.class.field_names.map.with_object({}) { |e, r| r[e] = public_send(e) }
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def field_accessor
|
132
|
+
@field_accessor ||= FieldAccessor.new(self)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/sumaki/model.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'model/
|
3
|
+
require_relative 'model/fields'
|
4
4
|
require_relative 'model/associations'
|
5
5
|
require_relative 'model/enum'
|
6
6
|
|
@@ -163,7 +163,7 @@ module Sumaki
|
|
163
163
|
base.extend ClassMethods
|
164
164
|
base.include InstanceMethods
|
165
165
|
|
166
|
-
base.include
|
166
|
+
base.include Fields
|
167
167
|
base.include Associations
|
168
168
|
base.include Enum
|
169
169
|
end
|
@@ -237,12 +237,14 @@ module Sumaki
|
|
237
237
|
"#<#{self.class.name} #{inspection}>"
|
238
238
|
end
|
239
239
|
|
240
|
-
def pretty_print(pp)
|
240
|
+
def pretty_print(pp) # rubocop:disable Metrics/MethodLength
|
241
241
|
pp.object_address_group(self) do
|
242
|
-
pp.seplist(fields) do |field, value|
|
242
|
+
pp.seplist(fields, -> { pp.text ',' }) do |field, value|
|
243
243
|
pp.breakable
|
244
244
|
pp.group(1) do
|
245
|
-
pp.text
|
245
|
+
pp.text field.to_s
|
246
|
+
pp.text ':'
|
247
|
+
pp.breakable
|
246
248
|
pp.pp value
|
247
249
|
end
|
248
250
|
end
|
data/lib/sumaki/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sumaki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Loose Coupling
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minenum
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.2.0
|
27
27
|
description: |
|
28
28
|
Sumaki is a wrapper for structured data like JSON.
|
29
29
|
Since Sumaki wraps the target data as it is, rather than parsing it using a schema, the original data can be referenced at any time.
|
@@ -52,8 +52,17 @@ files:
|
|
52
52
|
- lib/sumaki/model/associations/association.rb
|
53
53
|
- lib/sumaki/model/associations/collection.rb
|
54
54
|
- lib/sumaki/model/associations/reflection.rb
|
55
|
-
- lib/sumaki/model/attribute.rb
|
56
55
|
- lib/sumaki/model/enum.rb
|
56
|
+
- lib/sumaki/model/fields.rb
|
57
|
+
- lib/sumaki/model/fields/reflection.rb
|
58
|
+
- lib/sumaki/model/fields/type.rb
|
59
|
+
- lib/sumaki/model/fields/type/boolean.rb
|
60
|
+
- lib/sumaki/model/fields/type/date.rb
|
61
|
+
- lib/sumaki/model/fields/type/date_time.rb
|
62
|
+
- lib/sumaki/model/fields/type/float.rb
|
63
|
+
- lib/sumaki/model/fields/type/integer.rb
|
64
|
+
- lib/sumaki/model/fields/type/string.rb
|
65
|
+
- lib/sumaki/model/fields/type/value.rb
|
57
66
|
- lib/sumaki/version.rb
|
58
67
|
- sig/sumaki.rbs
|
59
68
|
homepage: https://github.com/nowlinuxing/sumaki/
|
@@ -1,81 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Sumaki
|
4
|
-
module Model
|
5
|
-
# = Sumaki::Model::Attribute
|
6
|
-
module Attribute
|
7
|
-
def self.included(base)
|
8
|
-
base.extend ClassMethods
|
9
|
-
base.include InstanceMethods
|
10
|
-
end
|
11
|
-
|
12
|
-
module AccessorAdder # :nodoc:
|
13
|
-
def add(methods_module, field_name)
|
14
|
-
add_getter(methods_module, field_name)
|
15
|
-
add_setter(methods_module, field_name)
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_getter(methods_module, field_name)
|
19
|
-
methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
20
|
-
def #{field_name} # def title
|
21
|
-
get(:'#{field_name}') # get(:'title')
|
22
|
-
end # end
|
23
|
-
RUBY
|
24
|
-
end
|
25
|
-
|
26
|
-
def add_setter(methods_module, field_name)
|
27
|
-
methods_module.module_eval <<~RUBY, __FILE__, __LINE__ + 1
|
28
|
-
def #{field_name}=(value) # def title=(value)
|
29
|
-
set(:'#{field_name}', value) # set(:'title', value)
|
30
|
-
end # end
|
31
|
-
RUBY
|
32
|
-
end
|
33
|
-
module_function :add, :add_getter, :add_setter
|
34
|
-
end
|
35
|
-
|
36
|
-
module ClassMethods # :nodoc:
|
37
|
-
# Access to the field.
|
38
|
-
#
|
39
|
-
# class Anime
|
40
|
-
# include Sumaki::Model
|
41
|
-
# field :title
|
42
|
-
# field :url
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# anime = Anime.new({ title: 'The Vampire Dies in No Time', url: 'https://sugushinu-anime.jp/' })
|
46
|
-
# anime.title #=> 'The Vampire Dies in No Time'
|
47
|
-
# anime.url #=> 'https://sugushinu-anime.jp/'
|
48
|
-
#
|
49
|
-
# The Field value cam be set.
|
50
|
-
#
|
51
|
-
# anime = Anime.new({})
|
52
|
-
# anime.title = 'The Vampire Dies in No Time'
|
53
|
-
# anime.title #=> 'The Vampire Dies in No Time'
|
54
|
-
def field(name)
|
55
|
-
field_names << name.to_sym
|
56
|
-
AccessorAdder.add(attribute_methods_module, name)
|
57
|
-
end
|
58
|
-
|
59
|
-
def field_names
|
60
|
-
@field_names ||= []
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def attribute_methods_module
|
66
|
-
@attribute_methods_module ||= begin
|
67
|
-
mod = Module.new
|
68
|
-
include mod
|
69
|
-
mod
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
module InstanceMethods # :nodoc:
|
75
|
-
def fields
|
76
|
-
self.class.field_names.map.with_object({}) { |e, r| r[e] = public_send(e) }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|