teron 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/associations/belongs_to.rb +49 -0
- data/lib/associations/has_many.rb +90 -0
- data/lib/associations/has_one.rb +101 -0
- data/lib/field.rb +27 -0
- data/lib/record.rb +52 -0
- data/lib/teron.rb +141 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cc7987d1adca37e5e5706ff9fdbeca077ef28a130d54ca046368dd2ed8139e26
|
4
|
+
data.tar.gz: bbdf6db66b23c1a1173b15d6e6811f279856883cc399e11505577032988a009e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 38d06c4f49b93497de80cb25800e154be38fa88becab7d6143518061c19b4f073a8906b6a7bf7408b5f7b6d956c809a8c66588ed935635f269893f25d3e252be
|
7
|
+
data.tar.gz: e03bf8b54a4774ccac65b23a7e00d9a5b2aaceb425223c1b5ef6acb05faa02a6e40ccbf7a7416bbf8a5835243a97aedde0abb5d4e4a43abdb359ebe7706ef998
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Associations for Has Many
|
2
|
+
module TeronAssociation
|
3
|
+
# The Object to be included
|
4
|
+
def belongs_to(class_name, param_options = {})
|
5
|
+
# Should Inverse Object Be Updated
|
6
|
+
inverse = param_options[:inverse] || true
|
7
|
+
|
8
|
+
field "#{class_name}_id".to_sym
|
9
|
+
|
10
|
+
# ==================================
|
11
|
+
# Accessor
|
12
|
+
# ==================================
|
13
|
+
define_method(class_name) do
|
14
|
+
# Get Constant
|
15
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
16
|
+
|
17
|
+
# Get Entry Id
|
18
|
+
klass_obj_id = send("#{class_name}_id".to_sym)
|
19
|
+
klass.find klass_obj_id
|
20
|
+
end
|
21
|
+
|
22
|
+
# ==================================
|
23
|
+
# Add
|
24
|
+
# ==================================
|
25
|
+
define_method("#{class_name}=") do |klass_obj|
|
26
|
+
# Get Constant
|
27
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
28
|
+
|
29
|
+
raise "Invalid #{klass}; Received #{klass_obj.class})" unless klass_obj.instance_of?(klass)
|
30
|
+
|
31
|
+
send("#{class_name}_id=", klass_obj.id)
|
32
|
+
save!
|
33
|
+
end
|
34
|
+
|
35
|
+
# ==================================
|
36
|
+
# Destroy
|
37
|
+
# ==================================
|
38
|
+
define_method('destroy!') do
|
39
|
+
# Get Association Name
|
40
|
+
klass_name = self.class.name.downcase.singularize
|
41
|
+
# self.class._obj_clear(id)
|
42
|
+
|
43
|
+
# Remove from included object`
|
44
|
+
send(class_name)&.send("#{klass_name}_remove", self) if inverse
|
45
|
+
|
46
|
+
super()
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# Associations for Has Many
|
2
|
+
module TeronAssociation
|
3
|
+
# The Object to do the including
|
4
|
+
def has_many(class_name, param_options = {})
|
5
|
+
# Should Inverse Object Be Updated
|
6
|
+
inverse = param_options[:inverse] || true
|
7
|
+
|
8
|
+
field "#{class_name}_ids".to_sym, default: -> { [] }
|
9
|
+
|
10
|
+
# ==================================
|
11
|
+
# Accessor
|
12
|
+
# ==================================
|
13
|
+
define_method(class_name) do
|
14
|
+
# Get Constant
|
15
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
16
|
+
|
17
|
+
# Get Entry Ids
|
18
|
+
klass_list = send("#{class_name}_ids".to_sym)
|
19
|
+
return klass_list if klass_list.empty?
|
20
|
+
|
21
|
+
klass_list.map { |x| klass.find x }.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
# ==================================
|
25
|
+
# Add
|
26
|
+
# ==================================
|
27
|
+
define_method("#{class_name}_add") do |klass_obj|
|
28
|
+
# Get Constant
|
29
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
30
|
+
|
31
|
+
raise "Invalid #{klass}; Received #{klass_obj.class})" unless klass_obj.instance_of?(klass)
|
32
|
+
|
33
|
+
klass_list = send("#{class_name}_ids".to_sym)
|
34
|
+
klass_list.push klass_obj.id unless klass_list.include? klass_obj.id
|
35
|
+
|
36
|
+
# Klass Many Name
|
37
|
+
klass_many_name = self.class.to_s.underscore
|
38
|
+
|
39
|
+
# Update Obj Association
|
40
|
+
if inverse
|
41
|
+
klass_obj.send("#{klass_many_name}=", self)
|
42
|
+
klass_obj.save!
|
43
|
+
end
|
44
|
+
|
45
|
+
save!
|
46
|
+
end
|
47
|
+
|
48
|
+
# ==================================
|
49
|
+
# Remove (Meta)
|
50
|
+
# Don't think this whould be called directly
|
51
|
+
# ==================================
|
52
|
+
define_method("#{class_name}_remove") do |klass_obj|
|
53
|
+
# Get Constant
|
54
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
55
|
+
|
56
|
+
raise "Invalid #{klass}; Received #{klass_obj.class})" unless klass_obj.instance_of?(klass)
|
57
|
+
|
58
|
+
klass_list = send("#{class_name}_ids".to_sym)
|
59
|
+
klass_list.delete klass_obj.id if klass_list.include? klass_obj.id
|
60
|
+
|
61
|
+
# Remove Association on removed object
|
62
|
+
if inverse
|
63
|
+
klass_many_name = self.class.to_s.underscore
|
64
|
+
klass_obj.send("#{klass_many_name}_id=", nil)
|
65
|
+
end
|
66
|
+
|
67
|
+
save!
|
68
|
+
end
|
69
|
+
|
70
|
+
# ==================================
|
71
|
+
# Create
|
72
|
+
# ==================================
|
73
|
+
define_method("#{class_name}_create") do |opts = {}|
|
74
|
+
# Get Constant
|
75
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
76
|
+
klass_obj = klass.new(opts)
|
77
|
+
|
78
|
+
send("#{class_name}_add", klass_obj)
|
79
|
+
|
80
|
+
klass_obj
|
81
|
+
end
|
82
|
+
|
83
|
+
# ==================================
|
84
|
+
# Destroy All
|
85
|
+
# ==================================
|
86
|
+
define_method("#{class_name}_destroy_all") do
|
87
|
+
send(class_name).each(&:destroy!) if inverse
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# Associations for Has Many
|
2
|
+
module TeronAssociation
|
3
|
+
# The Object to do the including
|
4
|
+
def has_one(class_name, param_options = {})
|
5
|
+
# @relationships ||= []
|
6
|
+
|
7
|
+
# Should Inverse Object Be Updated
|
8
|
+
inverse = if param_options.key?(:inverse)
|
9
|
+
param_options[:inverse]
|
10
|
+
else
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
field "#{class_name}_id".to_sym
|
15
|
+
|
16
|
+
# ==================================
|
17
|
+
# Accessor
|
18
|
+
# ==================================
|
19
|
+
define_method(class_name) do
|
20
|
+
# Get Constant
|
21
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
22
|
+
|
23
|
+
# Get Entry Id
|
24
|
+
klass_one = send("#{class_name}_id".to_sym)
|
25
|
+
return klass_one if klass_one.nil?
|
26
|
+
|
27
|
+
klass.find klass_one
|
28
|
+
end
|
29
|
+
|
30
|
+
# ==================================
|
31
|
+
# Add
|
32
|
+
# ==================================
|
33
|
+
define_method("#{class_name}=") do |klass_obj|
|
34
|
+
# Get Constant
|
35
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
36
|
+
|
37
|
+
raise "Invalid #{klass}; Received #{klass_obj.class})" unless klass_obj.instance_of?(klass)
|
38
|
+
|
39
|
+
send("#{class_name}_id=", klass_obj.id)
|
40
|
+
save!
|
41
|
+
end
|
42
|
+
|
43
|
+
# ==================================
|
44
|
+
# Remove (Meta)
|
45
|
+
# Don't think this whould be called directly
|
46
|
+
# ==================================
|
47
|
+
define_method("#{class_name}_remove") do |klass_obj|
|
48
|
+
# Get Constant
|
49
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
50
|
+
|
51
|
+
# Validate Correct Klass Object
|
52
|
+
raise "Invalid #{klass}; Received #{klass_obj.class})" unless klass_obj.instance_of?(klass)
|
53
|
+
|
54
|
+
klass_name = self.class.name.downcase.singularize
|
55
|
+
|
56
|
+
# Get Entry Id
|
57
|
+
# klass_one = send("#{class_name}_id".to_sym)
|
58
|
+
# return klass_one if klass_one.nil?
|
59
|
+
|
60
|
+
klass_obj.send("#{klass_name}_id=", nil) if inverse
|
61
|
+
send("#{class_name}_id=", nil)
|
62
|
+
|
63
|
+
save!
|
64
|
+
end
|
65
|
+
|
66
|
+
# ==================================
|
67
|
+
# Create
|
68
|
+
# ==================================
|
69
|
+
define_method("#{class_name}_create") do |opts = {}|
|
70
|
+
# Get Constant
|
71
|
+
klass = class_name.to_s.capitalize.singularize.classify.constantize
|
72
|
+
klass_obj = klass.new(opts)
|
73
|
+
|
74
|
+
send("#{class_name}=", klass_obj)
|
75
|
+
|
76
|
+
# Klass Has One Name
|
77
|
+
klass_one_name = self.class.to_s.underscore
|
78
|
+
|
79
|
+
# Update Obj Association
|
80
|
+
if inverse
|
81
|
+
klass_obj.send("#{klass_one_name}=", self)
|
82
|
+
klass_obj.save!
|
83
|
+
end
|
84
|
+
|
85
|
+
save!
|
86
|
+
|
87
|
+
klass_obj
|
88
|
+
end
|
89
|
+
|
90
|
+
# # ==================================
|
91
|
+
# # Destroy All
|
92
|
+
# # ==================================
|
93
|
+
# define_method("#{class_name}_destroy_all") do
|
94
|
+
# send(class_name).each(&:destroy!) if inverse
|
95
|
+
# end
|
96
|
+
|
97
|
+
# class_variable_set(:@@relationships, @relationships)
|
98
|
+
|
99
|
+
# true
|
100
|
+
end
|
101
|
+
end
|
data/lib/field.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Field Actions
|
2
|
+
module TeronField
|
3
|
+
def field(param_name, param_options = {})
|
4
|
+
unless class_variables.include? :@@data
|
5
|
+
class_variable_set(:@@data, {})
|
6
|
+
class_variable_set(:@@mutex, Mutex.new)
|
7
|
+
class_variable_set(:@@object_list, {})
|
8
|
+
end
|
9
|
+
|
10
|
+
@params ||= [{
|
11
|
+
name: :id,
|
12
|
+
options: { default: -> { SecureRandom.uuid }, dump: true }
|
13
|
+
}]
|
14
|
+
|
15
|
+
param_options[:dump] = true unless param_options.key? :dump
|
16
|
+
|
17
|
+
@params.push(
|
18
|
+
name: param_name,
|
19
|
+
options: param_options
|
20
|
+
)
|
21
|
+
attr_accessor param_name.to_sym
|
22
|
+
|
23
|
+
class_variable_set(:@@params, @params)
|
24
|
+
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
data/lib/record.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Saving/Records Keeper
|
2
|
+
module TeronRecords
|
3
|
+
def save!
|
4
|
+
self.class._mutex.synchronize do
|
5
|
+
# Handle Dump vs No Dump Variables
|
6
|
+
payload = self.class.class_variable_get(:@@params).each_with_object({}) do |data, obj|
|
7
|
+
value = attributes[data[:name]]
|
8
|
+
obj[data[:name]] = data.dig(:options, :dump) ? Marshal.load(Marshal.dump(value)) : value
|
9
|
+
|
10
|
+
obj
|
11
|
+
end
|
12
|
+
|
13
|
+
self.class._data[id] = payload
|
14
|
+
end
|
15
|
+
|
16
|
+
self.class._obj_clear id
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
alias save save!
|
22
|
+
|
23
|
+
def destroy!
|
24
|
+
self.class._mutex.synchronize do
|
25
|
+
self.class._data.delete id
|
26
|
+
end
|
27
|
+
|
28
|
+
self.class._obj_clear id
|
29
|
+
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def attributes
|
34
|
+
instance_variables.each_with_object({}) do |name, obj|
|
35
|
+
key = name.to_s.delete('@').to_sym
|
36
|
+
obj[key] = instance_variable_get(name)
|
37
|
+
|
38
|
+
obj
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def reload
|
43
|
+
klass_obj = self.class.find id
|
44
|
+
|
45
|
+
instance_variables.each do |name|
|
46
|
+
key = name.to_s.delete('@').to_sym
|
47
|
+
instance_variable_set(name, klass_obj.send(key))
|
48
|
+
end
|
49
|
+
|
50
|
+
true
|
51
|
+
end
|
52
|
+
end
|
data/lib/teron.rb
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# ==============================================================
|
2
|
+
# ___ ____ ____ ____ __ _
|
3
|
+
# | |=== |--< [__] | \|
|
4
|
+
#
|
5
|
+
# ======== [ The Devious Teron ] ========
|
6
|
+
# ==============================================================
|
7
|
+
|
8
|
+
# Attributes
|
9
|
+
require 'securerandom'
|
10
|
+
require_relative 'field'
|
11
|
+
|
12
|
+
# In Memory Collection
|
13
|
+
require_relative 'record'
|
14
|
+
|
15
|
+
# Associations
|
16
|
+
require 'active_support/core_ext/string/inflections' ## Constantize
|
17
|
+
|
18
|
+
require_relative 'associations/has_many'
|
19
|
+
require_relative 'associations/has_one'
|
20
|
+
require_relative 'associations/belongs_to'
|
21
|
+
|
22
|
+
# Initializtion Helper
|
23
|
+
class Teron
|
24
|
+
attr_accessor :id
|
25
|
+
|
26
|
+
include TeronRecords
|
27
|
+
extend TeronField
|
28
|
+
extend TeronAssociation
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
"#<#{self.class.name} #{inspect_vars.join(', ')}>"
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect_vars
|
35
|
+
instance_variables.map do |name|
|
36
|
+
"#{name}: #{instance_variable_get(name)}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(params = {})
|
41
|
+
self.class.class_variable_get(:@@params).each do |param|
|
42
|
+
value = if params.key? param[:name]
|
43
|
+
params[param[:name]]
|
44
|
+
else
|
45
|
+
default = param.dig(:options, :default)
|
46
|
+
if default.instance_of?(Proc)
|
47
|
+
default.call
|
48
|
+
else
|
49
|
+
# Ensure Deep Clone
|
50
|
+
param.dig(:options, :dump) ? Marshal.load(Marshal.dump(default)) : default
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
instance_variable_set("@#{param[:name]}", value) if value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class << self
|
60
|
+
def _data
|
61
|
+
class_variable_get(:@@data)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Store of In Memory already loaded objects
|
65
|
+
def _object_list
|
66
|
+
class_variable_get(:@@object_list)
|
67
|
+
end
|
68
|
+
|
69
|
+
def _mutex
|
70
|
+
class_variable_get(:@@mutex)
|
71
|
+
end
|
72
|
+
|
73
|
+
def first
|
74
|
+
return nil if count.zero?
|
75
|
+
|
76
|
+
_obj_create _data.values[0]
|
77
|
+
end
|
78
|
+
|
79
|
+
def last
|
80
|
+
return nil if count.zero?
|
81
|
+
|
82
|
+
_obj_create _data.values[-1]
|
83
|
+
end
|
84
|
+
|
85
|
+
def count
|
86
|
+
_data.size
|
87
|
+
end
|
88
|
+
|
89
|
+
def _obj_create(obj_data)
|
90
|
+
_mutex.synchronize do
|
91
|
+
_object_list[obj_data[:id]] = new obj_data unless _object_list.key? obj_data[:id]
|
92
|
+
end
|
93
|
+
|
94
|
+
_object_list[obj_data[:id]]
|
95
|
+
end
|
96
|
+
|
97
|
+
def _obj_clear(obj_id)
|
98
|
+
_mutex.synchronize do
|
99
|
+
_object_list.delete obj_id if _object_list.key? obj_id
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_by(args)
|
104
|
+
return nil if args.nil?
|
105
|
+
return nil if count.zero?
|
106
|
+
|
107
|
+
key, value = args.first
|
108
|
+
obj = _data.values.find { |x| x[key] == value }
|
109
|
+
|
110
|
+
return nil unless obj
|
111
|
+
|
112
|
+
_obj_create obj
|
113
|
+
end
|
114
|
+
|
115
|
+
def where(args)
|
116
|
+
return [] if args.nil?
|
117
|
+
return [] if count.zero?
|
118
|
+
|
119
|
+
objs = _data.values.select do |value|
|
120
|
+
args.all? { |k, v| value[k] == v }
|
121
|
+
end
|
122
|
+
|
123
|
+
objs.map { |x| _obj_create x }
|
124
|
+
end
|
125
|
+
|
126
|
+
def all
|
127
|
+
return [] if count.zero?
|
128
|
+
|
129
|
+
_data.values.map { |x| _obj_create x }
|
130
|
+
end
|
131
|
+
|
132
|
+
def find(key)
|
133
|
+
return nil if key.nil?
|
134
|
+
return nil if count.zero?
|
135
|
+
|
136
|
+
return nil unless _data.key? key
|
137
|
+
|
138
|
+
_obj_create _data[key]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: teron
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Davin Walker
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.12'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.80'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.80'
|
55
|
+
description: Gimme an easy way to initialize database less classes
|
56
|
+
email:
|
57
|
+
- dishcandanty@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/associations/belongs_to.rb
|
63
|
+
- lib/associations/has_many.rb
|
64
|
+
- lib/associations/has_one.rb
|
65
|
+
- lib/field.rb
|
66
|
+
- lib/record.rb
|
67
|
+
- lib/teron.rb
|
68
|
+
homepage: https://gitlab.com/davinwalker/teron
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.0.3
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Experimental Simple Class Initialization
|
91
|
+
test_files: []
|