jsondb 0.0.2 → 0.1.1
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/lib/jsondb.rb +14 -5
- data/lib/jsondb/base.rb +29 -0
- data/lib/jsondb/commands.rb +56 -0
- data/lib/jsondb/constants.rb +23 -0
- data/lib/jsondb/db.rb +94 -57
- data/lib/jsondb/field.rb +80 -48
- data/lib/jsondb/fields.rb +55 -0
- data/lib/jsondb/file_ops.rb +64 -54
- data/lib/jsondb/logger.rb +36 -0
- data/lib/jsondb/record.rb +53 -88
- data/lib/jsondb/records.rb +62 -0
- data/lib/jsondb/result_set.rb +126 -0
- data/lib/jsondb/settings.rb +34 -0
- data/lib/jsondb/table.rb +93 -145
- data/lib/jsondb/tables.rb +78 -0
- data/lib/jsondb/validations.rb +133 -0
- metadata +12 -4
- data/lib/jsondb/resultset.rb +0 -109
- data/lib/jsondb/validation.rb +0 -88
@@ -0,0 +1,34 @@
|
|
1
|
+
module JSONdb
|
2
|
+
|
3
|
+
class Settings
|
4
|
+
|
5
|
+
include JSONdb::Logger
|
6
|
+
|
7
|
+
attr_accessor :folder, :writeable, :raise_errors, :log_enabled, :log_level, :log_file, :log_folder, :verbose
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@folder = ""
|
11
|
+
# read-only?
|
12
|
+
@writeable = true
|
13
|
+
# raise errors or return true or false
|
14
|
+
@raise_errors = true
|
15
|
+
# logs
|
16
|
+
@log_enabled = false
|
17
|
+
@log_level = :info
|
18
|
+
@log_file = "db.log"
|
19
|
+
@log_folder = nil
|
20
|
+
@verbose = false
|
21
|
+
#
|
22
|
+
end
|
23
|
+
|
24
|
+
def log_level=(level)
|
25
|
+
if allowed_log_level?(level)
|
26
|
+
@log_level = level
|
27
|
+
else
|
28
|
+
log("Log level not log_level_allowed", :error)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/jsondb/table.rb
CHANGED
@@ -1,147 +1,95 @@
|
|
1
1
|
module JSONdb
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
@structure_file.contents['last_id'] = @last_id
|
96
|
-
@fields.each do |id, field|
|
97
|
-
@structure_file.contents['fields'][id] = field.to_hash
|
98
|
-
end
|
99
|
-
@structure_file.save
|
100
|
-
|
101
|
-
@records_file.contents = {}
|
102
|
-
@records.each do |id, record|
|
103
|
-
@records_file.contents[id] = record.to_hash
|
104
|
-
end
|
105
|
-
@records_file.save
|
106
|
-
@updated_at = Time.now.to_i
|
107
|
-
@persisted = true
|
108
|
-
end
|
109
|
-
|
110
|
-
def to_hash
|
111
|
-
return { "name" => @name, "updated_at" => @updated_at }
|
112
|
-
end
|
113
|
-
|
114
|
-
def updated_at_time
|
115
|
-
Time.at(@updated_at)
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
def new_id
|
121
|
-
@last_id = @last_id + 1
|
122
|
-
return @last_id
|
123
|
-
end
|
124
|
-
|
125
|
-
def add_main_fields
|
126
|
-
if @fields["id"].nil?
|
127
|
-
id_field = self.field('id')
|
128
|
-
id_field.type = "Fixnum"
|
129
|
-
id_field.nullable = false
|
130
|
-
id_field.default = 0
|
131
|
-
end
|
132
|
-
if @fields["created_at"].nil?
|
133
|
-
created_field = self.field('created_at')
|
134
|
-
created_field.type = "Fixnum"
|
135
|
-
created_field.nullable = false
|
136
|
-
created_field.default = 0
|
137
|
-
end
|
138
|
-
if @fields["updated_at"].nil?
|
139
|
-
updated_field = self.field('updated_at')
|
140
|
-
updated_field.type = "Fixnum"
|
141
|
-
updated_field.nullable = false
|
142
|
-
updated_field.default = 0
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
2
|
+
|
3
|
+
class Table
|
4
|
+
|
5
|
+
include JSONdb::Validations::Naming
|
6
|
+
include JSONdb::Logger
|
7
|
+
include JSONdb::Fields
|
8
|
+
include JSONdb::Records
|
9
|
+
|
10
|
+
attr_reader :created_at, :updated_at, :persisted
|
11
|
+
attr_accessor :timestamp
|
12
|
+
|
13
|
+
def initialize(name, new_table = true)
|
14
|
+
@name = name
|
15
|
+
|
16
|
+
@persisted = false
|
17
|
+
|
18
|
+
JSONdb.records[@name] = Hash.new
|
19
|
+
JSONdb.fields[@name] = Hash.new
|
20
|
+
|
21
|
+
set_defaults
|
22
|
+
add_main_fields
|
23
|
+
init_table(new_table)
|
24
|
+
end
|
25
|
+
|
26
|
+
def persist
|
27
|
+
@persisted = true
|
28
|
+
@file.contents = records_to_hash
|
29
|
+
@file.write
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_hash
|
33
|
+
{
|
34
|
+
@name => {
|
35
|
+
"created_at" => @created_at,
|
36
|
+
"updated_at" => @updated_at,
|
37
|
+
"last_id" => @last_id,
|
38
|
+
"fields" => fields_to_hash
|
39
|
+
},
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def destroy
|
44
|
+
@file.destroy
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def new_id
|
50
|
+
@last_id = @last_id + 1
|
51
|
+
return @last_id
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_defaults
|
55
|
+
@created_at = Time.now.to_i
|
56
|
+
@updated_at = Time.now.to_i
|
57
|
+
|
58
|
+
@timestamp = true
|
59
|
+
@id_autonumber = true
|
60
|
+
@last_id = 0
|
61
|
+
end
|
62
|
+
|
63
|
+
def init_table(new_table)
|
64
|
+
begin
|
65
|
+
if allowed_name?(@name)
|
66
|
+
@file = FileOps.new(JSONdb.settings.folder, "#{@name}.json", 'table', true)
|
67
|
+
@file.read
|
68
|
+
|
69
|
+
records_in_file = @file.contents
|
70
|
+
|
71
|
+
JSONdb.records[@name] = Hash.new
|
72
|
+
records_in_file.each do |key, values|
|
73
|
+
JSONdb.records[@name][values['id']] = Record.new(@name, values)
|
74
|
+
end
|
75
|
+
|
76
|
+
if new_table
|
77
|
+
@file.write
|
78
|
+
@persisted = true
|
79
|
+
log("Created data file for '#{@name}'.", :info)
|
80
|
+
else
|
81
|
+
@persisted = true
|
82
|
+
log("Loaded data file for '#{@name}'.", :info)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
log("Could not initialize class for table '#{@name}'.", :error)
|
86
|
+
end
|
87
|
+
rescue
|
88
|
+
log("Could not initialize class for table '#{@name}'.", :error)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
|
147
95
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module JSONdb
|
2
|
+
|
3
|
+
module Tables
|
4
|
+
|
5
|
+
include JSONdb::Logger
|
6
|
+
|
7
|
+
def table(name)
|
8
|
+
begin
|
9
|
+
return JSONdb.tables[name]
|
10
|
+
rescue
|
11
|
+
log("Table does not exists '#{name}'.", :error)
|
12
|
+
return nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def table_names
|
17
|
+
JSONdb.tables.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def table_count
|
21
|
+
return table_names.count
|
22
|
+
end
|
23
|
+
|
24
|
+
def table_exists?(name)
|
25
|
+
JSONdb.tables.keys.include?(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_table(name)
|
29
|
+
begin
|
30
|
+
JSONdb.tables[name] = JSONdb::Table.new(name, false)
|
31
|
+
log("Loaded from disk '#{name}',", :info)
|
32
|
+
return true
|
33
|
+
rescue
|
34
|
+
log("Cannot load from disk '#{name}'", :error)
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_table(name)
|
40
|
+
if table_exists?(name)
|
41
|
+
log("Already exists '#{name}'.", :error)
|
42
|
+
return false
|
43
|
+
else
|
44
|
+
begin
|
45
|
+
JSONdb.tables[name] = JSONdb::Table.new(name, true)
|
46
|
+
log("Created '#{name}'.", :info)
|
47
|
+
return true
|
48
|
+
rescue
|
49
|
+
log("Cannot create '#{name}'", :error)
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def drop_table(name)
|
56
|
+
begin
|
57
|
+
JSONdb.tables[name].destroy
|
58
|
+
JSONdb.tables[name] = nil
|
59
|
+
JSONdb.tables.delete(name)
|
60
|
+
log("Deleted '#{name}'.", :info)
|
61
|
+
return true
|
62
|
+
rescue
|
63
|
+
log("Could not delete '#{name}'.", :error)
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def tables_to_hash
|
69
|
+
to_hash = Hash.new
|
70
|
+
JSONdb.tables.each do |key, values|
|
71
|
+
to_hash = to_hash.merge(values.to_hash)
|
72
|
+
end
|
73
|
+
return to_hash
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module JSONdb
|
2
|
+
|
3
|
+
module Validations
|
4
|
+
|
5
|
+
module Naming
|
6
|
+
|
7
|
+
include JSONdb::Logger
|
8
|
+
|
9
|
+
def allowed_name?(name)
|
10
|
+
if (name =~ /^[a-zA-Z0-9_]+$/).nil?
|
11
|
+
log("Name '#{name}' not allowed. /^[a-zA-Z0-9_]+$/", :error)
|
12
|
+
return false
|
13
|
+
else
|
14
|
+
return true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Types
|
20
|
+
|
21
|
+
include JSONdb::Logger
|
22
|
+
|
23
|
+
AllowedTypes = [
|
24
|
+
"String",
|
25
|
+
"Fixnum",
|
26
|
+
"Integer",
|
27
|
+
"Float",
|
28
|
+
"Time",
|
29
|
+
"Bool"
|
30
|
+
]
|
31
|
+
|
32
|
+
def allowed_type?(type)
|
33
|
+
if AllowedTypes.include?(type.to_s)
|
34
|
+
return true
|
35
|
+
else
|
36
|
+
log("Validation: Type '#{type.to_s}' not allowed", :error)
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_type(_class, _value)
|
42
|
+
case _class
|
43
|
+
when "Bool"
|
44
|
+
bool?(_class, _value)
|
45
|
+
when "String"
|
46
|
+
string?(_class, _value)
|
47
|
+
when "Fixnum", "Integer", "Float"
|
48
|
+
numeric?(_class, _value)
|
49
|
+
when "Time"
|
50
|
+
time?(_class, _value)
|
51
|
+
else
|
52
|
+
log("Validation: '#{_class}' type not allowed", :error)
|
53
|
+
return false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def bool?(_class, _value)
|
60
|
+
case _value
|
61
|
+
when true, false
|
62
|
+
return true
|
63
|
+
else
|
64
|
+
log("Validation: Bool: Not a Bool type", :error)
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def string?(_class, _value)
|
70
|
+
if _class == _value.class.to_s
|
71
|
+
return true
|
72
|
+
else
|
73
|
+
log("Validation: #{_class}: Value '#{_value}' not allowed for '#{_class}' type", :error)
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def numeric?(_class, _value)
|
79
|
+
case _class
|
80
|
+
when "Fixnum", "Integer"
|
81
|
+
if _value.class.to_s == "Fixnum"
|
82
|
+
return true
|
83
|
+
else
|
84
|
+
log("Validation: '#{_value}' is not Integer", :error)
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
when "Float"
|
88
|
+
case _value.class.to_s
|
89
|
+
when "Float"
|
90
|
+
return true
|
91
|
+
when "Fixnum"
|
92
|
+
return true
|
93
|
+
else
|
94
|
+
log("Validation: '#{_value} is not a Float type", :error)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
log("Validation: '#{_value} is not a Numeric type", :error)
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def time?(_class, _value)
|
103
|
+
if eval(_value).class.to_s == "Time"
|
104
|
+
return true
|
105
|
+
else
|
106
|
+
log("Validation: '#{_value} is not a Time type", :error)
|
107
|
+
return false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end # Types
|
111
|
+
|
112
|
+
module Records
|
113
|
+
|
114
|
+
include JSONdb::Validations::Types
|
115
|
+
|
116
|
+
FieldsToNotVerify = ['id', 'created_at', 'updated_at']
|
117
|
+
|
118
|
+
def record_validates?(table_name, record)
|
119
|
+
table_fields = JSONdb.fields[table_name]
|
120
|
+
table_fields.each do |field_name, field_values|
|
121
|
+
if FieldsToNotVerify.include?(field_name) == false
|
122
|
+
actual_value = record.send field_name.to_sym
|
123
|
+
return false if field_values.nullable == false and actual_value.nil?
|
124
|
+
return false if validate_type(field_values.type, actual_value) == false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
return true # true if no previous invalidation
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end # Validations
|
133
|
+
end # JSONdb
|