jungle_path 0.0.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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +22 -0
  6. data/README.md +5 -0
  7. data/jungle_path.gemspec +43 -0
  8. data/lib/jungle_path/api/helpers/auth.rb +45 -0
  9. data/lib/jungle_path/api/helpers/auth_local_user.rb +284 -0
  10. data/lib/jungle_path/api/helpers/auth_old.rb +232 -0
  11. data/lib/jungle_path/api/helpers/data_cache.rb +20 -0
  12. data/lib/jungle_path/api/helpers/defaults.rb +83 -0
  13. data/lib/jungle_path/api/helpers/logging.rb +36 -0
  14. data/lib/jungle_path/api/helpers/query_filters.rb +15 -0
  15. data/lib/jungle_path/api/helpers/rescues.rb +15 -0
  16. data/lib/jungle_path/api/helpers/result.rb +16 -0
  17. data/lib/jungle_path/api/helpers/standard_apis.rb +280 -0
  18. data/lib/jungle_path/api/helpers.rb +16 -0
  19. data/lib/jungle_path/api/template.erb +35 -0
  20. data/lib/jungle_path/api.rb +5 -0
  21. data/lib/jungle_path/app/a.gitignore +1 -0
  22. data/lib/jungle_path/app/api/server_base.rb +95 -0
  23. data/lib/jungle_path/app/api/server_custom.rb +121 -0
  24. data/lib/jungle_path/app/api/server_gen.rb +11 -0
  25. data/lib/jungle_path/app/auth/authorization.rb +96 -0
  26. data/lib/jungle_path/app/config/a.gitignore +1 -0
  27. data/lib/jungle_path/app/config/config.rb +240 -0
  28. data/lib/jungle_path/app/config/override.rb +3 -0
  29. data/lib/jungle_path/app/config.ru +28 -0
  30. data/lib/jungle_path/app/logs/log_files_go_here +0 -0
  31. data/lib/jungle_path/app/run.sh +4 -0
  32. data/lib/jungle_path/app/schemas/schema.rb +21 -0
  33. data/lib/jungle_path/app/schemas/schema_all_in_one.rb +181 -0
  34. data/lib/jungle_path/app.rb +8 -0
  35. data/lib/jungle_path/authentication/auth_provider/default.rb +83 -0
  36. data/lib/jungle_path/authentication/auth_provider.rb +7 -0
  37. data/lib/jungle_path/authentication/data_provider/default.rb +144 -0
  38. data/lib/jungle_path/authentication/data_provider.rb +7 -0
  39. data/lib/jungle_path/authentication/helpers.rb +19 -0
  40. data/lib/jungle_path/authentication/identity.rb +30 -0
  41. data/lib/jungle_path/authentication/password_hash.rb +124 -0
  42. data/lib/jungle_path/authentication.rb +9 -0
  43. data/lib/jungle_path/authorization/filter.rb +106 -0
  44. data/lib/jungle_path/authorization/paths.rb +71 -0
  45. data/lib/jungle_path/authorization.rb +5 -0
  46. data/lib/jungle_path/cache.rb +36 -0
  47. data/lib/jungle_path/config.rb +65 -0
  48. data/lib/jungle_path/controller/authentication.rb +129 -0
  49. data/lib/jungle_path/controller/base.rb +193 -0
  50. data/lib/jungle_path/controller/helpers.rb +47 -0
  51. data/lib/jungle_path/controller/template.erb +14 -0
  52. data/lib/jungle_path/controller.rb +7 -0
  53. data/lib/jungle_path/db_access/import/db_dir.rb +74 -0
  54. data/lib/jungle_path/db_access/import/delete.rb +30 -0
  55. data/lib/jungle_path/db_access/import/insert.rb +168 -0
  56. data/lib/jungle_path/db_access/import/schema.rb +34 -0
  57. data/lib/jungle_path/db_access/import/select.rb +68 -0
  58. data/lib/jungle_path/db_access/import.rb +15 -0
  59. data/lib/jungle_path/db_access/io/chunked_file_reader.rb +62 -0
  60. data/lib/jungle_path/db_access/io/config.rb +19 -0
  61. data/lib/jungle_path/db_access/io/copy.rb +73 -0
  62. data/lib/jungle_path/db_access/io/db.rb +82 -0
  63. data/lib/jungle_path/db_access/io/delete.rb +23 -0
  64. data/lib/jungle_path/db_access/io/init_db.rb +39 -0
  65. data/lib/jungle_path/db_access/io/insert.rb +24 -0
  66. data/lib/jungle_path/db_access/io/schema.rb +21 -0
  67. data/lib/jungle_path/db_access/io/select.rb +44 -0
  68. data/lib/jungle_path/db_access/io/update.rb +36 -0
  69. data/lib/jungle_path/db_access/io.rb +104 -0
  70. data/lib/jungle_path/db_model/column.rb +186 -0
  71. data/lib/jungle_path/db_model/params.rb +60 -0
  72. data/lib/jungle_path/db_model/schema.rb +100 -0
  73. data/lib/jungle_path/db_model/string.rb +9 -0
  74. data/lib/jungle_path/db_model/table.rb +307 -0
  75. data/lib/jungle_path/db_model.rb +34 -0
  76. data/lib/jungle_path/exceptions.rb +10 -0
  77. data/lib/jungle_path/gen/api.rb +52 -0
  78. data/lib/jungle_path/gen/controller.rb +0 -0
  79. data/lib/jungle_path/gen/db.rb +0 -0
  80. data/lib/jungle_path/gen/schema.rb +47 -0
  81. data/lib/jungle_path/gen/schema_tree/filter.rb +33 -0
  82. data/lib/jungle_path/gen/schema_tree/match_columns.rb +54 -0
  83. data/lib/jungle_path/gen/schema_tree/match_table_data.rb +22 -0
  84. data/lib/jungle_path/gen/schema_tree/match_tables.rb +70 -0
  85. data/lib/jungle_path/gen/schema_tree/node.rb +39 -0
  86. data/lib/jungle_path/gen/schema_tree.rb +105 -0
  87. data/lib/jungle_path/gen.rb +9 -0
  88. data/lib/jungle_path/json/base.rb +29 -0
  89. data/lib/jungle_path/json/time.rb +8 -0
  90. data/lib/jungle_path/json.rb +6 -0
  91. data/lib/jungle_path/logging.rb +23 -0
  92. data/lib/jungle_path/query/alias_info.rb +16 -0
  93. data/lib/jungle_path/query/engine.rb +878 -0
  94. data/lib/jungle_path/query/entity.rb +141 -0
  95. data/lib/jungle_path/query/field.rb +28 -0
  96. data/lib/jungle_path/query/field_primary_key.rb +27 -0
  97. data/lib/jungle_path/query/filter.rb +34 -0
  98. data/lib/jungle_path/query/float_value.rb +16 -0
  99. data/lib/jungle_path/query/from.rb +33 -0
  100. data/lib/jungle_path/query/int_value.rb +16 -0
  101. data/lib/jungle_path/query/limit.rb +19 -0
  102. data/lib/jungle_path/query/nested_hash_sorter.rb +94 -0
  103. data/lib/jungle_path/query/operator.rb +17 -0
  104. data/lib/jungle_path/query/query.rb +23 -0
  105. data/lib/jungle_path/query/sort_field.rb +34 -0
  106. data/lib/jungle_path/query/sql_string.rb +145 -0
  107. data/lib/jungle_path/query/string_value.rb +16 -0
  108. data/lib/jungle_path/query.rb +19 -0
  109. data/lib/jungle_path/rack/basic_credentials.rb +70 -0
  110. data/lib/jungle_path/rack/json_body_parser.rb +41 -0
  111. data/lib/jungle_path/rack.rb +6 -0
  112. data/lib/jungle_path/schema/auth.rb +83 -0
  113. data/lib/jungle_path/schema/base.rb +6 -0
  114. data/lib/jungle_path/schema/db.rb +10 -0
  115. data/lib/jungle_path/schema/version.rb +19 -0
  116. data/lib/jungle_path/schema.rb +8 -0
  117. data/lib/jungle_path/sql/auth_local_user.rb +5 -0
  118. data/lib/jungle_path/sql/general.rb +10 -0
  119. data/lib/jungle_path/sql/helpers.rb +11 -0
  120. data/lib/jungle_path/sql/key.rb +107 -0
  121. data/lib/jungle_path/sql/query_filter.rb +5 -0
  122. data/lib/jungle_path/sql/role.rb +5 -0
  123. data/lib/jungle_path/sql/user.rb +35 -0
  124. data/lib/jungle_path/sql/user_role.rb +5 -0
  125. data/lib/jungle_path/sql.rb +12 -0
  126. data/lib/jungle_path.rb +13 -0
  127. data/test.rb +33 -0
  128. data/test2.rb +15 -0
  129. metadata +200 -0
@@ -0,0 +1,24 @@
1
+ module JunglePath
2
+ module DBAccess
3
+ module IO
4
+ require 'jungle_path/db_access/io/init_db'
5
+
6
+ class Insert
7
+ include JunglePath::DBAccess::IO::InitDB
8
+
9
+ def _model(model)
10
+ insert = handle_json_columns(model, model._has_value_hash)
11
+ puts "inserting: #{insert}."
12
+ #@db[model._table_name] << insert
13
+ result = @db[model._table_name].insert(insert)
14
+ if model._primary_key_columns.count == 1
15
+ model._values[model._primary_key_columns.keys.first] = result
16
+ end
17
+ model._secure = false #allow 'secure' columns to be included in hash.
18
+ model = model.class.new(model.to_hash, false) # create a new model instance with all values marked as unmodified.
19
+ model
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module JunglePath
2
+ require 'jungle_path/db_model/schema'
3
+
4
+ module DBAccess
5
+ module IO
6
+ require 'jungle_path/db_access/io/init_db'
7
+
8
+ class Schema
9
+ include JunglePath::DBAccess::IO::InitDB
10
+
11
+ def drop_table(table_class)
12
+ JunglePath::DBModel::Schema.new(@db).drop_table table_class
13
+ end
14
+
15
+ def create_table(table_class)
16
+ JunglePath::DBModel::Schema.new(@db).create_table table_class
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ module JunglePath
2
+ module DBAccess
3
+ module IO
4
+ require 'jungle_path/db_access/io/init_db'
5
+
6
+ class Select
7
+ include JunglePath::DBAccess::IO::InitDB
8
+
9
+ def _model(model)
10
+ # select based on a model's primary key.
11
+ ds = @db[model._table_name].where(model._primary_key)
12
+ #puts ds.sql
13
+ hash = ds.first
14
+ return nil unless hash
15
+ new_model = model.class.new(hash, false) # false since row (initial values) from db is considered unmodified.
16
+ end
17
+
18
+ def _model_by_any(model)
19
+ ds = @db[model._table_name].where(handle_json_columns(model, model._modified_hash))
20
+ #puts ds.sql
21
+ hash = ds.first
22
+ #puts "hash: #{hash}. Nil? #{hash == nil}."
23
+ return nil unless hash
24
+ new_model = model.class.new(hash, false) # false since row (initial values) from db is considered unmodified.
25
+ end
26
+
27
+ def _models(model, *order_by)
28
+ # select all of a given model.
29
+ ds = @db[model._table_name]
30
+ ds = ds.where(handle_json_columns(model, model._has_value_hash)) if model._has_value_hash.length > 0
31
+ ds = ds.order(*order_by) if order_by.length > 0
32
+ ds = ds.order(model._primary_key_columns.keys) unless order_by.length > 0
33
+ #puts ds.sql
34
+ rows = ds.all
35
+ models = []
36
+ rows.each do |row|
37
+ models << model.class.new(row, false)
38
+ end
39
+ models
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,36 @@
1
+ module JunglePath
2
+ module DBAccess
3
+ module IO
4
+ require 'jungle_path/db_access/io/init_db'
5
+
6
+ class Update
7
+ include JunglePath::DBAccess::IO::InitDB
8
+
9
+ def _model(model)
10
+ update = handle_json_columns(model, model._modified_hash)
11
+ count = update_by_primary_key model, update
12
+ return {update_count: count}
13
+ end
14
+
15
+ def _models(model_filter, model_values, confirm=false)
16
+ ds = @db[model_filter._table_name].where(handle_json_columns(model_filter, model_filter._has_value_hash))
17
+ #puts ds.sql
18
+ #puts "set values: #{model_values._has_value_hash}."
19
+ count = 0
20
+ count = ds.update(handle_json_columns(model_values, model_values._has_value_hash)) if confirm
21
+ return {update_count: count}
22
+ end
23
+
24
+ private
25
+
26
+ def update_by_primary_key model, update
27
+ @db.transaction do
28
+ ds = @db[model._table_name].where(model._primary_key).for_update
29
+ #puts ds.sql
30
+ ds.update update
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,104 @@
1
+ require 'sequel'
2
+
3
+ module JunglePath
4
+ module DBAccess
5
+ module IO
6
+ require 'jungle_path/db_access/io/chunked_file_reader'
7
+ require 'jungle_path/db_access/io/config'
8
+ require 'jungle_path/db_access/io/copy'
9
+ require 'jungle_path/db_access/io/db'
10
+ require 'jungle_path/db_access/io/delete'
11
+ require 'jungle_path/db_access/io/init_db'
12
+ require 'jungle_path/db_access/io/insert'
13
+ require 'jungle_path/db_access/io/schema'
14
+ require 'jungle_path/db_access/io/select'
15
+ require 'jungle_path/db_access/io/update'
16
+
17
+ def self.connection_from_config(config)
18
+ connection(
19
+ database_type: config.type,
20
+ user_name: config.user_name,
21
+ database_name: config.name,
22
+ host: config.host,
23
+ extensions: config.extensions,
24
+ password: config.password,
25
+ port: config.port,
26
+ options: config.options
27
+ )
28
+ end
29
+
30
+ def self.connection_from_config_unknown_database(config)
31
+ if config.type == 'postgres'
32
+ connection_from_config_use_postgres_db(config)
33
+ elsif config.type == 'tinytds'
34
+ connection_from_config_use_ms_sql_server_db(config)
35
+ else
36
+ throw "Unknown database type: #{config.type}."
37
+ end
38
+ end
39
+
40
+ def self.connection_from_config_use_ms_sql_server_db(config)
41
+ db = connection(
42
+ database_type: config.type,
43
+ user_name: config.user_name,
44
+ database_name: 'master',
45
+ host: config.host,
46
+ extensions: config.extensions,
47
+ password: config.password,
48
+ port: config.port,
49
+ options: config.options
50
+ )
51
+ end
52
+
53
+ def self.connection_from_config_use_postgres_db(config)
54
+ db = connection(
55
+ database_type: config.type,
56
+ user_name: config.user_name,
57
+ database_name: 'postgres',
58
+ host: config.host,
59
+ extensions: config.extensions,
60
+ password: config.password,
61
+ port: config.port,
62
+ options: config.options
63
+ )
64
+ end
65
+
66
+ def self.clone_config(config)
67
+ JunglePath::DBAccess::IO::Config.new(
68
+ name: config.name,
69
+ type: config.type,
70
+ user_name: config.user_name,
71
+ password: config.password,
72
+ host: config.host,
73
+ extensions: config.extensions,
74
+ port: config.port,
75
+ options: config.options
76
+ )
77
+ end
78
+
79
+ def self.connection(database_type:, user_name:, database_name:, host: "localhost", extensions: [], password: nil, port: nil, options: nil)
80
+ Sequel.default_timezone = :utc
81
+ colon_port = ":#{port}" if port
82
+ options = {} unless options
83
+ if password
84
+ puts "Using db connection with explicit password!"
85
+ connection_string = "#{database_type}://#{user_name}:#{password}@#{host}#{colon_port}/#{database_name}"
86
+ puts "connection_string: #{connection_string}."
87
+ db = Sequel.connect(connection_string, options)
88
+ puts "connected."
89
+ else
90
+ puts "no explicit pw."
91
+ connection_string = "#{database_type}://#{user_name}@#{host}#{colon_port}/#{database_name}"
92
+ puts "connection_string: #{connection_string}."
93
+ db = Sequel.connect(connection_string, options)
94
+ puts "connected."
95
+ end
96
+ extensions.each do |extension|
97
+ puts "Adding Sequel extension: #{extension}."
98
+ db.extension extension
99
+ end
100
+ db
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,186 @@
1
+ require 'set'
2
+
3
+ module JunglePath
4
+ module DBModel
5
+ class Column
6
+ attr_reader :name, :type, :base_type, :foreign_key_table_name, :sequence, :tags, :override_type
7
+ def initialize(sequence, name, type, primary_key=false, foreign_key=false, foreign_key_table_name=nil, not_null=false, unique=false, secure=false, alternate_key=false, calculated=false, desc=nil, index=nil, unique_index=nil, default_value=nil, tags=nil, override_type=nil)
8
+ @sequence = sequence
9
+ @name = name
10
+ @type = type
11
+ @override_type = override_type
12
+ @base_type = get_base_type(@type)
13
+ @primary_key = primary_key
14
+ @foreign_key = foreign_key
15
+ @foreign_key_table_name = foreign_key_table_name
16
+ @not_null = not_null
17
+ @unique = unique
18
+ @secure = secure
19
+ @alternate_key = alternate_key
20
+ @calculated = calculated
21
+ @desc = desc
22
+ @index = index
23
+ @unique_index = unique_index
24
+ @default_value = default_value
25
+ @tags = tags
26
+ @is_audit_column = audit_column_names.include? name
27
+ end
28
+
29
+ def primary_key?
30
+ @primary_key
31
+ end
32
+
33
+ def alternate_key?
34
+ @alternate_key
35
+ end
36
+
37
+ def foreign_key?
38
+ @foreign_key
39
+ end
40
+
41
+ def not_null?
42
+ @not_null
43
+ end
44
+
45
+ def calculated?
46
+ @calculated
47
+ end
48
+
49
+ def calculated=(value)
50
+ @calculated = value
51
+ end
52
+
53
+ def unique?
54
+ @unique
55
+ end
56
+
57
+ def secure?
58
+ @secure
59
+ end
60
+
61
+ def audit_column_names
62
+ [:created_at, :updated_at, :created_by_key_id, :created_by_user_id, :updated_by_key_id, :updated_by_user_id].to_set
63
+ end
64
+
65
+ def is_audit_column?
66
+ @is_audit_column
67
+ end
68
+
69
+ def ruby_type
70
+ return Integer if @type == :foreign_key
71
+ return Integer if @type == :primary_key
72
+ return String if @type == :string
73
+ return Integer if @type == :integer
74
+ return DateTime if @type == :timestamp
75
+ return DateTime if @type == :timestamp_local
76
+ return TrueClass if @type == :boolean
77
+ return Date if @type == :date
78
+ return String if @type == :json
79
+ return String if @type == :jsonb
80
+ return Float if @type == :float
81
+ nil
82
+ end
83
+
84
+ def desc
85
+ @desc
86
+ end
87
+
88
+ def index
89
+ @index
90
+ end
91
+
92
+ def unique_index
93
+ @unique_index
94
+ end
95
+
96
+ def default_value
97
+ @default_value
98
+ end
99
+
100
+ def self.get_column_def_columns(column_definition, sequence)
101
+ return audit_key(sequence) if column_definition.length == 1 and column_definition[0] == :audit_key
102
+ return audit_user(sequence) if column_definition.length == 1 and column_definition[0] == :audit_user
103
+ return killable(sequence) if column_definition.length == 1 and column_definition[0] == :killable
104
+ return verification(sequence) if column_definition.length == 1 and column_definition[0] == :verification
105
+ return audit_data(sequence) if column_definition.length == 1 and column_definition[0] == :audit_data
106
+ normal(column_definition, (sequence))
107
+ end
108
+
109
+ private
110
+
111
+ def get_base_type(type)
112
+ base_type = type
113
+ if type == :primary_key or type == :foreign_key
114
+ base_type = :integer
115
+ end
116
+ base_type = override_type if override_type
117
+ base_type
118
+ end
119
+
120
+ def self.normal(array, sequence)
121
+ name = array[0]
122
+ type = array[1]
123
+ #type = :integer if array.include? :primary_key
124
+ #type = :integer if array.include? :foreign_key
125
+ primary_key = array.include? :primary_key
126
+ foreign_key = array.include? :foreign_key
127
+ foreign_key_table_name = array[array.index(:foreign_key) + 1] if foreign_key
128
+ not_null = ((array.include? :not_null) or primary_key)
129
+ unique = array.include? :unique
130
+
131
+ contains_unique_index = array.include? :unique_index
132
+ unique_index = array[array.index(:unique_index) + 1] if contains_unique_index
133
+
134
+ contains_index = array.include? :index
135
+ index = array[array.index(:index) + 1] if contains_index
136
+
137
+ secure = array.include? :secure
138
+ alternate_key = array.include? :alternate_key
139
+ calculated = array.include? :calculated
140
+ desc = array[array.index(:desc) + 1] if array.include? :desc
141
+ override_type = array[array.index(:override_type) + 1] if array.include? :override_type
142
+ default_index = array.index(:default)
143
+ default_value = array[default_index + 1] if default_index and default_index > 0
144
+ tags = array[array.index(:tags) + 1] if array.include? :tags
145
+
146
+ columns = [Column.new(sequence, name, type, primary_key, foreign_key, foreign_key_table_name, not_null, unique, secure, alternate_key, calculated, desc, index, unique_index, default_value, tags, override_type)]
147
+ end
148
+
149
+ def self.audit_key(sequence)
150
+ columns = [
151
+ normal([:created_at, :timestamp], sequence)[0],
152
+ normal([:created_by_key_id, :foreign_key, :key], sequence+1)[0],
153
+ normal([:updated_at, :timestamp], sequence+2)[0],
154
+ normal([:updated_by_key_id, :foreign_key, :key], sequence+3)[0]]
155
+ end
156
+
157
+ def self.audit_user(sequence)
158
+ columns = [
159
+ normal([:created_at, :timestamp], sequence)[0],
160
+ normal([:created_by_user_id, :foreign_key, :user], sequence+1)[0],
161
+ normal([:updated_at, :timestamp], sequence+2)[0],
162
+ normal([:updated_by_user_id, :foreign_key, :user], sequence+3)[0]]
163
+ end
164
+
165
+ def self.killable(sequence)
166
+ columns = [
167
+ normal([:active, :boolean], sequence)[0],
168
+ normal([:effective_date, :date], sequence+1)[0],
169
+ normal([:kill_date, :date], sequence+2)[0],
170
+ normal([:kill_by_key_id, :foreign_key, :key], sequence+3)[0],
171
+ normal([:kill_reason, :string], sequence+4)[0]]
172
+ end
173
+
174
+ def self.verification(sequence)
175
+ columns = [
176
+ normal([:verification, :json, :tags, [:verification, :approval]], sequence)[0]]
177
+ end
178
+
179
+ def self.audit_data(sequence)
180
+ columns = [
181
+ normal([:audit_data, :json], sequence)[0]]
182
+ end
183
+
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,60 @@
1
+ module JunglePath
2
+ module DBModel
3
+ module Params
4
+ def self.transform(params, columns)
5
+ # sinatra params come as string keys with string values.
6
+ # Convert values to various types based on Schema column definitions.
7
+ # Convert keys to symbols.
8
+ p = params.to_hash
9
+ p = symbolize(p)
10
+ p = convert_to_type(p, columns)
11
+ p
12
+ end
13
+
14
+ def self.symbolize(params)
15
+ p = params.to_hash
16
+ Hash[p.map {|k, v| [k.to_sym, v] }]
17
+ end
18
+
19
+ def self.convert_to_type(params, columns)
20
+ #params must be hash of symbols (as keys) and values
21
+ p = {}
22
+ params = params.to_hash
23
+ params.each do |k, v|
24
+ column = columns[k]
25
+ if column and v
26
+ #puts "column, type: #{k} #{column.type}."
27
+ if column.type == :integer or column.base_type == :integer
28
+ p[k] = v.to_i
29
+ elsif column.type == :timestamp and v.class == String
30
+ p[k] = Time.parse(v).utc
31
+ elsif column.type == :timestamp_local and v.class == String # experimental, probably won't use...
32
+ p[k] = Time.parse(v)
33
+ elsif column.type == :date and v.class == String
34
+ p[k] = Date.parse(v).to_time
35
+ elsif column.type == :date and v.class == Date
36
+ p[k] = v.to_time
37
+ elsif column.type == :boolean
38
+ p[k] = to_bool(v)
39
+ elsif (column.type == :string or column.base_type == :string) and v.class == String and v.strip.empty?
40
+ # treat empty/whitespace only strings as nil.
41
+ p[k] = nil
42
+ else
43
+ p[k] = v
44
+ end
45
+ else
46
+ p[k] = v
47
+ end
48
+ end
49
+ p
50
+ end
51
+
52
+ def self.to_bool(value)
53
+ return false if value == nil
54
+ return true if value == true || value =~ (/(true|t|yes|y|on|1)$/i)
55
+ return false if value == false || value.empty? || value =~ (/(false|f|no|n|off|0)$/i)
56
+ raise ArgumentError.new("invalid value for Boolean: \"#{value}\"")
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,100 @@
1
+ module JunglePath
2
+ module DBModel
3
+ class Schema
4
+ def initialize db
5
+ # db should be a "Sequel" db object that is connected to some database.
6
+ @db = db
7
+ end
8
+
9
+ def get_sequel_method type
10
+ return 'foreign_key' if type == :foreign_key
11
+ return 'primary_key' if type == :primary_key
12
+ return 'String' if type == :string
13
+ return 'Integer' if type == :integer
14
+ return 'DateTime' if type == :timestamp
15
+ return 'DateTime' if type == :timestamp_local
16
+ return 'TrueClass' if type == :boolean
17
+ return 'Date' if type == :date
18
+ return 'json' if type == :json
19
+ return 'jsonb' if type == :jsonb
20
+ return 'Float' if type == :float
21
+ return type
22
+ end
23
+
24
+ def get_postgresql_override_type type
25
+ return 'text' if type == :string
26
+ return 'integer' if type == :integer
27
+ return 'bigint' if type == :bigint
28
+ return 'timestamp' if type == :timestamp
29
+ return 'timestamp' if type == :timestamp_local
30
+ return 'boolean' if type == :boolean
31
+ return 'date' if type == :date
32
+ return 'json' if type == :json
33
+ return 'jsonb' if type == :jsonb
34
+ return 'double' if type == :float
35
+ return type.to_s
36
+ end
37
+
38
+ def create_table table_class
39
+ # translate column type keys into Sequel methods used by Sequel (DB.create_table).
40
+
41
+ # call the Sequel DB.create_table method with a block:
42
+ #puts "\ttable_name: #{table_class.table_name}"
43
+ schema = self
44
+ @db.create_table? table_class.table_name do
45
+ made_pk = false
46
+ table_class.columns.each_value do |column|
47
+ puts "\tcolumn: #{column.name} #{schema.get_sequel_method(column.type)} #{column.foreign_key_table_name}."
48
+ method = schema.get_sequel_method(column.type)
49
+ args_hash = {}
50
+ if column.foreign_key? and column.not_null?
51
+ #args = [column.name, column.foreign_key_table_name, :null=>false]
52
+ args = [column.name, column.foreign_key_table_name]
53
+ args_hash[:null] = false
54
+ elsif column.foreign_key?
55
+ args = [column.name, column.foreign_key_table_name]
56
+ elsif column.primary_key?
57
+ args = [column.name]
58
+ #made_pk = true
59
+ else
60
+ args = [column.name]
61
+ end
62
+ args_hash[:unique] = true if column.unique?
63
+ args_hash[:null] = false if column.not_null?
64
+ args_hash[:type] = schema.get_postgresql_override_type(column.override_type) unless column.override_type == nil
65
+ args_hash[:default] = column.default_value unless column.default_value == nil
66
+ args << args_hash
67
+ #puts "\t\tmethod: #{method}. args:#{args}.\n"
68
+ made_pk = true if column.type == :primary_key # only happens when pk is single column.
69
+ puts "column: #{column.name}, override_type: #{column.override_type}, override_type.class: #{column.override_type.class}, method: #{method}, args: #{args}."
70
+ send(method, *args)
71
+
72
+ #index:
73
+ if column.index
74
+ send('index', column.index)
75
+ end
76
+
77
+ #unique index:
78
+ if column.unique_index
79
+ send('unique', column.unique_index)
80
+ end
81
+ end
82
+
83
+ if not made_pk
84
+ #puts "creating primary_key for table #{table_class.name}. keys: #{table_class.primary_key_columns.keys}."
85
+ send('primary_key', table_class.primary_key_columns.keys, :name=>"#{table_class.table_name}_pk".to_sym)
86
+ end
87
+ #puts "end of block"
88
+ end
89
+ end
90
+
91
+ def create_table! table_class
92
+ nil
93
+ end
94
+
95
+ def drop_table table_class
96
+ @db.drop_table? table_class.table_name
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,9 @@
1
+ class ::String
2
+ def underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+ end