webink 2.1.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/webink_database +5 -7
- data/bin/webink_init +47 -0
- data/lib/webink.rb +1 -0
- data/lib/webink/beauty.rb +168 -53
- data/lib/webink/controller.rb +40 -31
- data/lib/webink/database.rb +115 -46
- data/lib/webink/model.rb +91 -26
- metadata +7 -23
- data/bin/rfcgi +0 -143
data/bin/webink_database
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'webink/beauty'
|
3
|
+
require 'webink'
|
5
4
|
|
6
5
|
config = nil
|
7
6
|
model_classes = Array.new
|
8
7
|
|
9
8
|
begin
|
10
|
-
config = Ink::Beauty.load_config
|
9
|
+
config = Ink::Beauty.new.load_config
|
11
10
|
rescue Exception => bang
|
12
11
|
puts "Error while loading config: #{bang}."
|
13
12
|
end
|
14
13
|
|
15
|
-
require "#{config[
|
16
|
-
require 'webink'
|
14
|
+
require "#{config[:db_type]}"
|
17
15
|
|
18
16
|
models = Dir.new "./models"
|
19
17
|
models.each do |model|
|
20
18
|
load "#{models.path}/#{model}" if model =~ /\.rb$/
|
21
|
-
model_classes
|
19
|
+
model_classes << Ink::Model.classname($1) if model =~ /^(.*)\.rb$/
|
22
20
|
end
|
23
21
|
|
24
22
|
begin
|
25
|
-
Ink::Database.create
|
23
|
+
Ink::Database.create(config)
|
26
24
|
db = Ink::Database.database
|
27
25
|
db_tables = db.tables
|
28
26
|
|
data/bin/webink_init
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
config_ru = <<CFG_RU
|
4
|
+
require 'erb'
|
5
|
+
require 'webink'
|
6
|
+
|
7
|
+
run Ink::Beauty.new
|
8
|
+
CFG_RU
|
9
|
+
|
10
|
+
config_rb = <<CFG_RB
|
11
|
+
Ink::Beauty.config = {
|
12
|
+
#sqlite3 config
|
13
|
+
:db_type => "sqlite3",
|
14
|
+
:db_server => "./db.sqlite",
|
15
|
+
|
16
|
+
#mysql config
|
17
|
+
#:db_type => "mysql"
|
18
|
+
#:db_user => "db_username"
|
19
|
+
#:db_pass => "db_password"
|
20
|
+
#:db_database => "db_database_name"
|
21
|
+
#:db_server => "localhost"
|
22
|
+
}
|
23
|
+
CFG_RB
|
24
|
+
|
25
|
+
routes_rb = <<RT_RB
|
26
|
+
Ink::Beauty.root = ""
|
27
|
+
|
28
|
+
Ink::Beauty.routes = [
|
29
|
+
[ /^\\/([^\\/]+)\\/([^\\/]+)\\/?$/, {:controller => "$1", :module => "$2"} ],
|
30
|
+
[ /^\\/([^\\/]+)\\/?$/, {:controller => "$1", :module => "index"} ],
|
31
|
+
[ /^\\/?$/, {:controller => "admin", :module => "index"} ],
|
32
|
+
]
|
33
|
+
RT_RB
|
34
|
+
|
35
|
+
if File.exist?("config") or File.exist?("config.rb")
|
36
|
+
puts "Directory already initialized. Exiting."
|
37
|
+
exit(0)
|
38
|
+
end
|
39
|
+
|
40
|
+
File.open("config.ru", "w"){ |f| f.puts config_ru }
|
41
|
+
File.open("config.rb", "w"){ |f| f.puts config_rb }
|
42
|
+
File.open("routes.rb", "w"){ |f| f.puts routes_rb }
|
43
|
+
Dir.mkdir("controllers", 0775)
|
44
|
+
Dir.mkdir("models", 0775)
|
45
|
+
Dir.mkdir("views", 0775)
|
46
|
+
Dir.mkdir("files", 0775)
|
47
|
+
File.chmod(0775, "config.ru", "config.rb", "routes.rb")
|
data/lib/webink.rb
CHANGED
data/lib/webink/beauty.rb
CHANGED
@@ -3,78 +3,193 @@ module Ink
|
|
3
3
|
# = Beauty class
|
4
4
|
#
|
5
5
|
# This class provides a set of tools for loading config and init scripts
|
6
|
-
# as well as the route-matching.
|
7
|
-
# beautiful, hence the name.
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# as well as the route-matching. Formerly it made the dispatcher code
|
7
|
+
# much more beautiful, hence the name.
|
8
|
+
# Since 3.0.0 it handles the dispatching for rack and serves static files
|
9
|
+
# from ./files/*
|
10
|
+
#
|
11
|
+
#
|
10
12
|
#
|
11
13
|
class Beauty
|
12
|
-
|
13
|
-
# Class
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
|
15
|
+
# Class accessor definitions
|
16
|
+
#
|
17
|
+
class << self
|
18
|
+
attr_accessor :routes, :config, :root
|
19
|
+
end
|
20
|
+
|
21
|
+
# Constructor
|
22
|
+
#
|
23
|
+
def initialize
|
24
|
+
@params = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Instance method
|
28
|
+
#
|
29
|
+
# Rackup call
|
30
|
+
# Initializes the webink environment
|
31
|
+
# Rescues all kinds of errors and responds with error codes
|
32
|
+
# [param env:] rack environment
|
33
|
+
# [returns:] Rack-compatible array
|
34
|
+
def call(env)
|
35
|
+
@params = {} #reset
|
36
|
+
@env = env
|
37
|
+
controller = self.init
|
38
|
+
if controller and not @params[:file]
|
39
|
+
Ink::Database.create(@params[:config])
|
40
|
+
response = controller.verify(@params[:module]).call
|
41
|
+
Ink::Database.database.close
|
42
|
+
response || [404, {}, self.error_mapping(404)]
|
43
|
+
elsif File.exist?("."+@params[:file])
|
44
|
+
[ 200, {}, File.open("."+@params[:file], File::RDONLY) ]
|
45
|
+
else
|
46
|
+
[ 404, {}, self.error_mapping(404) ]
|
47
|
+
end
|
48
|
+
rescue LoadError => bang
|
49
|
+
render_error(404, "LoadError", bang)
|
50
|
+
rescue NotImplementedError => bang
|
51
|
+
render_error(500, "NotImplementedError", bang)
|
52
|
+
rescue ArgumentError => bang
|
53
|
+
render_error(500, "ArgumentError", bang)
|
54
|
+
rescue RuntimeError => bang
|
55
|
+
render_error(500, "RuntimeError", bang)
|
56
|
+
rescue NameError => bang
|
57
|
+
render_error(500, "NameError", bang)
|
58
|
+
rescue Exception, Error => bang
|
59
|
+
render_error(500, "Exception", bang)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Instance method
|
63
|
+
#
|
64
|
+
# Loads models and the controller. Requires the database type.
|
65
|
+
# [returns:] Controller class
|
66
|
+
def load_env
|
67
|
+
require "#{@params[:config][:db_type]}"
|
68
|
+
Dir.new("./models").each{ |m| load "./models/#{m}" if m =~ /\.rb$/ }
|
69
|
+
load "./controllers/#{@params[:controller]}.rb"
|
70
|
+
Ink::Controller.verify(@params[:controller]).new(@params)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Instance method
|
74
|
+
#
|
75
|
+
# Generates a param hash including the config, route and get/post
|
76
|
+
# parameters.
|
77
|
+
# [returns:] Controller class
|
78
|
+
def init
|
79
|
+
req = Rack::Request.new(@env)
|
80
|
+
@params.merge!({:header => {}, :cookie => req.cookies})
|
81
|
+
@params[:get] = Rack::Utils.parse_query(@env["QUERY_STRING"], '&;') || {}
|
82
|
+
@params[:post] = {}
|
83
|
+
if @env['rack.input'].is_a?(StringIO)
|
84
|
+
@params[:post] =
|
85
|
+
Rack::Utils.parse_query(@env['rack.input'].read, "&;\n")
|
86
|
+
end
|
87
|
+
self.load_config
|
88
|
+
self.load_routes
|
89
|
+
@params[:file] ? nil : self.load_env #static file requests are nil
|
23
90
|
end
|
24
|
-
|
25
|
-
#
|
26
|
-
#
|
91
|
+
|
92
|
+
# Instance method
|
93
|
+
#
|
27
94
|
# Attempts to load the config file of the project or raises a LoadError.
|
28
|
-
# Once loaded, the config is
|
29
|
-
# it is returned
|
30
|
-
# [param script:] Project folder path
|
95
|
+
# Once loaded, the config is returned
|
31
96
|
# [returns:] a valid config
|
32
|
-
def
|
33
|
-
config = "
|
34
|
-
config = "#{config}.rb"
|
35
|
-
raise LoadError.new("Config not found.")
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
config
|
97
|
+
def load_config
|
98
|
+
config = "./config"
|
99
|
+
config = "#{config}.rb" unless File.exist?(config)
|
100
|
+
raise LoadError.new("Config not found.") unless File.exist?(config)
|
101
|
+
load config
|
102
|
+
if Beauty.config.nil?
|
103
|
+
raise LoadError.new("Config extension error on Beauty")
|
104
|
+
end
|
105
|
+
@params[:config] = Beauty.config
|
106
|
+
Beauty.config
|
41
107
|
end
|
42
|
-
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# Attempts to load the routes file of the project or raises a LoadError
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
routes = "#{File.
|
50
|
-
|
51
|
-
|
52
|
-
routes
|
108
|
+
|
109
|
+
# Instance method
|
110
|
+
#
|
111
|
+
# Attempts to load the routes file of the project or raises a LoadError.
|
112
|
+
# Determines and stores the current route in the @params
|
113
|
+
def load_routes
|
114
|
+
routes = "./routes"
|
115
|
+
routes = "#{routes}.rb" unless File.exist?(routes)
|
116
|
+
raise LoadError.new("Routes not found.") unless File.exist?(routes)
|
117
|
+
load routes
|
118
|
+
if Beauty.routes.nil?
|
119
|
+
raise LoadError.new("Route extension error on Beauty")
|
120
|
+
elsif Beauty.root.nil?
|
121
|
+
raise LoadError.new("Root extension error on Beuaty")
|
122
|
+
end
|
123
|
+
@params.merge!(self.routing(@env["REQUEST_PATH"])) if @env["REQUEST_PATH"]
|
53
124
|
end
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
125
|
+
|
126
|
+
# Instance method
|
127
|
+
#
|
57
128
|
# Attempts to match the params onto the routes and return the results in
|
58
129
|
# form of a Hash.
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# [param
|
130
|
+
# Possible root route is extracted and routes matching to /files/* will
|
131
|
+
# be stored in the match.
|
132
|
+
# [param str:] Requested string
|
62
133
|
# [returns:] Hash of Symbol => String
|
63
|
-
def
|
134
|
+
def routing(str)
|
135
|
+
root = Beauty.root
|
136
|
+
root = $1 if root =~ /(.*)\/$/
|
64
137
|
match = { :root => root }
|
65
|
-
|
138
|
+
if str =~ /^#{root}(.*)\/?$/
|
139
|
+
str = $1
|
140
|
+
else
|
141
|
+
raise LoadError.new("No matching route found")
|
142
|
+
end
|
143
|
+
# match file route:
|
144
|
+
if str =~ /^(\/files\/.+)$/
|
145
|
+
return match.merge({ :file => $1 })
|
146
|
+
end
|
147
|
+
Beauty.routes.each do |entry|
|
66
148
|
k = entry[0]
|
67
149
|
v = entry[1]
|
68
|
-
if
|
150
|
+
if str =~ k
|
69
151
|
v.each do |sys,e|
|
70
|
-
match[sys] =
|
152
|
+
match[sys] =
|
153
|
+
(e =~ /^\$\d+$/ and str =~ k and eval e) ? (eval e) : e
|
71
154
|
end
|
72
155
|
break
|
73
156
|
end
|
74
157
|
end
|
158
|
+
raise LoadError.new("No matching route found") if match.keys.length <= 1
|
75
159
|
match
|
76
160
|
end
|
77
|
-
|
161
|
+
|
162
|
+
# Instance method
|
163
|
+
#
|
164
|
+
# Renders error stacktraces or errors back to the
|
165
|
+
# user
|
166
|
+
# [param code:] Error code integer
|
167
|
+
# [param type:] Exception type string
|
168
|
+
# [param bang:] Exception instance
|
169
|
+
# [returns:] Rack-compatible array
|
170
|
+
def render_error(code, type, bang)
|
171
|
+
if Beauty.config and Beauty.config[:production]
|
172
|
+
[code, {}, self.error_mapping(code)]
|
173
|
+
else
|
174
|
+
[200, {}, [
|
175
|
+
"<b>#{type}</b>",
|
176
|
+
"<em><pre>#{bang}</pre></em>",
|
177
|
+
"<pre>#{bang.backtrace.join("\n")}</pre>"
|
178
|
+
]]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Instance method
|
183
|
+
#
|
184
|
+
# Maps error code integers to error strings
|
185
|
+
# [param code:] Error code integer
|
186
|
+
# [returns:] Error string
|
187
|
+
def error_mapping(code)
|
188
|
+
{
|
189
|
+
404 => "404 Page not found",
|
190
|
+
500 => "500 Internal error",
|
191
|
+
}[code]
|
192
|
+
end
|
193
|
+
|
78
194
|
end
|
79
|
-
|
80
195
|
end
|
data/lib/webink/controller.rb
CHANGED
@@ -12,7 +12,8 @@ module Ink
|
|
12
12
|
# class App < Ink::Controller
|
13
13
|
#
|
14
14
|
# def index
|
15
|
-
# redirect_to :controller => "my_app", :module => "feed",
|
15
|
+
# redirect_to :controller => "my_app", :module => "feed",
|
16
|
+
# :id => 29382374
|
16
17
|
# end
|
17
18
|
#
|
18
19
|
# def feed
|
@@ -29,9 +30,11 @@ module Ink
|
|
29
30
|
# end
|
30
31
|
#
|
31
32
|
# A controller named App should have the filename app.rb and be
|
32
|
-
# placed inside the project
|
33
|
+
# placed inside the project controllers folder. It can have
|
33
34
|
# instance methods that are usually refered to as modules.
|
34
35
|
# So a route should contain at least a :controller and a :module.
|
36
|
+
# Note that controller filenames are not camelized when they are
|
37
|
+
# being searched for by the dispatcher.
|
35
38
|
#
|
36
39
|
# In the sample above there are three modules, index redirects
|
37
40
|
# to feed, feed renders a template and partial renders a partial.
|
@@ -72,10 +75,11 @@ module Ink
|
|
72
75
|
# The routes being evaluated by the dispatcher are simple regular expressions.
|
73
76
|
# This example fits the controller from earlier.
|
74
77
|
#
|
75
|
-
# root = "/folder"
|
78
|
+
# Beauty.root = "/folder"
|
76
79
|
#
|
77
|
-
# routes = [
|
78
|
-
# [ /^\/([^\/]+)\/([^\/]+)(\/([0-9]+))?$/,
|
80
|
+
# Beauty.routes = [
|
81
|
+
# [ /^\/([^\/]+)\/([^\/]+)(\/([0-9]+))?$/,
|
82
|
+
# {:controller => "$1", :module => "$2", :id => "$4"} ],
|
79
83
|
# [ /^\/([^\/]+)\/?$/, {:controller => "$1", :module => "index"} ],
|
80
84
|
# [ /^\/?$/, {:controller => "app", :module => "index"} ],
|
81
85
|
# ]
|
@@ -94,7 +98,8 @@ module Ink
|
|
94
98
|
# will dynamically match the project path etc. (and is also using
|
95
99
|
# the root variable from the routes.rb)
|
96
100
|
#
|
97
|
-
# link_to "name", "controller", "module", "param1", "param2",
|
101
|
+
# link_to "name", "controller", "module", "param1", "param2",
|
102
|
+
# {:class => "h1", :id => "14"}
|
98
103
|
#
|
99
104
|
# The link above will produce this:
|
100
105
|
#
|
@@ -126,18 +131,18 @@ module Ink
|
|
126
131
|
# There is some basic support for it in webink, that will make certain
|
127
132
|
# bits easier. For more information have a look at the blog-demo.
|
128
133
|
#
|
129
|
-
# Each controller usually expects cookies to work
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
134
|
+
# Each controller usually expects cookies to work. Whenever cookies
|
135
|
+
# do not work, or you do not intend to use them in the first place,
|
136
|
+
# path_to and link_to watch out for the instance variables @session_key
|
137
|
+
# and @session_id which are added via GET to the path/hyperlink, that
|
138
|
+
# they construct. Therefore the tools should not be used for external
|
139
|
+
# linking. The dispatcher automatically filters the GET session_id when
|
140
|
+
# using POST and adds it to the cgi.params, so sessions can be used
|
141
|
+
# confortably.
|
137
142
|
#
|
138
|
-
# Per default, the @session_key should be "_session_id"
|
139
|
-
#
|
140
|
-
#
|
143
|
+
# Per default, the @session_key should be "_session_id", but the
|
144
|
+
# controller offers some freedom, in case you may want a different
|
145
|
+
# key name for some reason.
|
141
146
|
#
|
142
147
|
#
|
143
148
|
#
|
@@ -169,17 +174,18 @@ module Ink
|
|
169
174
|
template = File.open "./views/#{args[:template]}.html.erb", "r"
|
170
175
|
erb = ERB.new template.readlines * "\n"
|
171
176
|
template.close
|
172
|
-
|
173
|
-
erb.run self.getBinding(args[:locals])
|
177
|
+
[200, @params[:header], erb.result(self.getBinding(args[:locals]))]
|
174
178
|
elsif args[:partial]
|
175
|
-
template = File.open "./views/#{
|
179
|
+
template = File.open "./views/#{
|
180
|
+
(File.dirname(args[:partial]) != ".") ?
|
181
|
+
"#{File.dirname(args[:partial])}/" : ""
|
182
|
+
}_#{File.basename(args[:partial])}.html.erb", "r"
|
176
183
|
erb = ERB.new template.readlines * "\n"
|
177
184
|
template.close
|
178
185
|
if not args[:standalone]
|
179
|
-
erb.result
|
186
|
+
erb.result(self.getBinding(args[:locals]))
|
180
187
|
else
|
181
|
-
|
182
|
-
erb.run self.getBinding(args[:locals])
|
188
|
+
[200, @params[:header], erb.result(self.getBinding(args[:locals]))]
|
183
189
|
end
|
184
190
|
else
|
185
191
|
nil
|
@@ -201,8 +207,8 @@ module Ink
|
|
201
207
|
p[k] = v
|
202
208
|
end
|
203
209
|
if p[:controller] and p[:module]
|
204
|
-
controller =
|
205
|
-
|
210
|
+
controller = Ink::Controller.verify(p[:controller]).new(p)
|
211
|
+
controller.verify(p[:module]).call
|
206
212
|
else
|
207
213
|
nil
|
208
214
|
end
|
@@ -218,8 +224,10 @@ module Ink
|
|
218
224
|
# [param args:] Array of Strings and Hashes
|
219
225
|
# [returns:] Hyperlink
|
220
226
|
def link_to(*args)
|
221
|
-
|
222
|
-
|
227
|
+
if not args.instance_of? Array and args.length < 2
|
228
|
+
raise ArgumentError.new("Expects an array.")
|
229
|
+
end
|
230
|
+
href = "#{@params[:root]}/"
|
223
231
|
a = "<a "
|
224
232
|
name = args[0]
|
225
233
|
for i in 1...args.length
|
@@ -245,7 +253,7 @@ module Ink
|
|
245
253
|
# [param args:] Array of Strings or String
|
246
254
|
# [returns:] path
|
247
255
|
def path_to(*args)
|
248
|
-
href =
|
256
|
+
href = "#{@params[:root]}/"
|
249
257
|
|
250
258
|
if args.is_a? Array
|
251
259
|
for i in 0...args.length
|
@@ -275,14 +283,15 @@ module Ink
|
|
275
283
|
# [param controller:] Controller name string
|
276
284
|
# [returns:] class or nil
|
277
285
|
def self.verify(controller)
|
278
|
-
if not Module.const_defined?
|
279
|
-
if File.exists? "./controllers/#{controller}.rb"
|
286
|
+
if not Module.const_defined?(controller.capitalize)
|
287
|
+
if File.exists? "./controllers/#{controller}.rb" and
|
288
|
+
Module.const_get(controller.capitalize).is_a?(Class)
|
280
289
|
load "./controllers/#{controller}.rb"
|
281
290
|
else
|
282
291
|
raise NameError.new("Controller not found.")
|
283
292
|
end
|
284
293
|
end
|
285
|
-
|
294
|
+
Module.const_get(controller.capitalize)
|
286
295
|
end
|
287
296
|
|
288
297
|
# Instance method
|
data/lib/webink/database.rb
CHANGED
@@ -10,21 +10,19 @@ module Ink
|
|
10
10
|
#
|
11
11
|
# Sample config for MySQL:
|
12
12
|
# config = {
|
13
|
-
#
|
14
|
-
# "
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# "db_server" => "localhost",
|
13
|
+
# :production => true,
|
14
|
+
# :db_type => "mysql",
|
15
|
+
# :db_user => "yourusername",
|
16
|
+
# :db_pass => "yourpassword",
|
17
|
+
# :db_database => "yourdatabase",
|
18
|
+
# :db_server => "localhost",
|
20
19
|
# }
|
21
20
|
#
|
22
21
|
# Sample config for SQLite3:
|
23
22
|
# config = {
|
24
|
-
#
|
25
|
-
# "
|
26
|
-
#
|
27
|
-
# "db_server" => "/full/path/to/database.sqlite",
|
23
|
+
# :production => true,
|
24
|
+
# :db_type => "sqlite3",
|
25
|
+
# :db_server => "/full/path/to/database.sqlite",
|
28
26
|
# }
|
29
27
|
#
|
30
28
|
# == Usage
|
@@ -109,12 +107,13 @@ module Ink
|
|
109
107
|
# possible.
|
110
108
|
# [param config:] Hash of config parameters
|
111
109
|
def initialize(config)
|
112
|
-
@type = config[
|
110
|
+
@type = config[:db_type]
|
113
111
|
if @type == "mysql"
|
114
|
-
@db = Mysql.real_connect(config[
|
112
|
+
@db = Mysql.real_connect(config[:db_server],config[:db_user],
|
113
|
+
config[:db_pass],config[:db_database])
|
115
114
|
@db.reconnect = true
|
116
115
|
elsif @type == "sqlite3"
|
117
|
-
@db = SQLite3::Database.new(config[
|
116
|
+
@db = SQLite3::Database.new(config[:db_server])
|
118
117
|
else
|
119
118
|
raise ArgumentError.new("Database undefined.")
|
120
119
|
end
|
@@ -140,7 +139,11 @@ module Ink
|
|
140
139
|
# Returns the Database instance or raises a Runtime Error
|
141
140
|
# [returns:] Database instance
|
142
141
|
def self.database
|
143
|
-
|
142
|
+
if @@database
|
143
|
+
@@database
|
144
|
+
else
|
145
|
+
raise RuntimeError.new("No Database found. Create one first")
|
146
|
+
end
|
144
147
|
end
|
145
148
|
|
146
149
|
# Instance method
|
@@ -158,7 +161,9 @@ module Ink
|
|
158
161
|
end
|
159
162
|
end
|
160
163
|
elsif @type == "sqlite3"
|
161
|
-
re = @db.query
|
164
|
+
re = @db.query <<QUERY
|
165
|
+
SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;
|
166
|
+
QUERY
|
162
167
|
re.each do |row|
|
163
168
|
row.each do |t|
|
164
169
|
result.push t
|
@@ -273,7 +278,9 @@ module Ink
|
|
273
278
|
# [param class_name:] Defines the __table__ name or class
|
274
279
|
# [returns:] primary key or nil
|
275
280
|
def last_inserted_pk(class_name)
|
276
|
-
|
281
|
+
unless class_name.is_a?(Class)
|
282
|
+
class_name = Ink::Model.classname(class_name)
|
283
|
+
end
|
277
284
|
table_name = class_name.table_name
|
278
285
|
pk_name = class_name.primary_key
|
279
286
|
return if table_name.nil? or pk_name.nil?
|
@@ -302,7 +309,8 @@ module Ink
|
|
302
309
|
# [param class_name:] Defines the class name or class
|
303
310
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
304
311
|
def remove(class_name, params="")
|
305
|
-
table_name = (class_name.is_a? Class) ? class_name.table_name :
|
312
|
+
table_name = (class_name.is_a? Class) ? class_name.table_name :
|
313
|
+
Ink::Model.str_to_tablename(class_name)
|
306
314
|
return if table_name.nil?
|
307
315
|
self.query("DELETE FROM #{table_name} #{params};")
|
308
316
|
end
|
@@ -310,11 +318,14 @@ module Ink
|
|
310
318
|
# Instance method
|
311
319
|
#
|
312
320
|
# Retrieve class instances, that are loaded with the database result set.
|
313
|
-
# [param class_name:] Defines the class name or class which should be
|
321
|
+
# [param class_name:] Defines the class name or class which should be
|
322
|
+
# queried
|
314
323
|
# [param params:] Additional SQL syntax like WHERE conditions (optional)
|
315
324
|
# [returns:] Array of class_name instances from the SQL result set
|
316
325
|
def find(class_name, params="")
|
317
|
-
|
326
|
+
unless class_name.is_a?(Class)
|
327
|
+
class_name = Ink::Model.classname(class_name)
|
328
|
+
end
|
318
329
|
result = Array.new
|
319
330
|
table_name = class_name.table_name
|
320
331
|
return result if table_name.nil?
|
@@ -354,7 +365,11 @@ module Ink
|
|
354
365
|
union_class = ((class1.class_name <=> class2.class_name) < 0) ?
|
355
366
|
"#{tablename1}_#{tablename2}" :
|
356
367
|
"#{tablename2}_#{tablename1}"
|
357
|
-
re = self.query
|
368
|
+
re = self.query <<QUERY
|
369
|
+
SELECT #{tablename2}.* FROM #{union_class}, #{tablename2}
|
370
|
+
WHERE #{union_class}.#{fk1} = #{class1_id}
|
371
|
+
AND #{union_class}.#{fk2} = #{tablename2}.#{pk2} #{params};
|
372
|
+
QUERY
|
358
373
|
re.each do |entry|
|
359
374
|
instance = class2.new entry
|
360
375
|
result.push instance
|
@@ -384,10 +399,19 @@ module Ink
|
|
384
399
|
fk1 = class1.foreign_key
|
385
400
|
tablename1 = class1.table_name
|
386
401
|
tablename2 = class2.table_name
|
387
|
-
if ((class1.class_name <=> class2.class_name) < 0 and
|
388
|
-
|
402
|
+
if ((class1.class_name <=> class2.class_name) < 0 and
|
403
|
+
relationship == "one_one") or relationship == "one_many"
|
404
|
+
re = self.query <<QUERY
|
405
|
+
SELECT * FROM #{tablename2}
|
406
|
+
WHERE #{class2.primary_key}=(
|
407
|
+
SELECT #{class2.foreign_key} FROM #{tablename1}
|
408
|
+
WHERE #{class1.primary_key}=#{class1_id}
|
409
|
+
);
|
410
|
+
QUERY
|
389
411
|
else
|
390
|
-
re = self.query
|
412
|
+
re = self.query <<QUERY
|
413
|
+
SELECT * FROM #{tablename2} WHERE #{fk1} = #{class1_id} #{params};
|
414
|
+
QUERY
|
391
415
|
end
|
392
416
|
|
393
417
|
re.each do |entry|
|
@@ -400,7 +424,8 @@ module Ink
|
|
400
424
|
# Instance method
|
401
425
|
#
|
402
426
|
# Retrieve one class2 instance, that is related to the class1 instance with
|
403
|
-
# primary key class1_id. Only relevant for one_one and one_many
|
427
|
+
# primary key class1_id. Only relevant for one_one and one_many
|
428
|
+
# relationships
|
404
429
|
# [param class1:] Reference classname or class
|
405
430
|
# [param class1_id:] Primary key value of the reference classname
|
406
431
|
# [param class2:] Match classname or class
|
@@ -426,23 +451,42 @@ module Ink
|
|
426
451
|
# [param type:] relationship type
|
427
452
|
def delete_all_links(instance, link, type)
|
428
453
|
if type == "one_one"
|
429
|
-
firstclass =
|
430
|
-
|
431
|
-
|
454
|
+
firstclass =
|
455
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
456
|
+
instance.class : link
|
457
|
+
secondclass =
|
458
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
459
|
+
link : instance.class
|
460
|
+
key =
|
461
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
462
|
+
instance.class.primary_key : instance.class.foreign_key
|
432
463
|
value = instance.method(instance.class.primary_key).call
|
433
|
-
@db.query
|
464
|
+
@db.query <<QUERY
|
465
|
+
UPDATE #{firstclass.table_name}
|
466
|
+
SET #{secondclass.foreign_key}=NULL
|
467
|
+
WHERE #{key}=#{value};
|
468
|
+
QUERY
|
434
469
|
elsif type == "one_many" or type == "many_one"
|
435
470
|
firstclass = (type == "one_many") ? instance.class : link
|
436
471
|
secondclass = (type == "one_many") ? link : instance.class
|
437
|
-
key = (type == "one_many") ? instance.class.primary_key :
|
472
|
+
key = (type == "one_many") ? instance.class.primary_key :
|
473
|
+
instance.class.foreign_key
|
438
474
|
value = instance.method(instance.class.primary_key).call
|
439
|
-
@db.query
|
475
|
+
@db.query <<QUERY
|
476
|
+
UPDATE #{firstclass.table_name}
|
477
|
+
SET #{secondclass.foreign_key}=NULL
|
478
|
+
WHERE #{key}=#{value};
|
479
|
+
QUERY
|
440
480
|
elsif type == "many_many"
|
441
481
|
tablename1 = instance.class.table_name
|
442
482
|
tablename2 = link.table_name
|
443
|
-
union_class =
|
483
|
+
union_class =
|
484
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
485
|
+
"#{tablename1}_#{tablename2}" : "#{tablename2}_#{tablename1}"
|
444
486
|
value = instance.method(instance.class.primary_key).call
|
445
|
-
@db.query
|
487
|
+
@db.query <<QUERY
|
488
|
+
DELETE FROM #{union_class} WHERE #{instance.class.foreign_key}=#{value};
|
489
|
+
QUERY
|
446
490
|
end
|
447
491
|
end
|
448
492
|
|
@@ -452,10 +496,12 @@ module Ink
|
|
452
496
|
# link is the class of the related data, and type refers to the
|
453
497
|
# relationship type of the two. When one tries to insert an array
|
454
498
|
# for a x_one relationship, the last entry will be set.
|
455
|
-
# [param instance:] Instance of a class that refers to an existing
|
499
|
+
# [param instance:] Instance of a class that refers to an existing
|
500
|
+
# database entry
|
456
501
|
# [param link:] the related class (not a String, but class reference)
|
457
502
|
# [param type:] relationship type
|
458
|
-
# [param value:] relationship data that was set, either a primary key value,
|
503
|
+
# [param value:] relationship data that was set, either a primary key value,
|
504
|
+
# or an instance, or an array of both
|
459
505
|
def create_all_links(instance, link, type, value)
|
460
506
|
to_add = Array.new
|
461
507
|
if value.is_a? Array
|
@@ -482,7 +528,8 @@ module Ink
|
|
482
528
|
# The relationship between the two is defined by type. one_one
|
483
529
|
# relationships are placing an additional call to delete_all_links
|
484
530
|
# that will remove conflicts.
|
485
|
-
# [param instance:] Instance of a class that refers to an existing database
|
531
|
+
# [param instance:] Instance of a class that refers to an existing database
|
532
|
+
# entry
|
486
533
|
# [param link:] the related class (not a String, but class reference)
|
487
534
|
# [param type:] relationship type
|
488
535
|
# [param value:] primary key of the relationship, that is to be created
|
@@ -492,27 +539,49 @@ module Ink
|
|
492
539
|
re = self.find(link.name, "WHERE #{link.primary_key}=#{fk};").first
|
493
540
|
self.delete_all_links re, instance.class, type
|
494
541
|
end
|
495
|
-
firstclass =
|
496
|
-
|
497
|
-
|
542
|
+
firstclass =
|
543
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
544
|
+
instance.class : link
|
545
|
+
secondclass =
|
546
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
547
|
+
link : instance.class
|
548
|
+
key =
|
549
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
550
|
+
instance.class.primary_key : link.primary_key
|
498
551
|
value = instance.method(instance.class.primary_key).call
|
499
|
-
fk_set =
|
500
|
-
|
501
|
-
|
552
|
+
fk_set =
|
553
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
554
|
+
fk : value
|
555
|
+
value_set =
|
556
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
557
|
+
value : fk
|
558
|
+
@db.query <<QUERY
|
559
|
+
UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=#{fk}
|
560
|
+
WHERE #{key}=#{value};
|
561
|
+
QUERY
|
502
562
|
elsif type == "one_many" or type == "many_one"
|
503
563
|
firstclass = (type == "one_many") ? instance.class : link
|
504
564
|
secondclass = (type == "one_many") ? link : instance.class
|
505
|
-
key = (type == "one_many") ? instance.class.primary_key :
|
565
|
+
key = (type == "one_many") ? instance.class.primary_key :
|
566
|
+
link.primary_key
|
506
567
|
value = instance.method(instance.class.primary_key).call
|
507
568
|
fk_set = (type == "one_many") ? fk : value
|
508
569
|
value_set = (type == "one_many") ? value : fk
|
509
|
-
@db.query
|
570
|
+
@db.query <<QUERY
|
571
|
+
UPDATE #{firstclass.table_name} SET #{secondclass.foreign_key}=#{fk_set}
|
572
|
+
WHERE #{key}=#{value_set};
|
573
|
+
QUERY
|
510
574
|
elsif type == "many_many"
|
511
575
|
tablename1 = instance.class.table_name
|
512
576
|
tablename2 = link.table_name
|
513
|
-
union_class =
|
577
|
+
union_class =
|
578
|
+
((instance.class.name.downcase <=> link.name.downcase) < 0) ?
|
579
|
+
"#{tablename1}_#{tablename2}" : "#{tablename2}_#{tablename1}"
|
514
580
|
value = instance.method(instance.class.primary_key).call
|
515
|
-
@db.query
|
581
|
+
@db.query <<QUERY
|
582
|
+
INSERT INTO #{union_class}
|
583
|
+
(#{instance.class.foreign_key}, #{link.foreign_key}) VALUES (#{value}, #{fk});
|
584
|
+
QUERY
|
516
585
|
end
|
517
586
|
end
|
518
587
|
|
data/lib/webink/model.rb
CHANGED
@@ -139,15 +139,26 @@ module Ink
|
|
139
139
|
i = 0
|
140
140
|
self.class.fields.each do |k,v|
|
141
141
|
if data.is_a? Array
|
142
|
-
|
143
|
-
|
142
|
+
if data.length < self.class.fields.length - 1 or
|
143
|
+
data.length > self.class.fields.length
|
144
|
+
raise LoadError.new(<<ERR)
|
145
|
+
Model cannot be loaded, wrong number or arguments #{data.length} expected
|
146
|
+
#{self.class.fields.length} or #{self.class.fields.length - 1}
|
147
|
+
ERR
|
148
|
+
end
|
149
|
+
if self.class.primary_key != k or
|
150
|
+
data.length == self.class.fields.length
|
144
151
|
init_field k, data[i]
|
145
152
|
i += 1
|
146
153
|
else
|
147
154
|
init_field self.class.primary_key, nil
|
148
155
|
end
|
149
156
|
else
|
150
|
-
|
157
|
+
if not data.key?(k.to_s) and self.class.primary_key != k
|
158
|
+
raise LoadError.new(<<ERR)
|
159
|
+
Model cannot be loaded, argument missing: #{key}
|
160
|
+
ERR
|
161
|
+
end
|
151
162
|
init_field k, data[k.to_s]
|
152
163
|
end
|
153
164
|
end
|
@@ -188,7 +199,11 @@ module Ink
|
|
188
199
|
# [key:] String
|
189
200
|
# [value:] Object
|
190
201
|
def init_field(key, value)
|
191
|
-
|
202
|
+
if key.to_s.downcase == "pk"
|
203
|
+
raise NameError.new(<<ERR)
|
204
|
+
Model cannot use #{key} as field, it is blocked by primary key
|
205
|
+
ERR
|
206
|
+
end
|
192
207
|
entry = self.class.make_safe(value)
|
193
208
|
instance_variable_set("@#{key}", entry)
|
194
209
|
|
@@ -231,7 +246,11 @@ module Ink
|
|
231
246
|
# [key:] String
|
232
247
|
def init_foreign(key)
|
233
248
|
k_table = self.class.str_to_tablename(key)
|
234
|
-
|
249
|
+
if k_table == "pk"
|
250
|
+
raise NameError.new(<<ERR)
|
251
|
+
Model cannot use #{k_table} as foreign, it already exists
|
252
|
+
ERR
|
253
|
+
end
|
235
254
|
if not self.respond_to?(k_table)
|
236
255
|
instance_variable_set("@#{k_table}", nil)
|
237
256
|
self.class.send(:define_method, k_table) do
|
@@ -250,7 +269,11 @@ module Ink
|
|
250
269
|
# nil if you do not want to change them. Old references are
|
251
270
|
# automatically removed.
|
252
271
|
def save
|
253
|
-
|
272
|
+
if not self.class.respond_to?(:fields)
|
273
|
+
raise NotImplementedError.new(<<ERR)
|
274
|
+
Cannot save to Database without field definitions
|
275
|
+
ERR
|
276
|
+
end
|
254
277
|
string = Array.new
|
255
278
|
keystring = Array.new
|
256
279
|
valuestring = Array.new
|
@@ -259,21 +282,33 @@ module Ink
|
|
259
282
|
value = instance_variable_get "@#{k}"
|
260
283
|
value = "NULL" if value.nil?
|
261
284
|
if k != self.class.primary_key
|
262
|
-
string.push "`#{k}`=#{(value.is_a?(Numeric)) ? value :
|
285
|
+
string.push "`#{k}`=#{(value.is_a?(Numeric)) ? value :
|
286
|
+
"\'#{value}\'"}"
|
263
287
|
keystring.push "`#{k}`"
|
264
288
|
valuestring.push "#{(value.is_a?(Numeric)) ? value : "\'#{value}\'"}"
|
265
289
|
else
|
266
|
-
pkvalue = "WHERE `#{self.class.primary_key}`=#{
|
290
|
+
pkvalue = "WHERE `#{self.class.primary_key}`=#{
|
291
|
+
(value.is_a?(Numeric)) ? value : "\'#{value}\'"
|
292
|
+
}"
|
267
293
|
end
|
268
294
|
end
|
269
295
|
if pkvalue
|
270
296
|
response = Ink::Database.database.find self.class, pkvalue
|
271
297
|
if response.empty?
|
272
|
-
Ink::Database.database.query
|
298
|
+
Ink::Database.database.query <<QUERY
|
299
|
+
INSERT INTO #{self.class.table_name}
|
300
|
+
(#{keystring * ","}) VALUES
|
301
|
+
(#{valuestring * ","});
|
302
|
+
QUERY
|
273
303
|
pk = Ink::Database.database.last_inserted_pk(self.class)
|
274
|
-
|
304
|
+
if pk
|
305
|
+
instance_variable_set("@#{self.class.primary_key}",
|
306
|
+
pk.is_a?(Numeric) ? pk : "\'#{pk}\'")
|
307
|
+
end
|
275
308
|
else
|
276
|
-
Ink::Database.database.query
|
309
|
+
Ink::Database.database.query <<QUERY
|
310
|
+
UPDATE #{self.class.table_name} SET #{string * ","} #{pkvalue};
|
311
|
+
QUERY
|
277
312
|
end
|
278
313
|
end
|
279
314
|
|
@@ -281,8 +316,10 @@ module Ink
|
|
281
316
|
self.class.foreign.each do |k,v|
|
282
317
|
value = instance_variable_get "@#{self.class.str_to_tablename(k)}"
|
283
318
|
if value
|
284
|
-
Ink::Database.database.delete_all_links
|
285
|
-
|
319
|
+
Ink::Database.database.delete_all_links(self,
|
320
|
+
Ink::Model.classname(k), v)
|
321
|
+
Ink::Database.database.create_all_links(self,
|
322
|
+
Ink::Model.classname(k), v, value)
|
286
323
|
end
|
287
324
|
end
|
288
325
|
end
|
@@ -294,15 +331,24 @@ module Ink
|
|
294
331
|
# obsolete. Disregard from using the instance anymore.
|
295
332
|
# All links between models will be removed also.
|
296
333
|
def delete
|
297
|
-
|
334
|
+
if not self.class.respond_to? :fields
|
335
|
+
raise NotImplementedError.new(<<ERR)
|
336
|
+
Cannot delete from Database without field definitions
|
337
|
+
ERR
|
338
|
+
end
|
298
339
|
if self.class.respond_to? :foreign
|
299
340
|
self.class.foreign.each do |k,v|
|
300
|
-
Ink::Database.database.delete_all_links
|
341
|
+
Ink::Database.database.delete_all_links(self,
|
342
|
+
Ink::Model.classname(k), v)
|
301
343
|
end
|
302
344
|
end
|
303
345
|
|
304
346
|
pkvalue = instance_variable_get "@#{self.class.primary_key}"
|
305
|
-
Ink::Database.database.remove self.class.name,
|
347
|
+
Ink::Database.database.remove self.class.name, <<QUERY
|
348
|
+
WHERE `#{self.class.primary_key}`=#{
|
349
|
+
(pkvalue.is_a?(Numeric)) ? pkvalue : "\'#{pkvalue}\'"
|
350
|
+
}
|
351
|
+
QUERY
|
306
352
|
end
|
307
353
|
|
308
354
|
# Instance method
|
@@ -311,11 +357,15 @@ module Ink
|
|
311
357
|
# matching foreign accessor
|
312
358
|
# [param foreign_class:] Defines the foreign class name or class
|
313
359
|
def find_references(foreign_class)
|
314
|
-
c = (foreign_class.is_a? Class) ? foreign_class :
|
360
|
+
c = (foreign_class.is_a? Class) ? foreign_class :
|
361
|
+
Ink::Model.classname(foreign_class)
|
315
362
|
relationship = self.class.foreign[c.class_name]
|
316
363
|
if relationship
|
317
|
-
result_array = (relationship == "many_many") ?
|
318
|
-
|
364
|
+
result_array = (relationship == "many_many") ?
|
365
|
+
Ink::Database.database.find_union(self.class, self.pk, c) :
|
366
|
+
Ink::Database.database.find_references(self.class, self.pk, c)
|
367
|
+
instance_variable_set("@#{c.table_name}",
|
368
|
+
(relationship =~ /^one_/) ? result_array.first : result_array)
|
319
369
|
true
|
320
370
|
else
|
321
371
|
false
|
@@ -330,7 +380,11 @@ module Ink
|
|
330
380
|
# [returns:] Array of SQL statements
|
331
381
|
def self.create
|
332
382
|
result = Array.new
|
333
|
-
|
383
|
+
if not self.respond_to?(:fields)
|
384
|
+
raise NotImplementedError.new(<<ERR)
|
385
|
+
Cannot create a Database without field definitions
|
386
|
+
ERR
|
387
|
+
end
|
334
388
|
|
335
389
|
string = "CREATE TABLE #{self.table_name} ("
|
336
390
|
mfk = self.foreign_key
|
@@ -346,7 +400,12 @@ module Ink
|
|
346
400
|
tmp = self.foreign.map do |k,v|
|
347
401
|
f_class = Ink::Model::classname(k)
|
348
402
|
if v == "many_many" and (self.name <=> k) < 0
|
349
|
-
result.push
|
403
|
+
result.push <<QUERY
|
404
|
+
CREATE TABLE #{self.table_name}_#{Ink::Model::str_to_tablename(k)}
|
405
|
+
(#{Ink::Database.database.primary_key_autoincrement*" "},
|
406
|
+
`#{self.foreign_key}` #{self.foreign_key_type},
|
407
|
+
`#{f_class.foreign_key}` #{f_class.foreign_key_type});
|
408
|
+
QUERY
|
350
409
|
nil
|
351
410
|
end
|
352
411
|
if v == "one_many" or (v == "one_one" and (self.name <=> k) < 0)
|
@@ -387,9 +446,12 @@ module Ink
|
|
387
446
|
def self.str_to_classname(str)
|
388
447
|
res = []
|
389
448
|
str.scan(/((^|_)([a-z0-9]+))/) { |s|
|
390
|
-
|
449
|
+
if s.length > 0
|
450
|
+
res.push(s[2][0].upcase +
|
451
|
+
((s[2].length > 1) ? s[2][1,s[2].length] : ""))
|
452
|
+
end
|
391
453
|
}
|
392
|
-
|
454
|
+
Module.const_get(res.join).is_a?(Class) ? res.join : nil
|
393
455
|
end
|
394
456
|
|
395
457
|
# Class method
|
@@ -404,7 +466,7 @@ module Ink
|
|
404
466
|
str.scan(/([A-Z][a-z0-9]*)/) { |s|
|
405
467
|
res.push (res.length>0) ? "_" + s.join.downcase : s.join.downcase
|
406
468
|
}
|
407
|
-
|
469
|
+
Module.const_get(str).is_a?(Class) ? res.join : nil
|
408
470
|
end
|
409
471
|
|
410
472
|
# Class method
|
@@ -418,12 +480,15 @@ module Ink
|
|
418
480
|
res = []
|
419
481
|
if str[0] =~ /^[a-z]/
|
420
482
|
str.scan(/((^|_)([a-z0-9]+))/) { |s|
|
421
|
-
|
483
|
+
if s.length > 0
|
484
|
+
res.push(s[2][0].upcase +
|
485
|
+
((s[2].length > 1) ? s[2][1,s[2].length] : ""))
|
486
|
+
end
|
422
487
|
}
|
423
488
|
else
|
424
489
|
res.push str
|
425
490
|
end
|
426
|
-
|
491
|
+
Module.const_get(res.join).is_a?(Class) ? Module.const_get(res.join) : nil
|
427
492
|
end
|
428
493
|
|
429
494
|
# Class method
|
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: 3.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,16 +9,16 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: rack
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.5.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,28 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: simple-mmap
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 1.1.4
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 1.1.4
|
29
|
+
version: 1.5.2
|
46
30
|
description:
|
47
31
|
email:
|
48
32
|
executables:
|
49
33
|
- webink_database
|
50
|
-
-
|
34
|
+
- webink_init
|
51
35
|
extensions: []
|
52
36
|
extra_rdoc_files: []
|
53
37
|
files:
|
@@ -57,7 +41,7 @@ files:
|
|
57
41
|
- lib/webink/database.rb
|
58
42
|
- lib/webink/model.rb
|
59
43
|
- bin/webink_database
|
60
|
-
- bin/
|
44
|
+
- bin/webink_init
|
61
45
|
- LICENSE.md
|
62
46
|
homepage: https://github.com/matthias-geier/WebInk
|
63
47
|
licenses: []
|
data/bin/rfcgi
DELETED
@@ -1,143 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "fcgi"
|
4
|
-
require "simple_mmap"
|
5
|
-
require "webink/beauty"
|
6
|
-
|
7
|
-
def getBinding(cgi,env,params)
|
8
|
-
return binding
|
9
|
-
end
|
10
|
-
def error(cgi, code)
|
11
|
-
puts cgi.header
|
12
|
-
puts cgi.header("nph" => true, "status" => code, "connection" => "close", "type" => "text/html")
|
13
|
-
end
|
14
|
-
|
15
|
-
script = nil
|
16
|
-
fhandle = nil
|
17
|
-
control = nil
|
18
|
-
pram = nil
|
19
|
-
is_production = nil
|
20
|
-
use_errors = nil
|
21
|
-
FCGI.each_cgi do |cgi|
|
22
|
-
is_production = ((cgi.env_table["INK_PRODUCTION"] and eval cgi.env_table["INK_PRODUCTION"]) or (ENV["INK_PRODUCTION"] and eval ENV["INK_PRODUCTION"])) ? true : false
|
23
|
-
use_errors = ((cgi.env_table["INK_ERRORS"] and eval cgi.env_table["INK_ERRORS"]) or (ENV["INK_ERRORS"] and eval ENV["INK_ERRORS"])) ? true : false
|
24
|
-
time = Time.now
|
25
|
-
script = cgi.env_table['SCRIPT_FILENAME']
|
26
|
-
begin
|
27
|
-
pram = Hash.new
|
28
|
-
CGI::parse(cgi.env_table['QUERY_STRING'].gsub(/\?/, "&")).each do |k,v|
|
29
|
-
if v.is_a? Array
|
30
|
-
if v.length == 0
|
31
|
-
pram[k] = nil
|
32
|
-
elsif v.length == 1
|
33
|
-
pram[k] = v[0]
|
34
|
-
else
|
35
|
-
pram[k] = v
|
36
|
-
end
|
37
|
-
else
|
38
|
-
pram[k] = v
|
39
|
-
end
|
40
|
-
end
|
41
|
-
control = pram['controller']
|
42
|
-
routes = Ink::Beauty.load_routes script
|
43
|
-
fhandle = SimpleMmap::MappedFile.new(routes)
|
44
|
-
Dir.chdir( File.dirname(routes) )
|
45
|
-
control = eval fhandle.read_window_data(0,fhandle.size), getBinding(cgi,cgi.env_table,control) if fhandle
|
46
|
-
fhandle.close
|
47
|
-
raise StandardError.new("Routes not matched.") if control.keys.length <= 1
|
48
|
-
|
49
|
-
control[:get] = pram
|
50
|
-
control[:config] = Ink::Beauty.load_config script
|
51
|
-
control[:time] = time
|
52
|
-
control[:cgi] = cgi
|
53
|
-
control[:env] = ENV
|
54
|
-
control[:is_production] = is_production
|
55
|
-
control[:use_errors] = use_errors
|
56
|
-
if cgi.env_table['REQUEST_METHOD'] == 'POST'
|
57
|
-
control[:post] = Hash.new
|
58
|
-
cgi.params.each do |k,v|
|
59
|
-
if v.is_a? Array
|
60
|
-
control[:post][k] = Array.new
|
61
|
-
v.each do |a|
|
62
|
-
control[:post][k].push((control[:config]["escape_post_data"]) ? CGI::escapeHTML(a) : a)
|
63
|
-
end
|
64
|
-
control[:post][k] = control[:post][k][0] if control[:post][k].length <= 1
|
65
|
-
else
|
66
|
-
control[:post][k] = (control[:config]["escape_post_data"]) ? CGI::escapeHTML(v) : v
|
67
|
-
end
|
68
|
-
end
|
69
|
-
pram.each do |k,v|
|
70
|
-
cgi.params[k] = v if not cgi.params.has_key? k
|
71
|
-
end
|
72
|
-
else
|
73
|
-
cgi.params = pram
|
74
|
-
end
|
75
|
-
|
76
|
-
script = Ink::Beauty.load_init script
|
77
|
-
fhandle = SimpleMmap::MappedFile.new(script)
|
78
|
-
Dir.chdir( File.dirname(script) )
|
79
|
-
eval fhandle.read_window_data(0,fhandle.size), getBinding(cgi,cgi.env_table,control) if fhandle
|
80
|
-
fhandle.close
|
81
|
-
|
82
|
-
rescue LoadError => bang
|
83
|
-
if is_production
|
84
|
-
puts cgi.header({"Location" => "/status-404.html"}) if use_errors
|
85
|
-
error cgi, "NOT_FOUND" if not use_errors
|
86
|
-
else
|
87
|
-
puts cgi.header
|
88
|
-
puts "<hr><b>LoadError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
89
|
-
end
|
90
|
-
|
91
|
-
rescue NotImplementedError => bang
|
92
|
-
if is_production
|
93
|
-
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
94
|
-
error cgi, "SERVER_ERROR" if not use_errors
|
95
|
-
else
|
96
|
-
puts cgi.header
|
97
|
-
puts "<hr><b>NotImplementedError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
98
|
-
end
|
99
|
-
|
100
|
-
rescue ArgumentError => bang
|
101
|
-
if is_production
|
102
|
-
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
103
|
-
error cgi, "SERVER_ERROR" if not use_errors
|
104
|
-
else
|
105
|
-
puts cgi.header
|
106
|
-
puts "<hr><b>ArgumentError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
107
|
-
end
|
108
|
-
|
109
|
-
rescue RuntimeError => bang
|
110
|
-
if is_production
|
111
|
-
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
112
|
-
error cgi, "SERVER_ERROR" if not use_errors
|
113
|
-
else
|
114
|
-
puts cgi.header
|
115
|
-
puts "<hr><b>RuntimeError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
116
|
-
end
|
117
|
-
|
118
|
-
rescue NameError => bang
|
119
|
-
if is_production
|
120
|
-
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
121
|
-
error cgi, "SERVER_ERROR" if not use_errors
|
122
|
-
else
|
123
|
-
puts cgi.header
|
124
|
-
puts "<hr><b>NameError:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
125
|
-
end
|
126
|
-
|
127
|
-
rescue Exception, StandardError => bang
|
128
|
-
if is_production
|
129
|
-
puts cgi.header({"Location" => "/status-500.html"}) if use_errors
|
130
|
-
error cgi, "SERVER_ERROR" if not use_errors
|
131
|
-
else
|
132
|
-
puts cgi.header
|
133
|
-
puts "<hr><b>Exception:</b>", "<em><pre>", CGI::escapeHTML("#{bang}"), "</pre></em>\n", "<pre>", bang.backtrace.join("\n"), "</pre>"
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
script = nil
|
138
|
-
fhandle = nil
|
139
|
-
control = nil
|
140
|
-
pram = nil
|
141
|
-
GC.start
|
142
|
-
end
|
143
|
-
|