webink 2.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rfcgi +11 -9
- data/bin/webink_database +4 -2
- data/lib/webink/controller.rb +66 -61
- data/lib/webink/database.rb +57 -51
- data/lib/webink/model.rb +35 -31
- metadata +2 -2
data/bin/rfcgi
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
1
3
|
require "fcgi"
|
2
4
|
require "simple_mmap"
|
3
5
|
require "webink/beauty"
|
@@ -43,7 +45,7 @@ FCGI.each_cgi do |cgi|
|
|
43
45
|
control = eval fhandle.read_window_data(0,fhandle.size), getBinding(cgi,cgi.env_table,control) if fhandle
|
44
46
|
fhandle.close
|
45
47
|
raise StandardError.new("Routes not matched.") if control.keys.length <= 1
|
46
|
-
|
48
|
+
|
47
49
|
control[:get] = pram
|
48
50
|
control[:config] = Ink::Beauty.load_config script
|
49
51
|
control[:time] = time
|
@@ -70,13 +72,13 @@ FCGI.each_cgi do |cgi|
|
|
70
72
|
else
|
71
73
|
cgi.params = pram
|
72
74
|
end
|
73
|
-
|
75
|
+
|
74
76
|
script = Ink::Beauty.load_init script
|
75
77
|
fhandle = SimpleMmap::MappedFile.new(script)
|
76
78
|
Dir.chdir( File.dirname(script) )
|
77
79
|
eval fhandle.read_window_data(0,fhandle.size), getBinding(cgi,cgi.env_table,control) if fhandle
|
78
80
|
fhandle.close
|
79
|
-
|
81
|
+
|
80
82
|
rescue LoadError => bang
|
81
83
|
if is_production
|
82
84
|
puts cgi.header({"Location" => "/status-404.html"}) if use_errors
|
@@ -85,7 +87,7 @@ FCGI.each_cgi do |cgi|
|
|
85
87
|
puts cgi.header
|
86
88
|
puts "<hr><b>LoadError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
87
89
|
end
|
88
|
-
|
90
|
+
|
89
91
|
rescue NotImplementedError => bang
|
90
92
|
if is_production
|
91
93
|
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
@@ -94,7 +96,7 @@ FCGI.each_cgi do |cgi|
|
|
94
96
|
puts cgi.header
|
95
97
|
puts "<hr><b>NotImplementedError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
96
98
|
end
|
97
|
-
|
99
|
+
|
98
100
|
rescue ArgumentError => bang
|
99
101
|
if is_production
|
100
102
|
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
@@ -103,7 +105,7 @@ FCGI.each_cgi do |cgi|
|
|
103
105
|
puts cgi.header
|
104
106
|
puts "<hr><b>ArgumentError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
105
107
|
end
|
106
|
-
|
108
|
+
|
107
109
|
rescue RuntimeError => bang
|
108
110
|
if is_production
|
109
111
|
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
@@ -112,7 +114,7 @@ FCGI.each_cgi do |cgi|
|
|
112
114
|
puts cgi.header
|
113
115
|
puts "<hr><b>RuntimeError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
114
116
|
end
|
115
|
-
|
117
|
+
|
116
118
|
rescue NameError => bang
|
117
119
|
if is_production
|
118
120
|
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
@@ -121,7 +123,7 @@ FCGI.each_cgi do |cgi|
|
|
121
123
|
puts cgi.header
|
122
124
|
puts "<hr><b>NameError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
123
125
|
end
|
124
|
-
|
126
|
+
|
125
127
|
rescue Exception, StandardError => bang
|
126
128
|
if is_production
|
127
129
|
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
@@ -131,7 +133,7 @@ FCGI.each_cgi do |cgi|
|
|
131
133
|
puts "<hr><b>Exception:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
132
134
|
end
|
133
135
|
end
|
134
|
-
|
136
|
+
|
135
137
|
script = nil
|
136
138
|
fhandle = nil
|
137
139
|
control = nil
|
data/bin/webink_database
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
1
3
|
require 'simple_mmap'
|
2
4
|
require 'webink/beauty'
|
3
5
|
|
@@ -23,7 +25,7 @@ begin
|
|
23
25
|
Ink::Database.create config
|
24
26
|
db = Ink::Database.database
|
25
27
|
db_tables = db.tables
|
26
|
-
|
28
|
+
|
27
29
|
if ARGV[0] == "drop"
|
28
30
|
puts "Dropping old tables..."
|
29
31
|
db_tables.each do |t|
|
@@ -31,7 +33,7 @@ begin
|
|
31
33
|
db.query "DROP TABLE #{t};"
|
32
34
|
end
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
puts "Creating new tables..."
|
36
38
|
model_classes.each do |m|
|
37
39
|
puts "...for class: #{m.name}:"
|
data/lib/webink/controller.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
module Ink
|
2
2
|
|
3
3
|
# = Controller class
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# == Usage
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# Controllers handle incoming requests and decide what to do
|
8
8
|
# with them. A controller has access to all incoming data, like
|
9
9
|
# POST and GET (through @params[:get] and @params[:post] as
|
10
10
|
# well as the config.
|
11
11
|
#
|
12
12
|
# class App < Ink::Controller
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# def index
|
15
15
|
# redirect_to :controller => "my_app", :module => "feed", :id => 29382374
|
16
16
|
# end
|
17
|
-
#
|
17
|
+
#
|
18
18
|
# def feed
|
19
19
|
# @arg = @params[:id]
|
20
20
|
# @users = []
|
@@ -25,14 +25,12 @@ module Ink
|
|
25
25
|
# @arg = "foo bar"
|
26
26
|
# render :partial => "part", :standalone => true
|
27
27
|
# end
|
28
|
-
#
|
28
|
+
#
|
29
29
|
# end
|
30
30
|
#
|
31
|
-
# A controller named App should have the filename app.rb
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# controller folder. It can have instance methods that are
|
35
|
-
# usually refered to as modules.
|
31
|
+
# A controller named App should have the filename app.rb and be
|
32
|
+
# placed inside the project controller folder. It can have
|
33
|
+
# instance methods that are usually refered to as modules.
|
36
34
|
# So a route should contain at least a :controller and a :module.
|
37
35
|
#
|
38
36
|
# In the sample above there are three modules, index redirects
|
@@ -51,7 +49,8 @@ module Ink
|
|
51
49
|
# == Templates
|
52
50
|
#
|
53
51
|
# All templates are to be put into the project views folder, and are
|
54
|
-
# to be named name.html.erb, while partials are to be named
|
52
|
+
# to be named name.html.erb, while partials are to be named
|
53
|
+
# _anothername.html.erb.
|
55
54
|
# It is possible to create subfolders and call the templates via
|
56
55
|
# :template => "subfolder/template.html.erb".
|
57
56
|
#
|
@@ -81,16 +80,19 @@ module Ink
|
|
81
80
|
# [ /^\/?$/, {:controller => "app", :module => "index"} ],
|
82
81
|
# ]
|
83
82
|
#
|
84
|
-
# Routes are built as a priority list, the first match will be the
|
85
|
-
# route configurations must include a variable
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
83
|
+
# Routes are built as a priority list, the first match will be the
|
84
|
+
# route taken. All route configurations must include a variable
|
85
|
+
# named root, as it will help to create dynamic links within
|
86
|
+
# websites. Root is relative to the webserver root. Assume your
|
87
|
+
# webserver points to public_html, then routes can be "" for the
|
88
|
+
# public_html folder, or "/anysubfolder" which points to anysubfolder.
|
89
|
+
# Deeper structures work too.
|
89
90
|
#
|
90
91
|
# == Linking
|
91
92
|
#
|
92
|
-
# A controller has the ability to create hyperlinks for you, that
|
93
|
-
# the project path etc. (and is also using
|
93
|
+
# A controller has the ability to create hyperlinks for you, that
|
94
|
+
# will dynamically match the project path etc. (and is also using
|
95
|
+
# the root variable from the routes.rb)
|
94
96
|
#
|
95
97
|
# link_to "name", "controller", "module", "param1", "param2", {:class => "h1", :id => "14"}
|
96
98
|
#
|
@@ -99,14 +101,15 @@ module Ink
|
|
99
101
|
# <a class="h1" id="14" href="/controller/module/param1/param2/">name</a>
|
100
102
|
#
|
101
103
|
# So the first entry of the argument array is the hyperlink name, then all
|
102
|
-
# following entries are connected as the href string, prefixed by the root
|
103
|
-
# that is set in the routes.rb. The hash includes the attributes
|
104
|
+
# following entries are connected as the href string, prefixed by the root
|
105
|
+
# variable that is set in the routes.rb. The hash includes the attributes
|
106
|
+
# for the <a>-tag.
|
104
107
|
#
|
105
108
|
# == Pathing
|
106
109
|
#
|
107
|
-
# A controller also constructs paths for you (and is also using the root
|
108
|
-
# from the routes.rb), which you can use to dynamically reroute
|
109
|
-
# mention one example.
|
110
|
+
# A controller also constructs paths for you (and is also using the root
|
111
|
+
# variable from the routes.rb), which you can use to dynamically reroute
|
112
|
+
# forms, just to mention one example.
|
110
113
|
#
|
111
114
|
# @my = "no"
|
112
115
|
# path_to "this", "is", @my, "path"
|
@@ -119,42 +122,44 @@ module Ink
|
|
119
122
|
#
|
120
123
|
# == Sessions
|
121
124
|
#
|
122
|
-
# Usually very important in the development of websites are sessions.
|
123
|
-
# basic support for it in webink, that will make certain
|
124
|
-
# have a look at the blog-demo.
|
125
|
+
# Usually very important in the development of websites are sessions.
|
126
|
+
# There is some basic support for it in webink, that will make certain
|
127
|
+
# bits easier. For more information have a look at the blog-demo.
|
128
|
+
#
|
129
|
+
# Each controller usually expects cookies to work, if you handle
|
130
|
+
# sessions via cgi. Whenever cookies do not work, or you do not
|
131
|
+
# intend to use them in the first place, path_to and link_to watch
|
132
|
+
# out for the instance variables @session_key and @session_id
|
133
|
+
# which are added via GET to the path/hyperlink, that they construct.
|
134
|
+
# Therefore the tools should not be used for external linking. The
|
135
|
+
# dispatcher automatically filters the GET session_id when using
|
136
|
+
# POST and adds it to the cgi.params, so sessions can be used confortably.
|
125
137
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# which are added via GET to the path/hyperlink, that they construct. Therefore the
|
130
|
-
# tools should not be used for external linking. The dispatcher automatically filters
|
131
|
-
# the GET session_id when using POST and adds it to the cgi.params, so sessions can
|
132
|
-
# be used confortably.
|
138
|
+
# Per default, the @session_key should be "_session_id" as specified
|
139
|
+
# in the cgi/session library from ruby core, but the controller offers
|
140
|
+
# some freedom, in case you may want a different key name for some reason.
|
133
141
|
#
|
134
|
-
# Per default, the @session_key should be "_session_id" as specified in the cgi/session
|
135
|
-
# library from ruby core, but the controller offers some freedom, in case you may want
|
136
|
-
# a different key name for some reason.
|
137
142
|
#
|
138
|
-
#
|
139
143
|
#
|
140
144
|
class Controller
|
141
|
-
|
145
|
+
|
142
146
|
# Constructor
|
143
|
-
#
|
144
|
-
# Creates a new controller of the derived class. params are the globals
|
145
|
-
# by the dispatcher, and include keys like: :get, :post and :config.
|
146
|
-
# matched routes are put there, :controller, :module and any
|
147
|
-
# :id or :page that were retrieved from the routes.
|
147
|
+
#
|
148
|
+
# Creates a new controller of the derived class. params are the globals
|
149
|
+
# set by the dispatcher, and include keys like: :get, :post and :config.
|
150
|
+
# Also the matched routes are put there, :controller, :module and any
|
151
|
+
# parameters like :id or :page that were retrieved from the routes.
|
148
152
|
# [param params:] Hash of Symbol => Objects
|
149
153
|
def initialize(params)
|
150
154
|
@params = params
|
151
155
|
end
|
152
|
-
|
156
|
+
|
153
157
|
# Instance method
|
154
|
-
#
|
155
|
-
# Render a template or a partial that is located in the ./views/ folder
|
156
|
-
# project. Subfolders are allowed to be specified. All instance
|
157
|
-
# accessible from within the template, as are any instance
|
158
|
+
#
|
159
|
+
# Render a template or a partial that is located in the ./views/ folder
|
160
|
+
# of the project. Subfolders are allowed to be specified. All instance
|
161
|
+
# variables are accessible from within the template, as are any instance
|
162
|
+
# methods.
|
158
163
|
# [param args:] Hash of arguments
|
159
164
|
# [returns:] interpreted erb instance or nil
|
160
165
|
def render(args)
|
@@ -180,9 +185,9 @@ module Ink
|
|
180
185
|
nil
|
181
186
|
end
|
182
187
|
end
|
183
|
-
|
188
|
+
|
184
189
|
# Instance method
|
185
|
-
#
|
190
|
+
#
|
186
191
|
# Redirect to a controller and module. The new controller will
|
187
192
|
# be instanciated with a copy of the current params.
|
188
193
|
# [param args:] Hash of arguments
|
@@ -202,7 +207,7 @@ module Ink
|
|
202
207
|
nil
|
203
208
|
end
|
204
209
|
end
|
205
|
-
|
210
|
+
|
206
211
|
# Instance method
|
207
212
|
#
|
208
213
|
# Creates a dynamic hyperlink
|
@@ -230,7 +235,7 @@ module Ink
|
|
230
235
|
href += "?#{@session_key}=#{@session_id}" if @session_id and @session_key
|
231
236
|
"#{a}href=\"#{href}\">#{name}</a>"
|
232
237
|
end
|
233
|
-
|
238
|
+
|
234
239
|
# Instance method
|
235
240
|
#
|
236
241
|
# Creates a dynamic path
|
@@ -241,7 +246,7 @@ module Ink
|
|
241
246
|
# [returns:] path
|
242
247
|
def path_to(*args)
|
243
248
|
href = (@params[:root].length == 0) ? "/" : "#{@params[:root]}#{(@params[:root][@params[:root].length-1].chr == "/") ? "" : "/"}"
|
244
|
-
|
249
|
+
|
245
250
|
if args.is_a? Array
|
246
251
|
for i in 0...args.length
|
247
252
|
arg = args[i]
|
@@ -253,18 +258,18 @@ module Ink
|
|
253
258
|
href += "?#{@session_key}=#{@session_id}" if @session_id and @session_key
|
254
259
|
href
|
255
260
|
end
|
256
|
-
|
261
|
+
|
257
262
|
# Instance method
|
258
|
-
#
|
263
|
+
#
|
259
264
|
# Retrieve the current binding of the instance.
|
260
265
|
# [param locals:] an Array of data for the template
|
261
266
|
# [returns:] current binding
|
262
267
|
def getBinding(locals)
|
263
268
|
binding
|
264
269
|
end
|
265
|
-
|
270
|
+
|
266
271
|
# Class method
|
267
|
-
#
|
272
|
+
#
|
268
273
|
# Retrieve the class of the name controller, that can be instanciated
|
269
274
|
# by using new. Raises a NameError.
|
270
275
|
# [param controller:] Controller name string
|
@@ -279,9 +284,9 @@ module Ink
|
|
279
284
|
end
|
280
285
|
((Module.const_get controller.capitalize).is_a? Class) ? (Module.const_get controller.capitalize) : (raise NameError.new("Controller not found."))
|
281
286
|
end
|
282
|
-
|
287
|
+
|
283
288
|
# Instance method
|
284
|
-
#
|
289
|
+
#
|
285
290
|
# Retrieve the method of name mod, that can be called by using the
|
286
291
|
# call method. Raises a NameError.
|
287
292
|
# [param mod:] Method name string
|
@@ -289,7 +294,7 @@ module Ink
|
|
289
294
|
def verify(mod)
|
290
295
|
self.method(mod)
|
291
296
|
end
|
292
|
-
|
297
|
+
|
293
298
|
end
|
294
|
-
|
299
|
+
|
295
300
|
end
|
data/lib/webink/database.rb
CHANGED
@@ -188,6 +188,8 @@ module Ink
|
|
188
188
|
v = $&.to_i
|
189
189
|
elsif v =~ /^[0-9]+\.[0-9]+$/
|
190
190
|
v = $&.to_f
|
191
|
+
elsif v =~ /^NULL$/
|
192
|
+
v = nil
|
191
193
|
end
|
192
194
|
if block_given?
|
193
195
|
yield(result[result.length-1], k, v)
|
@@ -206,6 +208,8 @@ module Ink
|
|
206
208
|
row[i] = $&.to_i
|
207
209
|
elsif row[i] =~ /^[0-9]+\.[0-9]+$/
|
208
210
|
row[i] = $&.to_f
|
211
|
+
elsif row[i] =~ /^NULL$/
|
212
|
+
row[i] = nil
|
209
213
|
end
|
210
214
|
if block_given?
|
211
215
|
yield(result[result.length-1], re.columns[i], row[i])
|
@@ -241,12 +245,12 @@ module Ink
|
|
241
245
|
# [param class_name:] Defines the __table__ name or class
|
242
246
|
# [returns:] primary key or nil
|
243
247
|
def last_inserted_pk(class_name)
|
244
|
-
|
245
|
-
table_name =
|
246
|
-
pk_name =
|
247
|
-
return if
|
248
|
+
class_name = Ink::Model.classname(class_name) unless class_name.is_a? Class
|
249
|
+
table_name = class_name.table_name
|
250
|
+
pk_name = class_name.primary_key
|
251
|
+
return if table_name.nil? or pk_name.nil?
|
248
252
|
response = self.query("SELECT MAX(#{pk_name}) as id FROM #{table_name};")
|
249
|
-
return (response.
|
253
|
+
return (response.empty?) ? nil : response.first["id"]
|
250
254
|
end
|
251
255
|
|
252
256
|
# Instance method
|
@@ -271,7 +275,7 @@ module Ink
|
|
271
275
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
272
276
|
def remove(class_name, params="")
|
273
277
|
table_name = (class_name.is_a? Class) ? class_name.table_name : Ink::Model.str_to_tablename(class_name)
|
274
|
-
return if
|
278
|
+
return if table_name.nil?
|
275
279
|
self.query("DELETE FROM #{table_name} #{params};")
|
276
280
|
end
|
277
281
|
|
@@ -282,14 +286,14 @@ module Ink
|
|
282
286
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
283
287
|
# [returns:] Array of class_name instances from the SQL result set
|
284
288
|
def find(class_name, params="")
|
285
|
-
|
289
|
+
class_name = Ink::Model.classname(class_name) unless class_name.is_a? Class
|
286
290
|
result = Array.new
|
287
|
-
table_name =
|
288
|
-
return result if
|
291
|
+
table_name = class_name.table_name
|
292
|
+
return result if table_name.nil?
|
289
293
|
|
290
294
|
re = self.query("SELECT * FROM #{table_name} #{params};")
|
291
295
|
re.each do |entry|
|
292
|
-
instance =
|
296
|
+
instance = class_name.new entry
|
293
297
|
result.push instance
|
294
298
|
end
|
295
299
|
result
|
@@ -306,23 +310,25 @@ module Ink
|
|
306
310
|
# [param params:] Additional SQL syntax like GROUP BY (optional)
|
307
311
|
# [returns:] Array of class2 instances from the SQL result set
|
308
312
|
def find_union(class1, class1_id, class2, params="")
|
309
|
-
|
310
|
-
|
313
|
+
class1 = Ink::Model.classname(class1) unless class1.is_a? Class
|
314
|
+
class2 = Ink::Model.classname(class2) unless class2.is_a? Class
|
311
315
|
result = Array.new
|
312
316
|
relationship = nil
|
313
|
-
|
314
|
-
relationship = v if k
|
317
|
+
class1.foreign.each do |k,v|
|
318
|
+
relationship = v if k == class2.class_name
|
315
319
|
end
|
316
320
|
return result if relationship != "many_many"
|
317
|
-
fk1 =
|
318
|
-
pk2 =
|
319
|
-
fk2 =
|
320
|
-
tablename1 =
|
321
|
-
tablename2 =
|
322
|
-
union_class = ((
|
321
|
+
fk1 = class1.foreign_key
|
322
|
+
pk2 = class2.primary_key
|
323
|
+
fk2 = class2.foreign_key
|
324
|
+
tablename1 = class1.table_name
|
325
|
+
tablename2 = class2.table_name
|
326
|
+
union_class = ((class1.class_name <=> class2.class_name) < 0) ?
|
327
|
+
"#{tablename1}_#{tablename2}" :
|
328
|
+
"#{tablename2}_#{tablename1}"
|
323
329
|
re = self.query("SELECT #{tablename2}.* FROM #{union_class}, #{tablename2} WHERE #{union_class}.#{fk1} = #{class1_id} AND #{union_class}.#{fk2} = #{tablename2}.#{pk2} #{params};")
|
324
330
|
re.each do |entry|
|
325
|
-
instance =
|
331
|
+
instance = class2.new entry
|
326
332
|
result.push instance
|
327
333
|
end
|
328
334
|
result
|
@@ -338,26 +344,26 @@ module Ink
|
|
338
344
|
# [param params:] Additional SQL syntax like GROUP BY (optional)
|
339
345
|
# [returns:] Array of class2 instances from the SQL result set
|
340
346
|
def find_references(class1, class1_id, class2, params="")
|
341
|
-
|
342
|
-
|
347
|
+
class1 = Ink::Model.classname(class1) unless class1.is_a? Class
|
348
|
+
class2 = Ink::Model.classname(class2) unless class2.is_a? Class
|
343
349
|
result = Array.new
|
344
350
|
relationship = nil
|
345
|
-
|
346
|
-
relationship = v if k
|
351
|
+
class1.foreign.each do |k,v|
|
352
|
+
relationship = v if k == class2.class_name
|
347
353
|
end
|
348
354
|
return result if relationship == "many_many"
|
349
355
|
re = Array.new
|
350
|
-
fk1 =
|
351
|
-
tablename1 =
|
352
|
-
tablename2 =
|
353
|
-
if ((
|
354
|
-
re = self.query "SELECT * FROM #{tablename2} WHERE #{
|
356
|
+
fk1 = class1.foreign_key
|
357
|
+
tablename1 = class1.table_name
|
358
|
+
tablename2 = class2.table_name
|
359
|
+
if ((class1.class_name <=> class2.class_name) < 0 and relationship == "one_one") or relationship == "one_many"
|
360
|
+
re = self.query "SELECT * FROM #{tablename2} WHERE #{class2.primary_key}=(SELECT #{class2.foreign_key} FROM #{tablename1} WHERE #{class1.primary_key}=#{class1_id});"
|
355
361
|
else
|
356
362
|
re = self.query "SELECT * FROM #{tablename2} WHERE #{fk1} = #{class1_id} #{params};"
|
357
363
|
end
|
358
364
|
|
359
365
|
re.each do |entry|
|
360
|
-
instance =
|
366
|
+
instance = class2.new entry
|
361
367
|
result.push instance
|
362
368
|
end
|
363
369
|
result
|
@@ -375,7 +381,7 @@ module Ink
|
|
375
381
|
def find_reference(class1, class1_id, class2, params="")
|
376
382
|
result_array = self.find_references class1, class1_id, class2, params
|
377
383
|
if result_array.length == 1
|
378
|
-
result_array
|
384
|
+
result_array.first
|
379
385
|
else
|
380
386
|
nil
|
381
387
|
end
|
@@ -394,21 +400,21 @@ module Ink
|
|
394
400
|
if type == "one_one"
|
395
401
|
firstclass = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class : link
|
396
402
|
secondclass = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? link : instance.class
|
397
|
-
key = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class.primary_key
|
398
|
-
value = instance.method(instance.class.primary_key
|
399
|
-
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key
|
403
|
+
key = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class.primary_key : instance.class.foreign_key
|
404
|
+
value = instance.method(instance.class.primary_key).call
|
405
|
+
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=NULL WHERE #{key}=#{value};"
|
400
406
|
elsif type == "one_many" or type == "many_one"
|
401
407
|
firstclass = (type == "one_many") ? instance.class : link
|
402
408
|
secondclass = (type == "one_many") ? link : instance.class
|
403
|
-
key = (type == "one_many") ? instance.class.primary_key
|
404
|
-
value = instance.method(instance.class.primary_key
|
405
|
-
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key
|
409
|
+
key = (type == "one_many") ? instance.class.primary_key : instance.class.foreign_key
|
410
|
+
value = instance.method(instance.class.primary_key).call
|
411
|
+
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=NULL WHERE #{key}=#{value};"
|
406
412
|
elsif type == "many_many"
|
407
413
|
tablename1 = instance.class.table_name
|
408
414
|
tablename2 = link.table_name
|
409
415
|
union_class = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? "#{tablename1}_#{tablename2}" : "#{tablename2}_#{tablename1}"
|
410
|
-
value = instance.method(instance.class.primary_key
|
411
|
-
@db.query "DELETE FROM #{union_class} WHERE #{instance.class.foreign_key
|
416
|
+
value = instance.method(instance.class.primary_key).call
|
417
|
+
@db.query "DELETE FROM #{union_class} WHERE #{instance.class.foreign_key}=#{value};"
|
412
418
|
end
|
413
419
|
end
|
414
420
|
|
@@ -427,13 +433,13 @@ module Ink
|
|
427
433
|
if value.is_a? Array
|
428
434
|
value.each do |v|
|
429
435
|
if v.instance_of? link
|
430
|
-
to_add.push(v.method(link.primary_key
|
436
|
+
to_add.push(v.method(link.primary_key).call)
|
431
437
|
else
|
432
438
|
to_add.push v
|
433
439
|
end
|
434
440
|
end
|
435
441
|
elsif value.instance_of? link
|
436
|
-
to_add.push(value.method(link.primary_key
|
442
|
+
to_add.push(value.method(link.primary_key).call)
|
437
443
|
else
|
438
444
|
to_add.push value
|
439
445
|
end
|
@@ -455,30 +461,30 @@ module Ink
|
|
455
461
|
def create_link(instance, link, type, fk)
|
456
462
|
if type == "one_one"
|
457
463
|
if (instance.class.name.downcase <=> link.name.downcase) < 0
|
458
|
-
re = self.find(link.name, "WHERE #{link.primary_key
|
464
|
+
re = self.find(link.name, "WHERE #{link.primary_key}=#{fk};").first
|
459
465
|
self.delete_all_links re, instance.class, type
|
460
466
|
end
|
461
467
|
firstclass = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class : link
|
462
468
|
secondclass = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? link : instance.class
|
463
|
-
key = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class.primary_key
|
464
|
-
value = instance.method(instance.class.primary_key
|
469
|
+
key = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? instance.class.primary_key : link.primary_key
|
470
|
+
value = instance.method(instance.class.primary_key).call
|
465
471
|
fk_set = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? fk : value
|
466
472
|
value_set = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? value : fk
|
467
|
-
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key
|
473
|
+
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=#{fk} WHERE #{key}=#{value};"
|
468
474
|
elsif type == "one_many" or type == "many_one"
|
469
475
|
firstclass = (type == "one_many") ? instance.class : link
|
470
476
|
secondclass = (type == "one_many") ? link : instance.class
|
471
|
-
key = (type == "one_many") ? instance.class.primary_key
|
472
|
-
value = instance.method(instance.class.primary_key
|
477
|
+
key = (type == "one_many") ? instance.class.primary_key : link.primary_key
|
478
|
+
value = instance.method(instance.class.primary_key).call
|
473
479
|
fk_set = (type == "one_many") ? fk : value
|
474
480
|
value_set = (type == "one_many") ? value : fk
|
475
|
-
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key
|
481
|
+
@db.query "UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=#{fk_set} WHERE #{key}=#{value_set};"
|
476
482
|
elsif type == "many_many"
|
477
483
|
tablename1 = instance.class.table_name
|
478
484
|
tablename2 = link.table_name
|
479
485
|
union_class = ((instance.class.name.downcase <=> link.name.downcase) < 0) ? "#{tablename1}_#{tablename2}" : "#{tablename2}_#{tablename1}"
|
480
|
-
value = instance.method(instance.class.primary_key
|
481
|
-
@db.query "INSERT INTO #{union_class} (#{instance.class.foreign_key
|
486
|
+
value = instance.method(instance.class.primary_key).call
|
487
|
+
@db.query "INSERT INTO #{union_class} (#{instance.class.foreign_key}, #{link.foreign_key}) VALUES (#{value}, #{fk});"
|
482
488
|
end
|
483
489
|
end
|
484
490
|
|
data/lib/webink/model.rb
CHANGED
@@ -140,8 +140,12 @@ module Ink
|
|
140
140
|
self.class.fields.each do |k,v|
|
141
141
|
if data.is_a? Array
|
142
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
|
-
|
144
|
-
|
143
|
+
if self.class.primary_key != k or data.length == self.class.fields.length
|
144
|
+
init_field k, data[i]
|
145
|
+
i += 1
|
146
|
+
else
|
147
|
+
init_field self.class.primary_key, nil
|
148
|
+
end
|
145
149
|
else
|
146
150
|
raise LoadError.new("Model cannot be loaded, argument missing: #{key}") if not data.key?(k.to_s) and self.class.primary_key != k
|
147
151
|
init_field k, data[k.to_s]
|
@@ -258,28 +262,26 @@ module Ink
|
|
258
262
|
string = Array.new
|
259
263
|
keystring = Array.new
|
260
264
|
valuestring = Array.new
|
261
|
-
fields = self.class.fields
|
262
265
|
pkvalue = nil
|
263
|
-
|
264
|
-
k = fields.keys[i]
|
266
|
+
self.class.fields.each do |k,v|
|
265
267
|
value = instance_variable_get "@#{k}"
|
266
|
-
value = "NULL" if
|
267
|
-
if k != self.class.primary_key
|
268
|
+
value = "NULL" if value.nil?
|
269
|
+
if k != self.class.primary_key
|
268
270
|
string.push "`#{k}`=#{(value.is_a?(Numeric)) ? value : "\'#{value}\'"}"
|
269
271
|
keystring.push "`#{k}`"
|
270
272
|
valuestring.push "#{(value.is_a?(Numeric)) ? value : "\'#{value}\'"}"
|
271
273
|
else
|
272
|
-
pkvalue = "WHERE `#{self.class.primary_key
|
274
|
+
pkvalue = "WHERE `#{self.class.primary_key}`=#{(value.is_a?(Numeric)) ? value : "\'#{value}\'"}"
|
273
275
|
end
|
274
276
|
end
|
275
277
|
if pkvalue
|
276
278
|
response = Ink::Database.database.find self.class, pkvalue
|
277
|
-
if response.
|
278
|
-
Ink::Database.database.query "UPDATE #{self.class.table_name} SET #{string * ","} #{pkvalue};"
|
279
|
-
elsif response.length == 0
|
279
|
+
if response.empty?
|
280
280
|
Ink::Database.database.query "INSERT INTO #{self.class.table_name} (#{keystring * ","}) VALUES (#{valuestring * ","});"
|
281
281
|
pk = Ink::Database.database.last_inserted_pk(self.class)
|
282
|
-
instance_variable_set "@#{self.class.primary_key
|
282
|
+
instance_variable_set "@#{self.class.primary_key}", pk.is_a?(Numeric) ? pk : "\'#{pk}\'" if pk
|
283
|
+
else
|
284
|
+
Ink::Database.database.query "UPDATE #{self.class.table_name} SET #{string * ","} #{pkvalue};"
|
283
285
|
end
|
284
286
|
end
|
285
287
|
|
@@ -321,7 +323,7 @@ module Ink
|
|
321
323
|
relationship = self.class.foreign[c.class_name]
|
322
324
|
if relationship
|
323
325
|
result_array = (relationship == "many_many") ? Ink::Database.database.find_union(self.class, self.pk, c) : Ink::Database.database.find_references(self.class, self.pk, c)
|
324
|
-
instance_variable_set("@#{c.table_name}", (relationship =~ /^one_/) ? result_array
|
326
|
+
instance_variable_set("@#{c.table_name}", (relationship =~ /^one_/) ? result_array.first : result_array)
|
325
327
|
true
|
326
328
|
else
|
327
329
|
false
|
@@ -340,26 +342,28 @@ module Ink
|
|
340
342
|
|
341
343
|
string = "CREATE TABLE #{self.table_name} ("
|
342
344
|
mfk = self.foreign_key
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
end
|
345
|
+
string += self.fields.map do |k,v|
|
346
|
+
if k != self.primary_key
|
347
|
+
"`#{k}` #{v*" "}"
|
348
|
+
else
|
349
|
+
"#{Ink::Database.database.primary_key_autoincrement(k)*" "}"
|
350
|
+
end
|
351
|
+
end.join(",")
|
350
352
|
|
351
353
|
if self.respond_to? :foreign
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
354
|
+
tmp = self.foreign.map do |k,v|
|
355
|
+
f_class = Ink::Model::classname(k)
|
356
|
+
if v == "many_many" and (self.name <=> k) < 0
|
357
|
+
result.push "CREATE TABLE #{self.table_name}_#{Ink::Model::str_to_tablename(k)} (#{Ink::Database.database.primary_key_autoincrement*" "}, `#{self.foreign_key}` #{self.foreign_key_type}, `#{f_class.foreign_key}` #{f_class.foreign_key_type});"
|
358
|
+
nil
|
359
|
+
end
|
360
|
+
if v == "one_many" or (v == "one_one" and (self.name <=> k) < 0)
|
361
|
+
"`#{f_class.foreign_key}` #{f_class.foreign_key_type}"
|
362
|
+
else
|
363
|
+
nil
|
364
|
+
end
|
365
|
+
end.compact.join(",")
|
366
|
+
string += ",#{tmp}" if not tmp.empty?
|
363
367
|
end
|
364
368
|
string += ");"
|
365
369
|
result.push string
|
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.1
|
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-03-
|
12
|
+
date: 2013-03-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fcgi
|