webink 1.3.3 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/webink/database.rb +67 -48
- data/lib/webink/model.rb +166 -103
- metadata +3 -3
data/lib/webink/database.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Ink
|
2
2
|
|
3
3
|
# = Database class
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# == Config
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# Currently there are two types of databases supported, MySQL and
|
8
8
|
# SQLite3. Either way, you need to specify them in a config-file
|
9
9
|
# that is located inside the web project folder.
|
@@ -39,6 +39,16 @@ module Ink
|
|
39
39
|
# This is the most basic query, it returns an Array of results,
|
40
40
|
# and each element contains a Hash of column_name => column_entry.
|
41
41
|
#
|
42
|
+
# Ink::Database.database.query("SELECT * FROM x;", Array){ |itm, k, v|
|
43
|
+
# itm.push v
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# The query method has a second parameter "type" which defaults to Hash.
|
47
|
+
# This is the class instance created in the resultset array (i.e.
|
48
|
+
# query returns [ type, type, type,...]).
|
49
|
+
# A block allows you to assign the k (column name) and v (value) to itm
|
50
|
+
# (a type.new taken from the second parameter) however you like.
|
51
|
+
#
|
42
52
|
# The following methods are convenience methods to access data for
|
43
53
|
# models. As example a model Apple and its n:1 relation to Tree
|
44
54
|
# are used. Please note that both class and database table name can
|
@@ -86,14 +96,14 @@ module Ink
|
|
86
96
|
# This will return a date in the form of 2012-11-20 10:00:02 and takes a Time
|
87
97
|
# instance.
|
88
98
|
#
|
89
|
-
#
|
99
|
+
#
|
90
100
|
#
|
91
101
|
class Database
|
92
102
|
private_class_method :new
|
93
103
|
@@database = nil
|
94
|
-
|
104
|
+
|
95
105
|
# Private Constructor
|
96
|
-
#
|
106
|
+
#
|
97
107
|
# Uses the config parameter to create a database
|
98
108
|
# connection, and will throw an error, if that is not
|
99
109
|
# possible.
|
@@ -109,32 +119,32 @@ module Ink
|
|
109
119
|
raise ArgumentError.new("Database undefined.")
|
110
120
|
end
|
111
121
|
end
|
112
|
-
|
122
|
+
|
113
123
|
# Class method
|
114
|
-
#
|
124
|
+
#
|
115
125
|
# Instanciates a new Database if none is found
|
116
126
|
# [param config:] Hash of config parameters
|
117
127
|
def self.create(config)
|
118
128
|
@@database = new(config) if not @@database
|
119
129
|
end
|
120
|
-
|
130
|
+
|
121
131
|
# Class method
|
122
|
-
#
|
132
|
+
#
|
123
133
|
# Removes an instanciated Database
|
124
134
|
def self.drop
|
125
135
|
@@database = nil if @@database
|
126
136
|
end
|
127
|
-
|
137
|
+
|
128
138
|
# Class method
|
129
|
-
#
|
139
|
+
#
|
130
140
|
# Returns the Database instance or raises a Runtime Error
|
131
141
|
# [returns:] Database instance
|
132
142
|
def self.database
|
133
143
|
(@@database) ? @@database : (raise RuntimeError.new("No Database found. Create one first"))
|
134
144
|
end
|
135
|
-
|
145
|
+
|
136
146
|
# Instance method
|
137
|
-
#
|
147
|
+
#
|
138
148
|
# This will retrieve all tables nested into
|
139
149
|
# the connected database.
|
140
150
|
# [returns:] Array of tables
|
@@ -158,50 +168,59 @@ module Ink
|
|
158
168
|
end
|
159
169
|
result
|
160
170
|
end
|
161
|
-
|
171
|
+
|
162
172
|
# Instance method
|
163
|
-
#
|
173
|
+
#
|
164
174
|
# Send an SQL query string to the database
|
165
175
|
# and retrieve a result set
|
166
176
|
# [param query:] SQL query string
|
167
177
|
# [returns:] Array of Hashes of column_name => column_entry
|
168
|
-
def query(query)
|
178
|
+
def query(query, type=Hash)
|
179
|
+
type = Hash if not block_given?
|
169
180
|
result = Array.new
|
170
181
|
if @type == "mysql"
|
171
182
|
re = @db.method("query").call query
|
172
183
|
if re
|
173
184
|
re.each_hash do |row|
|
174
|
-
result.push
|
185
|
+
result.push type.new
|
175
186
|
row.each do |k,v|
|
176
187
|
if v =~ /^[0-9]+$/
|
177
188
|
v = $&.to_i
|
178
189
|
elsif v =~ /^[0-9]+\.[0-9]+$/
|
179
190
|
v = $&.to_f
|
180
191
|
end
|
181
|
-
|
192
|
+
if block_given?
|
193
|
+
yield(result[result.length-1], k, v)
|
194
|
+
else
|
195
|
+
result[result.length-1][k] = v
|
196
|
+
end
|
182
197
|
end
|
183
198
|
end
|
184
199
|
end
|
185
200
|
elsif @type == "sqlite3"
|
186
201
|
re = @db.method("query").call query
|
187
202
|
re.each do |row|
|
188
|
-
result.push
|
189
|
-
|
203
|
+
result.push type.new
|
204
|
+
re.columns.each_index do |i|
|
190
205
|
if row[i] =~ /^[0-9]+$/
|
191
206
|
row[i] = $&.to_i
|
192
207
|
elsif row[i] =~ /^[0-9]+\.[0-9]+$/
|
193
208
|
row[i] = $&.to_f
|
194
209
|
end
|
195
|
-
|
210
|
+
if block_given?
|
211
|
+
yield(result[result.length-1], re.columns[i], row[i])
|
212
|
+
else
|
213
|
+
result[result.length-1][re.columns[i]] = row[i]
|
214
|
+
end
|
196
215
|
end
|
197
216
|
end
|
198
217
|
re.close if not re.closed?
|
199
218
|
end
|
200
219
|
result
|
201
220
|
end
|
202
|
-
|
221
|
+
|
203
222
|
# Instance method
|
204
|
-
#
|
223
|
+
#
|
205
224
|
# Closes the database connection, there is no way
|
206
225
|
# to reopen without creating a new Ink::Database instance
|
207
226
|
def close
|
@@ -215,9 +234,9 @@ module Ink
|
|
215
234
|
end
|
216
235
|
self.class.drop
|
217
236
|
end
|
218
|
-
|
237
|
+
|
219
238
|
# Instance method
|
220
|
-
#
|
239
|
+
#
|
221
240
|
# Attempts to fetch the last inserted primary key
|
222
241
|
# [param class_name:] Defines the __table__ name or class
|
223
242
|
# [returns:] primary key or nil
|
@@ -229,9 +248,9 @@ module Ink
|
|
229
248
|
response = self.query("SELECT MAX(#{pk_name}) as id FROM #{table_name};")
|
230
249
|
return (response.length > 0) ? response[0]["id"] : nil
|
231
250
|
end
|
232
|
-
|
251
|
+
|
233
252
|
# Instance method
|
234
|
-
#
|
253
|
+
#
|
235
254
|
# Creates the SQL syntax for the chosen database type
|
236
255
|
# to define a primary key, autoincrementing field
|
237
256
|
# [returns:] SQL syntax for a primary key field
|
@@ -244,9 +263,9 @@ module Ink
|
|
244
263
|
end
|
245
264
|
result
|
246
265
|
end
|
247
|
-
|
266
|
+
|
248
267
|
# Instance method
|
249
|
-
#
|
268
|
+
#
|
250
269
|
# Delete something from the database.
|
251
270
|
# [param class_name:] Defines the class name or class
|
252
271
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
@@ -255,9 +274,9 @@ module Ink
|
|
255
274
|
return if not table_name
|
256
275
|
self.query("DELETE FROM #{table_name} #{params};")
|
257
276
|
end
|
258
|
-
|
277
|
+
|
259
278
|
# Instance method
|
260
|
-
#
|
279
|
+
#
|
261
280
|
# Retrieve class instances, that are loaded with the database result set.
|
262
281
|
# [param class_name:] Defines the class name or class which should be queried
|
263
282
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
@@ -267,7 +286,7 @@ module Ink
|
|
267
286
|
result = Array.new
|
268
287
|
table_name = c.table_name
|
269
288
|
return result if not table_name
|
270
|
-
|
289
|
+
|
271
290
|
re = self.query("SELECT * FROM #{table_name} #{params};")
|
272
291
|
re.each do |entry|
|
273
292
|
instance = c.new entry
|
@@ -275,9 +294,9 @@ module Ink
|
|
275
294
|
end
|
276
295
|
result
|
277
296
|
end
|
278
|
-
|
297
|
+
|
279
298
|
# Instance method
|
280
|
-
#
|
299
|
+
#
|
281
300
|
# Retrieve class2 instances, that are related to the class1 instance with
|
282
301
|
# primary key class1_id. This is done via an additional relationship table.
|
283
302
|
# Only relevant for many_many relationships.
|
@@ -308,9 +327,9 @@ module Ink
|
|
308
327
|
end
|
309
328
|
result
|
310
329
|
end
|
311
|
-
|
330
|
+
|
312
331
|
# Instance method
|
313
|
-
#
|
332
|
+
#
|
314
333
|
# Retrieve class2 instances, that are related to the class1 instance with
|
315
334
|
# primary key class1_id. Not relevant for many_many relationships
|
316
335
|
# [param class1:] Reference classname or class
|
@@ -336,16 +355,16 @@ module Ink
|
|
336
355
|
else
|
337
356
|
re = self.query "SELECT * FROM #{tablename2} WHERE #{fk1} = #{class1_id} #{params};"
|
338
357
|
end
|
339
|
-
|
358
|
+
|
340
359
|
re.each do |entry|
|
341
360
|
instance = c2.new entry
|
342
361
|
result.push instance
|
343
362
|
end
|
344
363
|
result
|
345
364
|
end
|
346
|
-
|
365
|
+
|
347
366
|
# Instance method
|
348
|
-
#
|
367
|
+
#
|
349
368
|
# Retrieve one class2 instance, that is related to the class1 instance with
|
350
369
|
# primary key class1_id. Only relevant for one_one and one_many relationships
|
351
370
|
# [param class1:] Reference classname or class
|
@@ -361,9 +380,9 @@ module Ink
|
|
361
380
|
nil
|
362
381
|
end
|
363
382
|
end
|
364
|
-
|
383
|
+
|
365
384
|
# Instance method
|
366
|
-
#
|
385
|
+
#
|
367
386
|
# This method attempts to remove all existing relationship data
|
368
387
|
# of instance with link of type: type. For one_one relationships
|
369
388
|
# this works only one way, requiring a second call later on before
|
@@ -392,9 +411,9 @@ module Ink
|
|
392
411
|
@db.query "DELETE FROM #{union_class} WHERE #{instance.class.foreign_key[0]}=#{value};"
|
393
412
|
end
|
394
413
|
end
|
395
|
-
|
414
|
+
|
396
415
|
# Instance method
|
397
|
-
#
|
416
|
+
#
|
398
417
|
# Attempt to create links of instance to the data inside value.
|
399
418
|
# link is the class of the related data, and type refers to the
|
400
419
|
# relationship type of the two. When one tries to insert an array
|
@@ -422,9 +441,9 @@ module Ink
|
|
422
441
|
self.create_link instance, link, type, fk
|
423
442
|
end
|
424
443
|
end
|
425
|
-
|
444
|
+
|
426
445
|
# Instance method
|
427
|
-
#
|
446
|
+
#
|
428
447
|
# Creates a link between instance and a link with primary fk.
|
429
448
|
# The relationship between the two is defined by type. one_one
|
430
449
|
# relationships are placing an additional call to delete_all_links
|
@@ -462,7 +481,7 @@ module Ink
|
|
462
481
|
@db.query "INSERT INTO #{union_class} (#{instance.class.foreign_key[0]}, #{link.foreign_key[0]}) VALUES (#{value}, #{fk});"
|
463
482
|
end
|
464
483
|
end
|
465
|
-
|
484
|
+
|
466
485
|
# Class method
|
467
486
|
#
|
468
487
|
# Formats a Time object according to the SQL TimeDate standard
|
@@ -471,7 +490,7 @@ module Ink
|
|
471
490
|
def self.format_date(date)
|
472
491
|
(date.instance_of? Time) ? date.strftime("%Y-%m-%d %H:%M:%S") : ""
|
473
492
|
end
|
474
|
-
|
493
|
+
|
475
494
|
end
|
476
|
-
|
495
|
+
|
477
496
|
end
|
data/lib/webink/model.rb
CHANGED
@@ -8,6 +8,7 @@ module Ink
|
|
8
8
|
# class called Apple < Ink::Model
|
9
9
|
#
|
10
10
|
# apple = Apple.new {:color => "red", :diameter => 4}
|
11
|
+
# apple = Apple.new [ "red", 4 ]
|
11
12
|
#
|
12
13
|
# The constructor checks, if there are class methods 'fields'
|
13
14
|
# and 'foreign' defined. If that check is positive, it will
|
@@ -15,6 +16,9 @@ module Ink
|
|
15
16
|
# the database, and throw an exception if fields is lacking
|
16
17
|
# an entry (excluded the primary key). The other case just
|
17
18
|
# creates an Apple with the Hash as instance variables.
|
19
|
+
# An alternate method of creating a new apple is by providing
|
20
|
+
# an Array of values in the same order as in the fields
|
21
|
+
# definition.
|
18
22
|
#
|
19
23
|
# puts apple.color
|
20
24
|
#
|
@@ -83,7 +87,7 @@ module Ink
|
|
83
87
|
# many_many, many_one]
|
84
88
|
# Obviously the Tree class requires a foreign with "Apple"
|
85
89
|
# mapped to "many_one" to match this schema.
|
86
|
-
#
|
90
|
+
#
|
87
91
|
# You can override the automatically generated getters and
|
88
92
|
# setters in any Model class you create by just redefining
|
89
93
|
# the methods.
|
@@ -91,12 +95,13 @@ module Ink
|
|
91
95
|
# == Convenience methods
|
92
96
|
#
|
93
97
|
# self.primary_key
|
98
|
+
# self.primary_key_type
|
94
99
|
# self.foreign_key
|
100
|
+
# self.foreign_key_type
|
95
101
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
# combination of "classname"_"primary_key" (i.e. "apple_id")
|
102
|
+
# primary_key is the name of the primary key (default "id").
|
103
|
+
# The foreign_key has a combination of "classname"_"primary_key"
|
104
|
+
# (i.e. "apple_id")
|
100
105
|
#
|
101
106
|
# self.class_name
|
102
107
|
#
|
@@ -118,89 +123,131 @@ module Ink
|
|
118
123
|
#
|
119
124
|
#
|
120
125
|
class Model
|
121
|
-
|
126
|
+
|
122
127
|
# Constructor
|
123
128
|
#
|
124
129
|
# Keys from the data parameter will be converted into
|
125
130
|
# instance variables with getters and setters in place.
|
131
|
+
# The data parameter can be an Array of length of the
|
132
|
+
# defined fields or without the primary key. The order
|
133
|
+
# needs to be the same as the defined fields.
|
126
134
|
# The primary key has no setter, but adds a getter called
|
127
135
|
# pk for convenience.
|
128
|
-
# [param data:] Hash of String => Objects
|
136
|
+
# [param data:] Hash of String => Objects or Array of Objects
|
129
137
|
def initialize(data)
|
130
138
|
if self.class.respond_to? :fields
|
139
|
+
i = 0
|
131
140
|
self.class.fields.each do |k,v|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
entry = nil
|
137
|
-
elsif data[k.to_s].is_a? String
|
138
|
-
entry = data[k.to_s].gsub(/'/, ''')
|
139
|
-
elsif data[k.to_s].is_a? Numeric
|
140
|
-
entry = data[k.to_s]
|
141
|
+
if data.is_a? Array
|
142
|
+
raise LoadError.new("Model cannot be loaded, wrong number or arguments #{data.length} expected #{self.class.fields.length} or #{self.class.fields.length - 1}") if data.length < self.class.fields.length - 1 or data.length > self.class.fields.length
|
143
|
+
init_field k, data[i] if self.class.primary_key != k or data.length == self.class.fields.length
|
144
|
+
i += 1
|
141
145
|
else
|
142
|
-
|
143
|
-
|
144
|
-
instance_variable_set("@#{k}", entry)
|
145
|
-
|
146
|
-
if not self.respond_to? k
|
147
|
-
self.class.send(:define_method, k) do
|
148
|
-
instance_variable_get "@#{k}"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
if self.class.primary_key[0] != k
|
152
|
-
if not self.respond_to? "#{k}="
|
153
|
-
self.class.send(:define_method, "#{k}=") do |val|
|
154
|
-
if data[k.to_s].nil?
|
155
|
-
val = nil
|
156
|
-
elsif val.is_a? String
|
157
|
-
val = val.gsub(/'/, ''')
|
158
|
-
elsif val.is_a? Numeric
|
159
|
-
val = val
|
160
|
-
else
|
161
|
-
val = "\'#{val}\'"
|
162
|
-
end
|
163
|
-
instance_variable_set "@#{k}", val
|
164
|
-
end
|
165
|
-
end
|
166
|
-
else
|
167
|
-
self.class.send(:define_method, "pk") do
|
168
|
-
instance_variable_get "@#{k.to_s.downcase}"
|
169
|
-
end
|
146
|
+
raise LoadError.new("Model cannot be loaded, argument missing: #{key}") if not data.key?(k.to_s) and self.class.primary_key != k
|
147
|
+
init_field k, data[k.to_s]
|
170
148
|
end
|
171
149
|
end
|
172
150
|
if self.class.respond_to? :foreign
|
173
151
|
self.class.foreign.each do |k,v|
|
174
|
-
|
175
|
-
raise NameError.new("Model cannot use #{k_table} as foreign, it already exists") if k_table == "pk"
|
176
|
-
if not self.respond_to? k_table
|
177
|
-
instance_variable_set("@#{k_table}", nil)
|
178
|
-
self.class.send(:define_method, k_table) do
|
179
|
-
instance_variable_get "@#{k_table}"
|
180
|
-
end
|
181
|
-
self.class.send(:define_method, "#{k_table}=") do |val|
|
182
|
-
instance_variable_set "@#{k_table}", val
|
183
|
-
end
|
184
|
-
end
|
152
|
+
init_foreign k
|
185
153
|
end
|
186
154
|
end
|
187
155
|
else
|
188
156
|
data.each do |k,v|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
157
|
+
init_no_fields k, v
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Private instance method
|
163
|
+
#
|
164
|
+
# Provides an instance accessor and setter for the key. It is
|
165
|
+
# initialized with data[key].
|
166
|
+
# [key:] String
|
167
|
+
# [data:] Hash of String => Object
|
168
|
+
def init_field(key, value)
|
169
|
+
raise NameError.new("Model cannot use #{key} as field, it is blocked by primary key") if key.to_s.downcase == "pk"
|
170
|
+
entry = nil
|
171
|
+
if value.nil?
|
172
|
+
entry = nil
|
173
|
+
elsif value.is_a? String
|
174
|
+
entry = value.gsub(/'/, ''')
|
175
|
+
elsif value.is_a? Numeric
|
176
|
+
entry = value
|
177
|
+
else
|
178
|
+
entry = "\'#{value}\'"
|
179
|
+
end
|
180
|
+
instance_variable_set("@#{key}", entry)
|
181
|
+
|
182
|
+
if not self.respond_to? key
|
183
|
+
self.class.send(:define_method, key) do
|
184
|
+
instance_variable_get "@#{key}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
if self.class.primary_key != key
|
188
|
+
if not self.respond_to? "#{key}="
|
189
|
+
self.class.send(:define_method, "#{key}=") do |val|
|
190
|
+
if val.nil?
|
191
|
+
val = nil
|
192
|
+
elsif val.is_a? String
|
193
|
+
val = val.gsub(/'/, ''')
|
194
|
+
elsif val.is_a? Numeric
|
195
|
+
val = val
|
196
|
+
else
|
197
|
+
val = "\'#{val}\'"
|
198
|
+
end
|
199
|
+
instance_variable_set "@#{key}", val
|
198
200
|
end
|
199
|
-
|
201
|
+
end
|
202
|
+
else
|
203
|
+
self.class.send(:define_method, "pk") do
|
204
|
+
instance_variable_get "@#{key.to_s.downcase}"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
private :init_field
|
209
|
+
|
210
|
+
# Private instance method
|
211
|
+
#
|
212
|
+
# Evaluates the value type and provides an instance accessor
|
213
|
+
# to access the value by key.
|
214
|
+
# [key:] String
|
215
|
+
# [value:] Object
|
216
|
+
def init_no_fields(key, value)
|
217
|
+
entry = nil
|
218
|
+
if value.nil?
|
219
|
+
entry = nil
|
220
|
+
elsif value.is_a? String
|
221
|
+
entry = value.gsub(/'/, ''')
|
222
|
+
elsif value.is_a? Numeric
|
223
|
+
entry = value
|
224
|
+
else
|
225
|
+
entry = "\'#{value}\'"
|
226
|
+
end
|
227
|
+
instance_variable_set "@#{key}", entry
|
228
|
+
end
|
229
|
+
private :init_no_fields
|
230
|
+
|
231
|
+
# Private instance method
|
232
|
+
#
|
233
|
+
# Transforms the key to tablename and provides an instance accessor
|
234
|
+
# and setter for the key. It is initialized with nil.
|
235
|
+
# [key:] String
|
236
|
+
def init_foreign(key)
|
237
|
+
k_table = self.class.str_to_tablename(key)
|
238
|
+
raise NameError.new("Model cannot use #{k_table} as foreign, it already exists") if k_table == "pk"
|
239
|
+
if not self.respond_to?(k_table)
|
240
|
+
instance_variable_set("@#{k_table}", nil)
|
241
|
+
self.class.send(:define_method, k_table) do
|
242
|
+
instance_variable_get "@#{k_table}"
|
243
|
+
end
|
244
|
+
self.class.send(:define_method, "#{k_table}=") do |val|
|
245
|
+
instance_variable_set "@#{k_table}", val
|
200
246
|
end
|
201
247
|
end
|
202
248
|
end
|
203
|
-
|
249
|
+
private :init_foreign
|
250
|
+
|
204
251
|
# Instance method
|
205
252
|
#
|
206
253
|
# Save the instance to the database. Set all foreign sets to
|
@@ -235,7 +282,7 @@ module Ink
|
|
235
282
|
instance_variable_set "@#{self.class.primary_key[0]}", pk.is_a?(Numeric) ? pk : "\'#{pk}\'" if pk
|
236
283
|
end
|
237
284
|
end
|
238
|
-
|
285
|
+
|
239
286
|
if self.class.respond_to? :foreign
|
240
287
|
self.class.foreign.each do |k,v|
|
241
288
|
value = instance_variable_get "@#{self.class.str_to_tablename(k)}"
|
@@ -246,9 +293,9 @@ module Ink
|
|
246
293
|
end
|
247
294
|
end
|
248
295
|
end
|
249
|
-
|
296
|
+
|
250
297
|
# Instance method
|
251
|
-
#
|
298
|
+
#
|
252
299
|
# Deletes the data from the database, essentially making the instance
|
253
300
|
# obsolete. Disregard from using the instance anymore.
|
254
301
|
# All links between models will be removed also.
|
@@ -259,11 +306,11 @@ module Ink
|
|
259
306
|
Ink::Database.database.delete_all_links self, Ink::Model.classname(k), v
|
260
307
|
end
|
261
308
|
end
|
262
|
-
|
309
|
+
|
263
310
|
pkvalue = instance_variable_get "@#{self.class.primary_key[0]}"
|
264
311
|
Ink::Database.database.remove self.class.name, "WHERE `#{self.class.primary_key[0]}`=#{(pkvalue.is_a?(Numeric)) ? pkvalue : "\'#{pkvalue}\'"}"
|
265
312
|
end
|
266
|
-
|
313
|
+
|
267
314
|
# Instance method
|
268
315
|
#
|
269
316
|
# Queries the database for foreign keys and attaches them to the
|
@@ -280,9 +327,9 @@ module Ink
|
|
280
327
|
false
|
281
328
|
end
|
282
329
|
end
|
283
|
-
|
330
|
+
|
284
331
|
# Class method
|
285
|
-
#
|
332
|
+
#
|
286
333
|
# This will create SQL statements for creating the
|
287
334
|
# database tables. 'fields' method is mandatory for
|
288
335
|
# this, and 'foreign' is optional.
|
@@ -290,7 +337,7 @@ module Ink
|
|
290
337
|
def self.create
|
291
338
|
result = Array.new
|
292
339
|
raise NotImplementedError.new("Cannot create a Database without field definitions") if not self.respond_to? :fields
|
293
|
-
|
340
|
+
|
294
341
|
string = "CREATE TABLE #{self.table_name} ("
|
295
342
|
mfk = self.foreign_key
|
296
343
|
fields = self.fields
|
@@ -300,7 +347,7 @@ module Ink
|
|
300
347
|
string += "#{Ink::Database.database.primary_key_autoincrement(k)*" "}" if k == self.primary_key[0]
|
301
348
|
string += "," if i < fields.keys.length - 1
|
302
349
|
end
|
303
|
-
|
350
|
+
|
304
351
|
if self.respond_to? :foreign
|
305
352
|
foreign = self.foreign
|
306
353
|
for i in 0...foreign.keys.length
|
@@ -308,7 +355,7 @@ module Ink
|
|
308
355
|
v = foreign[k]
|
309
356
|
fk = Ink::Model::classname(k).foreign_key
|
310
357
|
string += ",`#{fk[0]}` #{fk[1]}" if fk.length > 0 and (v == "one_many" or (v == "one_one" and (self.name <=> k) < 0))
|
311
|
-
|
358
|
+
|
312
359
|
if mfk.length > 0 and fk.length > 1 and v == "many_many" and (self.name <=> k) < 0
|
313
360
|
result.push "CREATE TABLE #{self.table_name}_#{Ink::Model::str_to_tablename(k)} (#{Ink::Database.database.primary_key_autoincrement*" "}, `#{mfk[0]}` #{mfk[1]}, `#{fk[0]}` #{fk[1]});"
|
314
361
|
end
|
@@ -318,25 +365,25 @@ module Ink
|
|
318
365
|
result.push string
|
319
366
|
result
|
320
367
|
end
|
321
|
-
|
368
|
+
|
322
369
|
# Class method
|
323
|
-
#
|
370
|
+
#
|
324
371
|
# This will retrieve a string-representation of the model name
|
325
372
|
# [returns:] valid classname
|
326
373
|
def self.class_name
|
327
374
|
self.name
|
328
375
|
end
|
329
|
-
|
376
|
+
|
330
377
|
# Class method
|
331
|
-
#
|
378
|
+
#
|
332
379
|
# This will retrieve a tablename-representation of the model name
|
333
380
|
# [returns:] valid tablename
|
334
381
|
def self.table_name
|
335
382
|
self.str_to_tablename self.name
|
336
383
|
end
|
337
|
-
|
384
|
+
|
338
385
|
# Class method
|
339
|
-
#
|
386
|
+
#
|
340
387
|
# This will check the parent module for existing classnames
|
341
388
|
# that match the input of the str parameter.
|
342
389
|
# [param str:] some string
|
@@ -348,9 +395,9 @@ module Ink
|
|
348
395
|
}
|
349
396
|
((Module.const_get res.join).is_a? Class) ? res.join : nil
|
350
397
|
end
|
351
|
-
|
398
|
+
|
352
399
|
# Class method
|
353
|
-
#
|
400
|
+
#
|
354
401
|
# This will check the parent module for existing classnames
|
355
402
|
# that match the input of the str parameter. Once found, it
|
356
403
|
# converts the string into the matching tablename.
|
@@ -363,9 +410,9 @@ module Ink
|
|
363
410
|
}
|
364
411
|
((Module.const_get str).is_a? Class) ? res.join : nil
|
365
412
|
end
|
366
|
-
|
413
|
+
|
367
414
|
# Class method
|
368
|
-
#
|
415
|
+
#
|
369
416
|
# This will check the parent module for existing classnames
|
370
417
|
# that match the input of the str parameter. Once found, it
|
371
418
|
# returns the class, not the string of the class.
|
@@ -382,36 +429,52 @@ module Ink
|
|
382
429
|
end
|
383
430
|
((Module.const_get res.join).is_a? Class) ? (Module.const_get res.join) : nil
|
384
431
|
end
|
385
|
-
|
432
|
+
|
386
433
|
# Class method
|
387
434
|
#
|
388
435
|
# This will find the primary key, as defined in the fields class
|
389
436
|
# method.
|
390
|
-
# [returns:]
|
437
|
+
# [returns:] key name or nil
|
391
438
|
def self.primary_key
|
392
439
|
if self.respond_to? :fields
|
393
|
-
|
394
|
-
|
395
|
-
self.fields.each do |k,v|
|
396
|
-
if v.is_a?(String) and v == "PRIMARY KEY"
|
397
|
-
pk = k
|
398
|
-
pktype = Ink::Database.database.primary_key_autoincrement(k)[1]
|
399
|
-
end
|
400
|
-
end
|
401
|
-
return [pk, pktype]
|
440
|
+
field = self.fields.select{|k,v| v.is_a?(String) and v == "PRIMARY KEY"}
|
441
|
+
return field.keys.first
|
402
442
|
end
|
403
|
-
|
443
|
+
nil
|
404
444
|
end
|
405
|
-
|
445
|
+
|
446
|
+
# Class method
|
447
|
+
#
|
448
|
+
# This will find the primary key type, as defined in the fields
|
449
|
+
# class method.
|
450
|
+
# [returns:] key type or nil
|
451
|
+
def self.primary_key_type
|
452
|
+
if self.respond_to? :fields
|
453
|
+
field = self.fields.select{|k,v| v.is_a?(String) and v == "PRIMARY KEY"}
|
454
|
+
return Ink::Database.database.
|
455
|
+
primary_key_autoincrement(field.keys.first)[1]
|
456
|
+
end
|
457
|
+
nil
|
458
|
+
end
|
459
|
+
|
406
460
|
# Class method
|
407
461
|
#
|
408
462
|
# This will create the foreign key from the defined primary key
|
409
|
-
# [returns:]
|
463
|
+
# [returns:] key name or nil
|
410
464
|
def self.foreign_key
|
411
465
|
pk = self.primary_key
|
412
|
-
return (pk) ?
|
466
|
+
return (pk) ? "#{self.table_name}_#{pk}" : nil
|
467
|
+
end
|
468
|
+
|
469
|
+
# Class method
|
470
|
+
#
|
471
|
+
# This will find the foreign key type, taken from the primary key
|
472
|
+
# in fields.
|
473
|
+
# [returns:] key type or nil
|
474
|
+
def self.foreign_key_type
|
475
|
+
self.primary_key_type
|
413
476
|
end
|
414
|
-
|
477
|
+
|
415
478
|
end
|
416
|
-
|
479
|
+
|
417
480
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webink
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: '2.0'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fcgi
|
@@ -52,10 +52,10 @@ extensions: []
|
|
52
52
|
extra_rdoc_files: []
|
53
53
|
files:
|
54
54
|
- lib/webink.rb
|
55
|
-
- lib/webink/controller.rb
|
56
55
|
- lib/webink/database.rb
|
57
56
|
- lib/webink/beauty.rb
|
58
57
|
- lib/webink/model.rb
|
58
|
+
- lib/webink/controller.rb
|
59
59
|
- bin/rfcgi
|
60
60
|
- bin/webink_database
|
61
61
|
homepage: https://github.com/matthias-geier/WebInk
|