actionframework 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2dfbfdbff057caaa49f475b6181cfe8a8c65a1c
4
- data.tar.gz: a232de6f77636b5790bd31cb3f06887da70223a3
3
+ metadata.gz: 3aedef6d1f194574cd1d6d70060908e52a00d3f8
4
+ data.tar.gz: b3a016326a7c9d37233d02905ffa5f6cc40a3c74
5
5
  SHA512:
6
- metadata.gz: 60ca2cf0c2938de702fa57cebaa58bcd4fd4d6e5c5522454337a55bea0ec1f3db7ce60308f674bccc7def60214980d97fe03d6cfd5e21725c7d2c4ebf0de90d3
7
- data.tar.gz: 4167766a9254097c0b2f8aca143708a9dae10c9b3f01a109b7b955e590ed84f9a112972efc724a72bbeac3ca059cfe62babc1b35caeb41ee77e226ce72bb2b47
6
+ metadata.gz: de9f3c95ef8262b36a83823e0ff6947187810eda5506c818020aac3818b0911736524227e5759fe62297f3fe1d9a7b27190795f50a19cbe0c07a962e5f07f857
7
+ data.tar.gz: 20399cbb33d4ac43b61b40dec725e5250f5e17102b6d66403b9c88d8a6fd0954dfc02e376d1d0b56707f0c3be743c693f5d7807b15432120516afed820227b05
data/bin/action ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optitron'
3
+ require 'fileutils'
4
+ require 'actionframework'
5
+ require 'json'
6
+ require 'httparty'
7
+
8
+ class String
9
+ def black; "\033[30m#{self}\033[0m" end
10
+ def red; "\033[31m#{self}\033[0m" end
11
+ def green; "\033[32m#{self}\033[0m" end
12
+ def brown; "\033[33m#{self}\033[0m" end
13
+ def blue; "\033[34m#{self}\033[0m" end
14
+ def magenta; "\033[35m#{self}\033[0m" end
15
+ def cyan; "\033[36m#{self}\033[0m" end
16
+ def gray; "\033[37m#{self}\033[0m" end
17
+ def bg_black; "\033[40m#{self}\0330m" end
18
+ def bg_red; "\033[41m#{self}\033[0m" end
19
+ def bg_green; "\033[42m#{self}\033[0m" end
20
+ def bg_brown; "\033[43m#{self}\033[0m" end
21
+ def bg_blue; "\033[44m#{self}\033[0m" end
22
+ def bg_magenta; "\033[45m#{self}\033[0m" end
23
+ def bg_cyan; "\033[46m#{self}\033[0m" end
24
+ def bg_gray; "\033[47m#{self}\033[0m" end
25
+ def bold; "\033[1m#{self}\033[22m" end
26
+ def reverse_color; "\033[7m#{self}\033[27m" end
27
+ end
28
+
29
+ class ActionFrameworkCLI < Optitron::CLI
30
+ desc "About ActionFramework"
31
+ def about
32
+ puts "ActionFramework (previously called ActionFramework) is a web application framework that tries to be as flexible as sinatra and at the same time have the structure of rails.Enjoy!"
33
+ end
34
+ desc "Create ActionFramework project"
35
+ def new projectname
36
+ puts "Creating project directory and structure"
37
+ Dir.mkdir("#{projectname}")
38
+ Dir.mkdir("#{projectname}/controllers")
39
+ Dir.mkdir("#{projectname}/models")
40
+ Dir.mkdir("#{projectname}/views")
41
+ Dir.mkdir("#{projectname}/config")
42
+ Dir.mkdir("#{projectname}/static")
43
+ Dir.mkdir("#{projectname}/initializers")
44
+ FileUtils.touch("#{projectname}/views/layout.html.erb")
45
+ FileUtils.touch("#{projectname}/Gemfile")
46
+ File.write("#{projectname}/main.rb","# Example of basic configuration\nActionFramework = ActionFramework::Server.new\n\nnActionFramework.autoimport\nActionFramework.start")
47
+ File.write("#{projectname}/controllers/default_controller.rb","class DefaultController < ActionFramework::Controller
48
+ \n def index\n \"<h1>Welcome to ActionFramework</h1><i>Great Opensource Ruby Server</i><p>ActionFramework 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");
49
+ File.write("#{projectname}/routes.json","{\n \"get\": [{\n \"/\": \"DefaultController#index\"\n}]\n}")
50
+ File.write("#{projectname}/config/routes.rb","ActionFramework::Server.current.routes do\n\n get \"/\" => \"DefaultController#index\"\n\nend")
51
+ File.write("#{projectname}/config/settings.rb","ActionFramework::Server.current.settings do |s|\n\nend")
52
+ File.write("#{projectname}/Gemfile","source 'https://rubygems.org'\n\ngem 'actionframework'")
53
+ File.write("#{projectname}/config.ru","require 'actionframework'\n\nrun ActionFramework::Base.new")
54
+ File.write("#{projectname}/config/plugables.rb","ActionFramework::Plugables.new do \n\nend")
55
+ system("cd #{projectname} && bundle install")
56
+ puts "Done"
57
+ puts "Run \"afw s\" to run your app"
58
+ end
59
+
60
+ desc "Start ActionFramework server"
61
+ def s
62
+ `rackup`
63
+ end
64
+
65
+ desc "Start ActionFramework console"
66
+ def c
67
+ $runningserver = ActionFramework::Server.new
68
+ puts "Starting ActionFramework IRB"
69
+ require 'irb'
70
+ ARGV.clear
71
+ IRB.start
72
+ end
73
+
74
+ desc "Install Stock plugables and add sources list"
75
+ def install_plugables
76
+ puts "Creating plugables directory".blue
77
+ puts "Downloading plugables sources list...".blue
78
+ Dir.mkdir(Dir.home+"/.actionframework/")
79
+ Dir.mkdir(Dir.home+"/.actionframework/plugables/")
80
+ Dir.mkdir(Dir.home+"/.actionframework/plugables/sources/")
81
+ Dir.mkdir(Dir.home+"/.actionframework/plugables/plugs/")
82
+
83
+ begin
84
+ plugables = HTTParty.get("https://raw.github.com/actionframework/plubables/master/sources.json").body
85
+ File.write(Dir.home+"/.actionframework/plugables/sources/list.json",plugables)
86
+ puts "Downloading stock plugables...".blue
87
+ plugables["stock"].each do |plugable|
88
+ puts "Downloading ".plugable["name"]+"..."
89
+ source = HTTParty.get("https://raw.github.com/actionframework/plugables/master/plugs/"+plugable["name"]+".rb").body
90
+ File.write(Dir.home+"/.actionframework/plugables/plugs/"+plugable["name"],source)
91
+ end
92
+ rescue Exception => e
93
+ puts "ERROR: Something went wrong".red
94
+ puts "ERROR: "+e.message.red
95
+ puts "LOG: "+e.backtrace.inspect
96
+ end
97
+ puts "Done".green
98
+ end
99
+ end
100
+
101
+ ActionFrameworkCLI.dispatch
@@ -3,9 +3,16 @@ require 'tilt'
3
3
  require 'json'
4
4
  require 'erb'
5
5
 
6
+ require 'actionframework/string'
7
+ require 'actionframework/gemextra'
8
+ require 'actionframework/gem'
6
9
  require 'actionframework/routes'
7
10
  require 'actionframework/controller'
8
11
  require 'actionframework/settings'
12
+ require 'actionframework/error_handler'
13
+ require 'actionframework/modelhelper'
14
+ require 'actionframework/realtime'
15
+ require 'actionframework/base'
9
16
 
10
17
  $runningserver = nil
11
18
 
@@ -44,6 +51,7 @@ module ActionFramework
44
51
 
45
52
  require './config/routes'
46
53
  require './config/settings'
54
+ require './config/plugables'
47
55
 
48
56
  Dir.glob("initializers/*").each do |file|
49
57
  require './'+file
@@ -55,9 +63,13 @@ module ActionFramework
55
63
  req = Rack::Request.new(env)
56
64
  res = Rack::Response.new
57
65
 
66
+ # auto-api feature (only at path /api/*)
67
+ getModelResponse req,res
68
+
58
69
  controllerinfo = @routesklass.route(req.path,req.request_method)
59
70
  if(controllerinfo == nil)
60
- res.write "<h1>404 Not found</h1>"
71
+ res.body = [ActionFramework::ErrorHandler.new(req,res,{}).send("error_404")]
72
+ res.status = 404
61
73
  return res.finish
62
74
  end
63
75
 
@@ -80,5 +92,32 @@ module ActionFramework
80
92
  def start
81
93
  Rack::Server.new({:app => self,:server => @settings.server, :Port => @settings.port}).start
82
94
  end
95
+
96
+ def getModelResponse req,res
97
+ # auto-api start
98
+ # [todo] add api security with policies
99
+ if(matcheddate = req.path.match(Regexp.new("^/api/(?<modelname>(.*))$")))
100
+ policy = @routesklass.models[matcheddata[:modelname]]
101
+ if(policy != nil)
102
+ res.headers = {"Content-type" => "application/json"}
103
+ model = Object.const_get(matcheddata[:modelname])
104
+ case req.request_method
105
+ when "POST"
106
+ ActionFramework::ModelHelper.post model,res
107
+ when "GET"
108
+ ActionFramework::ModelHelper.get model,res
109
+ when "UPDATE"
110
+ ActionFramework::ModelHelper.update model,res
111
+ when "DELETE"
112
+
113
+ else
114
+
115
+ end
116
+
117
+ end
118
+ end
119
+ # end auto-api
120
+ end
121
+
83
122
  end
84
123
  end
@@ -0,0 +1,26 @@
1
+ #######################
2
+ # Licenced under MIT ##
3
+ ### © BramVDB.com #####
4
+ #######################
5
+ module ActionFramework
6
+ # Base class (in config.ru -> run ActionFramework::Base.new)
7
+ class Base
8
+ def initialize
9
+ @app = Rack::Builder.new do
10
+ map '/static' do
11
+ run Rack::File.new("static")
12
+ end
13
+
14
+ map '/realtime' do
15
+ run ActionFramework::Realtime.new
16
+ end
17
+
18
+ run ActionFramework::Server.current
19
+ end
20
+ end
21
+
22
+ def call env
23
+ @app.call(env)
24
+ end
25
+ end
26
+ end
@@ -32,5 +32,29 @@ module ActionFramework
32
32
  output = renderer.render(self){ Tilt::ERBTemplate.new("views/"+template.to_s+".html.erb").render(self) }
33
33
  return output
34
34
  end
35
+
36
+ def erb_text erb_text
37
+ renderer = Tilt::ERBTemplate.new("views/layout.html.erb")
38
+ output = renderer.render(self){ erb_text }
39
+ return output
40
+ end
41
+
42
+ def error_erb code
43
+ if(Dir.exists? "views/errors")
44
+ renderer = Tilt::ERBTemplate.new("views/layout.html.erb")
45
+ output = renderer.render(self){ Tilt::ERBTemplate.new("views/errors/#{code}.html.erb").render(self) }
46
+ return output
47
+ else
48
+ root = ActionFramework::Gem.root
49
+ libdir = root.resources.to_s
50
+ puts ActionFramework::Gem.root.inspect
51
+ renderer = Tilt::ERBTemplate.new(libdir+"/views/errors/layout.html.erb")
52
+ output = renderer.render(self){ Tilt::ERBTemplate.new(libdir+"/views/errors/#{code}.html.erb").render(self) }
53
+ end
54
+ end
55
+
56
+ def session
57
+ @req.session
58
+ end
35
59
  end
36
60
  end
@@ -0,0 +1,17 @@
1
+ module ActionFramework
2
+
3
+ class ErrorHandler < ActionFramework::Controller
4
+ def error_404
5
+ error_erb "404"
6
+ end
7
+
8
+ def error_500
9
+ error_erb "500"
10
+ end
11
+
12
+ def error_403
13
+ error_erb "403"
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,6 @@
1
+ require 'jewel'
2
+ module ActionFramework
3
+ class Gem < Jewel::Gem
4
+ root "../.."
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module Gem
2
+ class Specification
3
+ def self.find_lib_dir_by_name name
4
+ spec = Gem::Specification.find_by_name(name)
5
+ gem_root = spec.gem_dir
6
+ gem_lib = gem_root + "/lib"
7
+ gem_lib
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+ module ActionFramework
2
+ class ModelHelper
3
+ def self.post model,res
4
+ response = model.create(JSON.parse(req.body.string)).to_json
5
+ res.write response
6
+ res.finish
7
+ end
8
+
9
+ def self.get model,res
10
+ response = model.all.to_json
11
+ res.write response
12
+ res.finish
13
+ end
14
+
15
+ def self.update model,res
16
+ doc = JSON.parse(req.body.string)
17
+ modelfind = model.where(doc[:where])
18
+ response = modelfind.update_attributes(doc[:attributes]).to_json
19
+ res.write response
20
+ res.finish
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ #######################
2
+ # Licenced under MIT ##
3
+ ### © BramVDB.com #####
4
+ #######################
5
+
6
+ module ActionFramework
7
+ class Plugables
8
+ def initialize &block
9
+ @index = JSON.parse(File.read(Gem::Specification.find_lib_dir_by_name("actionframework")+"/plugables/index.json"))
10
+ self.instance_eval &block
11
+ end
12
+
13
+ def plug name
14
+ if @index["plugs"].include? name
15
+ require Gem::Specification.find_lib_dir_by_name("actionframework")+'/plugables/'+name
16
+ end
17
+ Object.const_get(name.classify).new if(Object.const_get(name.classify).superclass.to_s == "ActionFramework::Plugable::Initializer")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ #######################
2
+ # Licenced under MIT ##
3
+ ### © BramVDB.com #####
4
+ #######################
5
+ module ActionFramework
6
+ module Plugable
7
+ class Initializer
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ #######################
2
+ # Licenced under MIT ##
3
+ ### © BramVDB.com #####
4
+ #######################
5
+ require 'rack/websocket'
6
+
7
+ module ActionFramework
8
+ class Realtime < Rack::WebSocket::Application
9
+ def on_open env
10
+
11
+ puts "Client connected"
12
+ end
13
+ end
14
+ end
@@ -6,6 +6,8 @@
6
6
  module ActionFramework
7
7
  class Routes
8
8
  attr_accessor :routes
9
+ attr_accessor :models
10
+
9
11
  def initialize
10
12
  @routes = {:get => {}, :post => {}, :update => {}, :delete => {}, :patch => {}}
11
13
  end
@@ -39,6 +41,11 @@ module ActionFramework
39
41
  @routes[:patch][build_regex(hash.keys.first.to_s)] = hash[hash.keys.first.to_s]
40
42
  end
41
43
 
44
+ def model hash
45
+ # @models[name of the class of the model] = name of class of the access policy of the model
46
+ @models[hash.keys.first_to.s] = hash[hash.keys.first.to_s]
47
+ end
48
+
42
49
  def route(path,method)
43
50
  @routes[method.downcase.to_sym].each do |regex,controller|
44
51
  puts regex
@@ -0,0 +1,13 @@
1
+ #######################
2
+ # Licenced under MIT ##
3
+ ### © BramVDB.com #####
4
+ #######################
5
+
6
+ # @author BramVDB.com
7
+ # @since 0.1.1
8
+ class String
9
+ # @return [String] Classified string
10
+ def classify
11
+ self.split('_').collect(&:capitalize).join
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 actionframework
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ plugables
2
+ =========
3
+
4
+ ActionFramework Plugables
@@ -0,0 +1,5 @@
1
+ {
2
+ "plugs": [
3
+ "mongomapper"
4
+ ]
5
+ }
@@ -0,0 +1,5 @@
1
+ class MongoMapper < ActionFramework::Plugable:Initializer
2
+ def initialize
3
+
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ {
2
+ "stock": [
3
+ {
4
+ "name": "mongomapper"
5
+ }
6
+ ]
7
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionframework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bram Vandenbogaerde
@@ -66,21 +66,76 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: websocket-rack
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: httparty
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: jewel
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
69
111
  description: A web framework built on top of Rack, it has the simplicity of sinatra
70
112
  and the structure of rails
71
113
  email: bram.vandenbogaerde@gmail.com
72
114
  executables:
73
- - afw
115
+ - action
74
116
  extensions: []
75
117
  extra_rdoc_files: []
76
118
  files:
119
+ - lib/actionframework/base.rb
77
120
  - lib/actionframework/controller.rb
121
+ - lib/actionframework/error_handler.rb
122
+ - lib/actionframework/gem.rb
123
+ - lib/actionframework/gemextra.rb
124
+ - lib/actionframework/modelhelper.rb
125
+ - lib/actionframework/plugables.rb
126
+ - lib/actionframework/plugmod.rb
78
127
  - lib/actionframework/rackup.rb
128
+ - lib/actionframework/realtime.rb
79
129
  - lib/actionframework/routes.rb
80
130
  - lib/actionframework/settings.rb
131
+ - lib/actionframework/string.rb
81
132
  - lib/actionframework.rb
82
- - lib/actionframework_old.rb
83
- - bin/afw
133
+ - lib/plugables/index.json
134
+ - lib/plugables/LICENSE
135
+ - lib/plugables/plugs/mongomapper.rb
136
+ - lib/plugables/README.md
137
+ - lib/plugables/sources.json
138
+ - bin/action
84
139
  homepage: http://rubygems.org/gems/actionframework
85
140
  licenses:
86
141
  - MIT
@@ -106,3 +161,4 @@ signing_key:
106
161
  specification_version: 4
107
162
  summary: A web framework built on top of Rack
108
163
  test_files: []
164
+ has_rdoc:
data/bin/afw DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'optitron'
3
- require 'fileutils'
4
- require 'actionframework'
5
- require 'json'
6
-
7
- class ActionFrameworkCLI < Optitron::CLI
8
- desc "About ActionFramework"
9
- def about
10
- puts "ActionFramework (previously called ActionFramework) 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\nActionFramework = ActionFramework::Server.new\n\nnActionFramework.autoimport\nActionFramework.start")
24
- File.write("#{projectname}/controllers/default_controller.rb","class DefaultController < ActionFramework::Controller
25
- \n def index\n \"<h1>Welcome to ActionFramework</h1><i>Great Opensource Ruby Server</i><p>ActionFramework 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","ActionFramework::Server.current.routes do\n\n get \"/\" => \"DefaultController#index\"\n\nend")
28
- File.write("#{projectname}/config/settings.rb","ActionFramework::Server.current.settings do |s|\n\nend")
29
- File.write("#{projectname}/Gemfile","source 'https://rubygems.org'\n\ngem 'actionframework'")
30
- system("cd #{projectname} && bundle install")
31
- puts "Done"
32
- puts "Run \"afw s\" to run your app"
33
- end
34
-
35
- desc "Start ActionFramework server"
36
- def s
37
- $runningserver = ActionFramework::Server.new
38
- ActionFramework::Server.current.start
39
- end
40
-
41
- desc "Start ActionFramework console"
42
- def c
43
- $runningserver = ActionFramework::Server.new
44
- puts "Starting ActionFramework IRB"
45
- require 'irb'
46
- ARGV.clear
47
- IRB.start
48
- end
49
- end
50
-
51
- ActionFrameworkCLI.dispatch
@@ -1,373 +0,0 @@
1
- require 'rack.rb'
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"],env["REQUEST_METHOD"].downcase)
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
- # Logic for models: in development
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 = Rack::Request.new(env)
74
- request.request.params = Rack::Utils.parse_query(env["QUERY_STRING"])
75
- Rack::Utils.parse_query(env["rack.input"].read).each do |key,value|
76
- request.request.params[key] = value
77
- end
78
-
79
- if(matcheddata != nil)
80
- request.request.params.merge! (matcheddata)
81
- end
82
- request.request.params.default = ""
83
-
84
- infoctrl = controller.split("#")
85
- ctrl = Object.const_get(infoctrl[0]).new(request)
86
-
87
- response = ctrl.send(infoctrl[1])
88
- if(@settings.server != "thin")
89
- response = [response]
90
- end
91
- [ctrl.info.response.status_code,ctrl.info.response.headers,response]
92
- end
93
-
94
- def start
95
- if(@settings.errorhandler != nil)
96
- @errorhandler = Object.const_get(@settings.errorhandler).new
97
- else
98
- @errorhandler = ActionFramework::DefaultErrorHandler.new
99
- end
100
-
101
- if(@settings.daemon)
102
- puts "Sending ActionFramework to background"
103
- system("kill `cat running.pid`")
104
- Process.daemon true
105
- File.write("running.pid",Process.pid)
106
- end
107
- @logger.log @routesklass.inspect
108
- Rack::Server.new({:app => self,:server => @settings.server, :Port => @settings.port}).start
109
- end
110
-
111
- def routes &block
112
- @routesklass.instance_eval &block
113
- end
114
-
115
- def settings
116
- yield(@settings)
117
- end
118
-
119
- def autoimport
120
- Dir.glob("controllers/*").each do |file|
121
- require './'+file
122
- end
123
-
124
- Dir.glob("models/*").each do |file|
125
- require './'+file
126
- end
127
-
128
- require './config/routes'
129
- require './config/settings'
130
-
131
- Dir.glob("initializers/*").each do |file|
132
- require './'+file
133
- end
134
-
135
- end
136
-
137
- end
138
- class Routes
139
- NAME_PATTERN = /:(\S+)/
140
-
141
- attr_accessor :routes
142
- attr_accessor :models
143
- attr_accessor :posts
144
-
145
- def initialize logger
146
- @routes = {:get => {}, :post => {},:update => {}, :delete => {},:patch => {}}
147
- @models = {}
148
- @logger = logger
149
- @routespost = {}
150
- end
151
-
152
- def get hash
153
- @routes[:get][pattern_for(hash.keys.first.to_s)] = hash[hash.keys.first.to_s]
154
- @logger.log "Adding route GET "+hash.keys.first.to_s
155
- end
156
-
157
- def post hash
158
- @routes[:post][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 update hash
163
- @routes[:update][hash.keys.first.to_s] = hash[hash.keys.first.to_s]
164
- @logger.log "Adding route UPDATE "+hash.keys.first.to_s
165
- end
166
-
167
- def delete hash
168
- @routes[:delete][hash.keys.first.to_s] = hash[hash.keys.first.to_s]
169
- @logger.log "Adding route DELETE "+hash.keys.first.to_s
170
- end
171
-
172
- def patch hash
173
- @routes[:patch][hash.keys.first.to_s] = hash[hash.keys.first.to_s]
174
- @logger.log "Adding route PATCH "+hash.keys.first.to_s
175
- end
176
-
177
- def model hash
178
- # In development
179
- @routes["/api/"+hash.keys.first.to_s] = "ActionFramework::Model#call:"+hash[hash.keys.first.to_s];
180
- puts "Adding model with path "+hash.keys.first.to_s
181
- end
182
-
183
- def routes(path,method)
184
- hash = {}
185
- controller = nil
186
- @routes[method.to_sym].each do |route,controller|
187
- if(matched = route.match path)
188
- matched.names.each do |name|
189
- hash[name] = matched[name]
190
- end
191
-
192
- return [controller,hash]
193
- end
194
- end
195
- end
196
- # Logic from github.com/alisnic/nyny
197
- def pattern_for signature
198
- if(signature.class == Regexp)
199
- return signature
200
- end
201
- build_regex(signature.start_with?('/') ? signature : "/#{signature}")
202
- end
203
-
204
- def build_regex signature
205
- return %r(^#{signature}$) unless signature.include?(':')
206
-
207
- groups = signature.split('/').map do |part|
208
- next part if part.empty?
209
- next part unless part.start_with? ':'
210
- name = NAME_PATTERN.match(part)[1]
211
- %Q{(?<#{name}>\\S+)}
212
- end.select {|s| !s.empty? }.join('\/')
213
-
214
- %r(^\/#{groups}$)
215
- end
216
- end
217
- class Controller
218
- attr_accessor :info
219
-
220
- def initialize(context)
221
- @info = context
222
- if(self.respond_to? "before")
223
- self.before
224
- end
225
- end
226
-
227
- def erb template
228
- renderer = Tilt::ERBTemplate.new("views/layout.html.erb")
229
- output = renderer.render(self){ Tilt::ERBTemplate.new("views/"+template.to_s+".html.erb").render(self) }
230
- return output
231
- end
232
-
233
- def params
234
- @info.req.params
235
- end
236
-
237
- def request
238
- @info.req
239
- end
240
-
241
- end
242
-
243
- class Request
244
- attr_accessor :response
245
- attr_accessor :request
246
- attr_accessor :req
247
-
248
- def initialize(env)
249
- @response = OpenStruct.new ({:headers => {}, :status_code => "200"})
250
- @request = OpenStruct.new ({:ip => "",:user_agent => "",:headers => {},:params => {}})
251
- @req = Rack::Request.new(env)
252
- end
253
-
254
- def info
255
- return @info
256
- end
257
- end
258
-
259
- class Model
260
- def initialize req
261
- @req = req
262
- end
263
-
264
- def call modelname
265
- case @req.request_method
266
- when "GET"
267
- if(Object.const_get(modelname.capitalize).respond_to? "append")
268
- model = Object.const_get(modelname.capitalize).all.send(Object.const_get(modelname.capitalize).append)
269
- else
270
- model = Object.const_get(modelname.capitalize).all
271
- end
272
- model.to_json
273
- when "POST"
274
- if(Object.const_get(modelname.capitalize).respond_to? "append")
275
- model = Object.const_get(modelname.capitalize).create(JSON.parse(@req.body.string))
276
- else
277
- model = Object.const_get(modelname.capitalize).create(JSON.parse(@req.body.string))
278
- end
279
- model.to_json
280
- else
281
-
282
- end
283
- end
284
-
285
- end
286
-
287
- class Settings
288
- attr_accessor :port
289
- attr_accessor :server
290
- attr_accessor :verbose
291
- attr_accessor :daemon
292
- attr_accessor :errorhandler
293
-
294
- def initialize
295
- @port = 8080
296
- @server = "puma"
297
- @verbose = true
298
- @daemon = false
299
- @errorhandler = nil
300
- end
301
- end
302
- class Logger
303
-
304
- def initialize(settings)
305
- @settings = settings
306
- end
307
-
308
- def log msg
309
- if(@settings.daemon)
310
- return
311
- end
312
- if(@settings.verbose)
313
- puts msg
314
- end
315
- end
316
-
317
- end
318
-
319
- class ErrorHelper
320
- def call(errortype)
321
- if(self.respond_to? "error_"+errortype)
322
- puts "Yes!!!!!"
323
- [errortype, {},[self.send("error_"+errortype)]]
324
- else
325
- [errortype, {}, [ActionFramework::DefaultErrorHandler.new.send("error_"+errortype)]]
326
- end
327
- end
328
-
329
- def erb template
330
- renderer = Tilt::ERBTemplate.new("views/layout.html.erb")
331
- output = renderer.render(self){ Tilt::ERBTemplate.new("views/"+template.to_s+".html.erb").render(self) }
332
- return output
333
- end
334
-
335
- end
336
-
337
- class DefaultErrorHandler < ActionFramework::ErrorHelper
338
- def error_404
339
- "<h1>404 Not Found</h1>"
340
- end
341
- def error_500
342
- "<h1>500 Internal server error</h1>"
343
- end
344
- def error_403
345
- "<h1>403 Forbidden</h1>"
346
- end
347
- end
348
- end
349
-
350
- at_exit do
351
- puts "Exiting..."
352
- if(File.exists? "running.pid")
353
- File.delete("running.pid")
354
- end
355
- end
356
-
357
-
358
- ########## IMPORTANT LOGIC SOON TO BE INTEGRATED ######
359
- string = "/{{appname}}/{{userid}}"
360
-
361
- string = string.gsub("{{","(?<")
362
- string = string.gsub("}}",">(.*))")
363
- string.insert(0,"^")
364
- string = string+"$"
365
- puts string
366
- regex = Regexp.new (string)
367
-
368
- puts regex
369
-
370
- if(matched = regex.match "/testapp/1")
371
- puts "matched"
372
- p matched
373
- end