actionframework 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/afw +49 -0
  2. data/lib/actionframework.rb +329 -0
  3. metadata +98 -0
data/bin/afw ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optitron'
3
+ require 'fileutils'
4
+ require 'gors'
5
+ require 'json'
6
+
7
+ class GorsCLI < Optitron::CLI
8
+ desc "About ActionFramework"
9
+ def about
10
+ puts "ActionFramework (previously called GORS) is a web application framework that tries to be as flexible as sinatra and at the same time have the structure of rails.Enjoy!"
11
+ end
12
+ desc "Create ActionFramework project"
13
+ def new projectname
14
+ puts "Creating project directory and structure"
15
+ Dir.mkdir("#{projectname}")
16
+ Dir.mkdir("#{projectname}/controllers")
17
+ Dir.mkdir("#{projectname}/models")
18
+ Dir.mkdir("#{projectname}/views")
19
+ Dir.mkdir("#{projectname}/config")
20
+ Dir.mkdir("#{projectname}/initializers")
21
+ FileUtils.touch("#{projectname}/views/layout.html.erb")
22
+ FileUtils.touch("#{projectname}/Gemfile")
23
+ File.write("#{projectname}/main.rb","# Example of basic configuration\ngors = Gors::Server.new\n\nngors.autoimport\ngors.start")
24
+ File.write("#{projectname}/controllers/default_controller.rb","class DefaultController < Gors::Controller
25
+ \n def index\n \"<h1>Welcome to ActionFramework</h1><i>Great Opensource Ruby Server</i><p>Gors is loading routes from routes.json but you should write your own main.rb<br/>This is just to gettings started</p>\"\n end\nend");
26
+ File.write("#{projectname}/routes.json","{\n \"get\": [{\n \"/\": \"DefaultController#index\"\n}]\n}")
27
+ File.write("#{projectname}/config/routes.rb","Gors::Server.current.routes do\n\n get \"/\" => \"DefaultController#index\"\n\nend")
28
+ File.write("#{projectname}/config/settings.rb","Gors::Server.current.settings do |s|\n\nend")
29
+ puts "Done"
30
+ puts "Test ActionFramework by running \"gors s\""
31
+ end
32
+
33
+ desc "Start gors server"
34
+ def s
35
+ Gors::Server.init
36
+ Gors::Server.current.start
37
+ end
38
+
39
+ desc "Start gors console"
40
+ def c
41
+ Gors::Server.init
42
+ puts "Starting Gors IRB"
43
+ require 'irb'
44
+ ARGV.clear
45
+ IRB.start
46
+ end
47
+ end
48
+
49
+ GorsCLI.dispatch
@@ -0,0 +1,329 @@
1
+ require 'rack'
2
+ require 'erb'
3
+ require 'tilt'
4
+ require 'json'
5
+ require 'ostruct'
6
+
7
+ $runningserver = nil
8
+
9
+ module ActionFramework
10
+ class Server
11
+ def self.init
12
+ require 'bundler'
13
+ Bundler.require(:default)
14
+ ActionFramework::Server.current = ActionFramework::Server.new
15
+ ActionFramework::Server.current.autoimport
16
+ end
17
+ def initialize
18
+ @settings = Settings.new
19
+ @logger = Logger.new(@settings)
20
+ @routesklass = Routes.new(@logger)
21
+ end
22
+
23
+ def self.current
24
+ if($runningserver.nil?)
25
+ ActionFramework::Server.init
26
+ $runningserver
27
+ else
28
+ $runningserver
29
+ end
30
+ end
31
+
32
+ def self.current=(runningserver)
33
+ $runningserver = runningserver
34
+ end
35
+
36
+ def run
37
+
38
+ end
39
+
40
+ def call env
41
+ if(@settings.errorhandler != nil)
42
+ @errorhandler = Object.const_get(@settings.errorhandler).new
43
+ else
44
+ @errorhandler = ActionFramework::DefaultErrorHandler.new
45
+ end
46
+
47
+ routesinfo = @routesklass.routes(env["REQUEST_PATH"])
48
+ controller = routesinfo[0]
49
+ @logger.log controller.inspect
50
+ matcheddata = routesinfo[1]
51
+
52
+ if(controller == nil)
53
+ if(@settings.server != "thin")
54
+ response = ["<h1>404 Not Found</h1>"]
55
+ else
56
+ response = "<h1>404 Not Found</h1>"
57
+ end
58
+ return @errorhandler.call "404"
59
+ end
60
+
61
+ #
62
+ if(controller.include? "ActionFramework::")
63
+ ctrl = controller.split("#")
64
+ params = ctrl[1].split(":")
65
+
66
+ req = Rack::Request.new(env)
67
+
68
+ data = Model.new(req).call(params[1])
69
+ return ["200",{"Content-type" => "application/json"},[data]]
70
+ end
71
+
72
+ # Call the Controller
73
+ request = Request.new
74
+ request.request.params = Rack::Utils.parse_query(env["QUERY_STRING"])
75
+ if(matcheddata != nil)
76
+ request.request.params.merge! (matcheddata)
77
+ end
78
+ request.request.params.default = ""
79
+
80
+ infoctrl = controller.split("#")
81
+ ctrl = Object.const_get(infoctrl[0]).new(request)
82
+
83
+ response = ctrl.send(infoctrl[1])
84
+ if(@settings.server != "thin")
85
+ response = [response]
86
+ end
87
+ [ctrl.info.response.status_code,ctrl.info.response.headers,response]
88
+ end
89
+
90
+ def start
91
+ if(@settings.errorhandler != nil)
92
+ @errorhandler = Object.const_get(@settings.errorhandler).new
93
+ else
94
+ @errorhandler = ActionFramework::DefaultErrorHandler.new
95
+ end
96
+
97
+ if(@settings.daemon)
98
+ puts "Sending ActionFramework to background"
99
+ system("kill `cat running.pid`")
100
+ Process.daemon true
101
+ File.write("running.pid",Process.pid)
102
+ end
103
+ @logger.log @routesklass.inspect
104
+ Rack::Server.new({:app => self,:server => @settings.server, :Port => @settings.port}).start
105
+ end
106
+
107
+ def routes &block
108
+ @routesklass.instance_eval &block
109
+ end
110
+
111
+ def settings
112
+ yield(@settings)
113
+ end
114
+
115
+ def autoimport
116
+ Dir.glob("controllers/*").each do |file|
117
+ require './'+file
118
+ end
119
+
120
+ Dir.glob("models/*").each do |file|
121
+ require './'+file
122
+ end
123
+
124
+ require './config/routes'
125
+ require './config/settings'
126
+
127
+ Dir.glob("initializers/*").each do |file|
128
+ require './'+file
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+ class Routes
135
+ NAME_PATTERN = /:(\S+)/
136
+
137
+ attr_accessor :routes
138
+ attr_accessor :models
139
+ attr_accessor :posts
140
+
141
+ def initialize logger
142
+ @routes = {}
143
+ @models = {}
144
+ @logger = logger
145
+ @routespost = {}
146
+ end
147
+
148
+ def get hash
149
+ @routes[pattern_for(hash.keys.first.to_s)] = hash[hash.keys.first.to_s]
150
+ @logger.log "Adding route GET "+hash.keys.first.to_s
151
+ end
152
+
153
+ def json
154
+ # TODO zorg evoor dat routes ook van routes.json gehaald kunnen worden (structuur zie generator in de CLI)
155
+ end
156
+
157
+ def post hash
158
+ @routespost[hash.keys.first.to_s] = hash[hash.keys.first.to_s]
159
+ @logger.log "Adding route POST "+hash.keys.first.to_s
160
+ end
161
+
162
+ def post
163
+
164
+ end
165
+
166
+ def model hash
167
+ @routes["/api/"+hash.keys.first.to_s] = "ActionFramework::Model#call:"+hash[hash.keys.first.to_s];
168
+ puts "Adding model with path "+hash.keys.first.to_s
169
+ end
170
+
171
+ def routes(path)
172
+ hash = {}
173
+ controller = nil
174
+ @routes.each do |route,controller|
175
+ if(matched = route.match path)
176
+ matched.names.each do |name|
177
+ hash[name] = matched[name]
178
+ end
179
+
180
+ return [controller,hash]
181
+ end
182
+ end
183
+ end
184
+ # Logic from github.com/alisnic/nyny
185
+ def pattern_for signature
186
+ if(signature.class == Regexp)
187
+ return signature
188
+ end
189
+ build_regex(signature.start_with?('/') ? signature : "/#{signature}")
190
+ end
191
+
192
+ def build_regex signature
193
+ return %r(^#{signature}$) unless signature.include?(':')
194
+
195
+ groups = signature.split('/').map do |part|
196
+ next part if part.empty?
197
+ next part unless part.start_with? ':'
198
+ name = NAME_PATTERN.match(part)[1]
199
+ %Q{(?<#{name}>\\S+)}
200
+ end.select {|s| !s.empty? }.join('\/')
201
+
202
+ %r(^\/#{groups}$)
203
+ end
204
+ end
205
+ class Controller
206
+ attr_accessor :info
207
+
208
+ def initialize(context)
209
+ @info = context
210
+ if(self.respond_to? "before")
211
+ self.before
212
+ end
213
+ end
214
+
215
+ def erb template
216
+ renderer = Tilt::ERBTemplate.new("views/layout.html.erb")
217
+ output = renderer.render(self){ Tilt::ERBTemplate.new("views/"+template.to_s+".html.erb").render(self) }
218
+ return output
219
+ end
220
+
221
+ def params
222
+ @info.request.params
223
+ end
224
+ end
225
+
226
+ class Request
227
+ attr_accessor :response
228
+ attr_accessor :request
229
+
230
+ def initialize
231
+ @response = OpenStruct.new ({:headers => {}, :status_code => "200"})
232
+ @request = OpenStruct.new ({:ip => "",:user_agent => "",:headers => {},:params => {}})
233
+ end
234
+
235
+ def info
236
+ return @info
237
+ end
238
+ end
239
+
240
+ class Model
241
+ def initialize req
242
+ @req = req
243
+ end
244
+
245
+ def call modelname
246
+ case @req.request_method
247
+ when "GET"
248
+ if(Object.const_get(modelname.capitalize).respond_to? "append")
249
+ model = Object.const_get(modelname.capitalize).all.send(Object.const_get(modelname.capitalize).append)
250
+ else
251
+ model = Object.const_get(modelname.capitalize).all
252
+ end
253
+ model.to_json
254
+ when "POST"
255
+ if(Object.const_get(modelname.capitalize).respond_to? "append")
256
+ model = Object.const_get(modelname.capitalize).create(JSON.parse(@req.body.string))
257
+ else
258
+ model = Object.const_get(modelname.capitalize).create(JSON.parse(@req.body.string))
259
+ end
260
+ model.to_json
261
+ else
262
+
263
+ end
264
+ end
265
+
266
+ end
267
+
268
+ class Settings
269
+ attr_accessor :port
270
+ attr_accessor :server
271
+ attr_accessor :verbose
272
+ attr_accessor :daemon
273
+ attr_accessor :errorhandler
274
+
275
+ def initialize
276
+ @port = 8080
277
+ @server = "puma"
278
+ @verbose = true
279
+ @daemon = false
280
+ @errorhandler = nil
281
+ end
282
+ end
283
+ class Logger
284
+
285
+ def initialize(settings)
286
+ @settings = settings
287
+ end
288
+
289
+ def log msg
290
+ if(@settings.daemon)
291
+ return
292
+ end
293
+ if(@settings.verbose)
294
+ puts msg
295
+ end
296
+ end
297
+
298
+ end
299
+
300
+ class ErrorHelper
301
+ def call(errortype)
302
+ if(self.respond_to? "error_"+errortype)
303
+ [errortype, {},[self.send("error_"+errortype)]]
304
+ else
305
+ ActionFramework::DefaultErrorHandler.new.send("error_"+errortype)
306
+ end
307
+ end
308
+ end
309
+
310
+ class DefaultErrorHandler < ActionFramework::ErrorHelper
311
+ def error_404
312
+ "<h1>404 Not Found</h1>"
313
+ end
314
+ def error_500
315
+ "<h1>500 Internal server error</h1>"
316
+ end
317
+ def error_403
318
+ "<h1>403 Forbidden</h1>"
319
+ end
320
+ end
321
+
322
+ end
323
+
324
+ at_exit do
325
+ puts "Exiting..."
326
+ if(File.exists? "running.pid")
327
+ File.delete("running.pid")
328
+ end
329
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: actionframework
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Bram Vandenbogaerde
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: tilt
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
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: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rack
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A web framework built on top of Rack, it has the simplicity of sinatra
63
+ and the structure of rails
64
+ email: bram.vandenbogaerde@gmail.com
65
+ executables:
66
+ - afw
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/actionframework.rb
71
+ - bin/afw
72
+ homepage: http://rubygems.org/gems/actionframework
73
+ licenses:
74
+ - MIT
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 1.8.23
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: A web framework built on top of Rack
97
+ test_files: []
98
+ has_rdoc: