microframe 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/console +14 -14
- data/bin/microframe +6 -0
- data/lib/microframe.rb +4 -3
- data/lib/microframe/application/application.rb +20 -0
- data/lib/microframe/application/generators/generator.rb +47 -0
- data/lib/microframe/application/generators/samples/app_sample/Gemfile +6 -0
- data/lib/microframe/application/generators/samples/app_sample/app/assets/images/.keep +0 -0
- data/lib/microframe/application/generators/samples/app_sample/app/assets/javascripts/.keep +0 -0
- data/lib/microframe/application/generators/samples/app_sample/app/assets/stylesheets/.keep +0 -0
- data/lib/microframe/application/generators/samples/app_sample/app/controllers/.keep +0 -0
- data/lib/microframe/application/generators/samples/app_sample/app/models/.keep +0 -0
- data/lib/microframe/application/generators/samples/app_sample/app/views/layouts/application.html.erb.tt +10 -0
- data/lib/microframe/application/generators/samples/app_sample/config.ru.tt +9 -0
- data/lib/microframe/application/generators/samples/app_sample/config/routes.rb.tt +7 -0
- data/lib/microframe/application/generators/samples/app_sample/db/config.rb.tt +7 -0
- data/lib/microframe/application/generators/samples/app_sample/public/404.html.erb.tt +10 -0
- data/lib/microframe/application/generators/samples/sample_controller.tt +8 -0
- data/lib/microframe/application/generators/samples/sample_model.tt +10 -0
- data/lib/microframe/controller/application_controller.rb +71 -0
- data/lib/microframe/orm/base.rb +18 -0
- data/lib/microframe/orm/class_queries.rb +133 -0
- data/lib/microframe/orm/connection.rb +30 -0
- data/lib/microframe/orm/instance_queries.rb +41 -0
- data/lib/microframe/orm/query_utils.rb +72 -0
- data/lib/microframe/orm/relationships.rb +28 -0
- data/lib/microframe/routing/mapper.rb +85 -0
- data/lib/microframe/routing/router.rb +86 -0
- data/lib/microframe/version.rb +1 -1
- data/microframe.gemspec +6 -4
- metadata +75 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b26273e0e3a66da31bd5ef27ec8e035a639ef6c
|
4
|
+
data.tar.gz: c783982497042b856f64fccf544c71dac1de3482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9b7a5966a249c8567ed6fe9056874f216069e4662fe0a6dc4a2ad6f4911f00db1cf1768f0cabc4f7746cd46ae1f68d404dd7988388d24287195a08686a827db
|
7
|
+
data.tar.gz: dc024b84ebcbf29345824c63640206e76ab0cbe1bba7b41a07f620dae4dd1435f2818c4658bc411ff892e0bf0cecc07b10e9220df00911fe22837d8cac9f28e9
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "microframe"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "microframe"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/microframe
ADDED
data/lib/microframe.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(__dir__, "../", "routing", "router")
|
2
|
+
|
3
|
+
module Microframe
|
4
|
+
class Application
|
5
|
+
attr_reader :request, :routes
|
6
|
+
def initialize
|
7
|
+
@routes = Router.new
|
8
|
+
require File.join(__dir__, "..", "orm", "base")
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
@request = Rack::Request.new(env)
|
13
|
+
verb = request.request_method
|
14
|
+
path = request.path_info
|
15
|
+
routes.request = request
|
16
|
+
|
17
|
+
routes.handle_request(verb, path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
module Microframe
|
4
|
+
class Generator < Thor
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
attr_reader :app_name, :type, :name, :xtras
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
File.join(__dir__, "samples")
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "new NAME", "Creates a new Microframe project called NAME"
|
14
|
+
def new(name)
|
15
|
+
@app_name = name
|
16
|
+
directory("app_sample", "#{app_name}")
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "generate TYPE NAME OPTIONS", "Generates microframe resource of TYPE (i.e. model, controller or view) with the given NAME extra options specific to TYPE can also be provided"
|
20
|
+
def generate(type, name, *xtras)
|
21
|
+
@type = type.downcase
|
22
|
+
@name = name.downcase
|
23
|
+
@xtras = xtras
|
24
|
+
|
25
|
+
if type == "controller"
|
26
|
+
template("sample_controller.tt", File.join(target_root, "controllers", "#{name}_controller.rb"))
|
27
|
+
generate("view", name)
|
28
|
+
elsif type == "model"
|
29
|
+
template("sample_model.tt", File.join(target_root, "models", "#{name}.rb"))
|
30
|
+
elsif type == "view"
|
31
|
+
directory("folder", File.join(target_root, "views", "name"))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "g TYPE NAME OPTIONS", "alias for microframe generate"
|
36
|
+
def g(type, name, *xtras)
|
37
|
+
invoke :generate, [type, name, *xtras]
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def target_root
|
43
|
+
"app/"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Microframe
|
2
|
+
class ApplicationController
|
3
|
+
attr_reader :request, :params, :view_rendered, :errors, :child, :action
|
4
|
+
|
5
|
+
def initialize(request, child, action)
|
6
|
+
@request = request
|
7
|
+
@child = child
|
8
|
+
@action = action
|
9
|
+
@params = request.params
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_render_option
|
13
|
+
{ view: action, layout: "application" }
|
14
|
+
end
|
15
|
+
|
16
|
+
def render(options = {})
|
17
|
+
@view_rendered = true
|
18
|
+
view = get_view(options[:view])
|
19
|
+
layout = get_layout(options[:layout])
|
20
|
+
|
21
|
+
if(render_error?(view, layout))
|
22
|
+
response = Tilt.new(File.join(".", "public", "404.html.erb"))
|
23
|
+
response = response.render(Object.new, errors: @errors)
|
24
|
+
else
|
25
|
+
template = Tilt::ERBTemplate.new(layout)
|
26
|
+
view = Tilt::ERBTemplate.new(view)
|
27
|
+
vars = set_instance_variables_for_views
|
28
|
+
response = template.render(self, vars){ view.render(self, vars)}
|
29
|
+
end
|
30
|
+
|
31
|
+
[200, {}, [response]]
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_view
|
35
|
+
render default_render_option
|
36
|
+
end
|
37
|
+
|
38
|
+
def render_error?(view, layout)
|
39
|
+
@errors = []
|
40
|
+
@errors << "Couldn't find view: #{view}" unless File.file?view
|
41
|
+
@errors << "Couldn't find layout: #{layout}" unless File.file?layout
|
42
|
+
@errors.size > 0
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_view(view)
|
46
|
+
view ||= default_render_option[:view]
|
47
|
+
file = File.join(".", "app", "views", child, "#{view}.html.erb")
|
48
|
+
unless File.file? file
|
49
|
+
file = File.join(".", "app", "views", "#{view}.html.erb")
|
50
|
+
end
|
51
|
+
file
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_layout(layout)
|
55
|
+
layout ||= default_render_option[:layout]
|
56
|
+
File.join(".", "app", "views", "layouts", layout + ".html.erb")
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_instance_variables_for_views
|
60
|
+
hash = {}
|
61
|
+
vars = instance_variables
|
62
|
+
vars -= protected_instance_variables_for_views
|
63
|
+
vars.each { |var| hash[var[1..-1]] = instance_variable_get(var)}
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def protected_instance_variables_for_views
|
68
|
+
[@request]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(__dir__,"class_queries")
|
2
|
+
Dir[File.join(".", "app", "models", "*.rb")].each { |file| require file}
|
3
|
+
|
4
|
+
module Microframe
|
5
|
+
module ORM
|
6
|
+
class Base
|
7
|
+
|
8
|
+
def update_queryset(key, value)
|
9
|
+
@queryset ||= Hash.new(Array.new)
|
10
|
+
@queryset[key] = @queryset[key] << value
|
11
|
+
end
|
12
|
+
|
13
|
+
def table_name
|
14
|
+
self.class.table_name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.join(__dir__,"query_utils")
|
2
|
+
require File.join(__dir__,"instance_queries")
|
3
|
+
require File.join(__dir__,"relationships")
|
4
|
+
|
5
|
+
module Microframe
|
6
|
+
module ORM
|
7
|
+
class Base
|
8
|
+
@@queryset = {}
|
9
|
+
class << self
|
10
|
+
include QueryUtils
|
11
|
+
include Relationships
|
12
|
+
|
13
|
+
def inherited(base)
|
14
|
+
base.include InstanceQueries
|
15
|
+
base.include QueryUtils
|
16
|
+
end
|
17
|
+
|
18
|
+
def property(col_name, options = {})
|
19
|
+
@@create_table_query ||= []
|
20
|
+
options[:type] = options[:type].to_s.upcase
|
21
|
+
options[:nullable] = options[:nullable] ? "NULL" : "NOT NULL"
|
22
|
+
options[:primary_key] = options[:primary_key] ? "PRIMARY KEY AUTOINCREMENT" : ""
|
23
|
+
@@create_table_query << col_name.to_s + " " + options.values.join(" ")
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_table
|
27
|
+
query = "CREATE TABLE IF NOT EXISTS #{table_name} (#{@@create_table_query.join(", ")})"
|
28
|
+
if Connection.execute(query)
|
29
|
+
@@create_table_query = nil
|
30
|
+
define_attributes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_attributes
|
35
|
+
Connection.retrieve_columns(table_name).each do |column|
|
36
|
+
define_method("#{column}=") do |val|
|
37
|
+
instance_var = "@#{column}"
|
38
|
+
instance_variable_set("@save_queryset", {}) unless @save_queryset
|
39
|
+
@save_queryset[column] = val unless column == "id"
|
40
|
+
instance_variable_set(instance_var, val)
|
41
|
+
end
|
42
|
+
|
43
|
+
define_method(column) do
|
44
|
+
instance_var = "@#{column}"
|
45
|
+
instance_variable_get(instance_var)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create(options={})
|
51
|
+
keys = options.keys.join(", ")
|
52
|
+
values = options.values
|
53
|
+
placeholders = Array.new(values.size, "?").join(", ")
|
54
|
+
Connection.connect.execute("INSERT INTO #{table_name} (#{keys}) VALUES (#{placeholders})", values)
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def table_name
|
59
|
+
self.to_s.downcase + "s"
|
60
|
+
end
|
61
|
+
|
62
|
+
def all
|
63
|
+
add_query("SELECT", "*") unless @@queryset && @@queryset["SELECT"]
|
64
|
+
fetch_result
|
65
|
+
end
|
66
|
+
|
67
|
+
def find(id)
|
68
|
+
find_by(id: id)
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_by(options = {})
|
72
|
+
where(options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def where(options = {})
|
76
|
+
sql = ""
|
77
|
+
options.each {|key, val| sql << "#{key.to_s} = '#{val}'"}
|
78
|
+
add_query("WHERE", sql)
|
79
|
+
end
|
80
|
+
|
81
|
+
def select(val)
|
82
|
+
add_query("SELECT", val)
|
83
|
+
end
|
84
|
+
|
85
|
+
def count
|
86
|
+
result = all
|
87
|
+
result.size
|
88
|
+
end
|
89
|
+
|
90
|
+
def first
|
91
|
+
limit(1)
|
92
|
+
fetch_result
|
93
|
+
end
|
94
|
+
|
95
|
+
def last
|
96
|
+
limit(1).order("id DESC")
|
97
|
+
fetch_result
|
98
|
+
end
|
99
|
+
|
100
|
+
def limit(val)
|
101
|
+
@@queryset["LIMIT"] = val
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
def order(val)
|
106
|
+
@@queryset["ORDER BY"] = val
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
def destroy(id)
|
111
|
+
destroy_all("WHERE id = #{id}")
|
112
|
+
end
|
113
|
+
|
114
|
+
def destroy_all(xtra = "; VACUUM")
|
115
|
+
query = "DELETE FROM #{table_name} #{xtra}"
|
116
|
+
execute(query)
|
117
|
+
self
|
118
|
+
end
|
119
|
+
|
120
|
+
def update_queryset(key, value)
|
121
|
+
@@queryset ||= {}
|
122
|
+
@@queryset[key] = @@queryset[key] ? @@queryset[key] << value : [value]
|
123
|
+
end
|
124
|
+
|
125
|
+
def fetch_result
|
126
|
+
result = process_query(@@queryset)
|
127
|
+
@@queryset = {}
|
128
|
+
parse_result_to_objects(result)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Microframe
|
2
|
+
module ORM
|
3
|
+
class Connection
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def connect
|
7
|
+
@@db ||= SQLite3::Database.open(File.join("db", @@dbname + ".sqlite"))
|
8
|
+
@@db.results_as_hash = true
|
9
|
+
connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def retrieve_columns(table)
|
13
|
+
@@db.execute2("SELECT * FROM #{table} WHERE id = 0")[0]
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_dbname(name)
|
17
|
+
@@dbname = name
|
18
|
+
end
|
19
|
+
|
20
|
+
def connection
|
21
|
+
@@db ||= connect
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute(query)
|
25
|
+
connection.execute(query)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Microframe
|
2
|
+
module ORM
|
3
|
+
module InstanceQueries
|
4
|
+
def save
|
5
|
+
@save_queryset["id"] = id
|
6
|
+
keys = @save_queryset.keys.join(", ")
|
7
|
+
values = @save_queryset.values
|
8
|
+
@save_queryset = nil
|
9
|
+
placeholders = Array.new(values.size, "?").join(", ")
|
10
|
+
result = Microframe::ORM::Connection.connect.execute("REPLACE INTO #{table_name} (#{keys}) VALUES (#{placeholders})", values)
|
11
|
+
result ? self.class.last : self
|
12
|
+
end
|
13
|
+
|
14
|
+
def update(options = {})
|
15
|
+
@save_queryset ||= {}
|
16
|
+
@save_queryset.merge(options)
|
17
|
+
save
|
18
|
+
end
|
19
|
+
# def order
|
20
|
+
# end
|
21
|
+
|
22
|
+
# def limit
|
23
|
+
# end
|
24
|
+
|
25
|
+
# def offset
|
26
|
+
# end
|
27
|
+
|
28
|
+
# def update
|
29
|
+
# end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
query = "DELETE FROM #{table_name} WHERE id =#{id}"
|
33
|
+
execute(query)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
# def group
|
38
|
+
# end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Microframe
|
2
|
+
module ORM
|
3
|
+
module QueryUtils
|
4
|
+
def add_query(key, value)
|
5
|
+
update_queryset(key, value)
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def process_query(queryset)
|
10
|
+
return unless queryset
|
11
|
+
query = build_query(queryset)
|
12
|
+
execute(query)
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute(query)
|
16
|
+
Microframe::ORM::Connection.execute(query)
|
17
|
+
end
|
18
|
+
|
19
|
+
def process_select(queryhash)
|
20
|
+
queryhash["SELECT"] ||= ["*"]
|
21
|
+
"SELECT #{queryhash["SELECT"].join(", ")}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_from(queryhash)
|
25
|
+
queryhash["FROM"] ||= self.to_s.downcase
|
26
|
+
"FROM #{queryhash["FROM"]}s"
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_where(queryhash)
|
30
|
+
return "" unless queryhash["WHERE"]
|
31
|
+
"WHERE #{queryhash["WHERE"].join(" AND ")}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_generic(name, queryhash)
|
35
|
+
return "" unless queryhash[name]
|
36
|
+
"#{name} #{queryhash[name]}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_order(queryhash)
|
40
|
+
process_generic("ORDER BY", queryhash)
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_limit(queryhash)
|
44
|
+
process_generic("LIMIT", queryhash)
|
45
|
+
end
|
46
|
+
|
47
|
+
def query_processes
|
48
|
+
[:process_select, :process_from, :process_where, :process_order, :process_limit]
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_query(queryhash)
|
52
|
+
query = []
|
53
|
+
query_processes.each { |process| query << send(process, queryhash)}
|
54
|
+
query.join(" ").strip
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_result_to_objects(result)
|
58
|
+
hash_objects = []
|
59
|
+
result.each do |hash|
|
60
|
+
obj = self.new
|
61
|
+
hash.each do |key, val|
|
62
|
+
if key.is_a? String
|
63
|
+
obj.instance_variable_set("@#{key}", val)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
hash_objects << obj
|
67
|
+
end
|
68
|
+
result.size == 1 ? hash_objects.first : hash_objects
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Microframe
|
2
|
+
module ORM
|
3
|
+
module Relationships
|
4
|
+
|
5
|
+
def has_many(model, options = {})
|
6
|
+
model = model.to_s
|
7
|
+
define_method(model) do
|
8
|
+
model_class = model[0..-2]
|
9
|
+
options[:foreign_key] ||= self.class.to_s.downcase + "_id"
|
10
|
+
Module.const_get(model_class.capitalize).where(options[:foreign_key] => id )
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def belongs_to(model, options = {})
|
15
|
+
model = model.to_s
|
16
|
+
define_method(model) do
|
17
|
+
options[:foreign_key] ||= "id"
|
18
|
+
model_id = send((model + "_id").to_sym)
|
19
|
+
Module.const_get(model.capitalize).where(options[:foreign_key] => model_id )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# def validates
|
24
|
+
# "With love from validates to"
|
25
|
+
# end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Microframe
|
2
|
+
class Mapper
|
3
|
+
attr_reader :routes, :placeholders
|
4
|
+
def initialize(routes)
|
5
|
+
@routes = routes
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.start(route)
|
9
|
+
new(route)
|
10
|
+
end
|
11
|
+
|
12
|
+
def map(verb, path)
|
13
|
+
value = nil
|
14
|
+
routes[verb].each do |route, target|
|
15
|
+
if match_this(route, path)
|
16
|
+
value = target
|
17
|
+
break
|
18
|
+
end
|
19
|
+
end
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
def match_components(a, b)
|
24
|
+
found = false
|
25
|
+
if a == b
|
26
|
+
found = true
|
27
|
+
elsif a[0] == ":" && a[-1] != ")" && a[-1] != "("
|
28
|
+
@placeholders[a[1..-1].to_sym] = b
|
29
|
+
found = true
|
30
|
+
end
|
31
|
+
return found
|
32
|
+
end
|
33
|
+
|
34
|
+
def match_begin_of_optional_components(a, optional)
|
35
|
+
if a[-1] == "("
|
36
|
+
optional += 1
|
37
|
+
a.sub!("(", "")
|
38
|
+
changed = true
|
39
|
+
end
|
40
|
+
return a, optional, changed
|
41
|
+
end
|
42
|
+
|
43
|
+
def match_end_of_optional_components(a, optional)
|
44
|
+
if a[-1] == ")"
|
45
|
+
optional -= 1
|
46
|
+
a.sub!(")", "")
|
47
|
+
changed = true
|
48
|
+
end
|
49
|
+
return a, optional, changed
|
50
|
+
end
|
51
|
+
|
52
|
+
def match_optional_components(match, optional, index)
|
53
|
+
if optional > 0
|
54
|
+
match = true
|
55
|
+
index -= 1
|
56
|
+
end
|
57
|
+
return match, index, match
|
58
|
+
end
|
59
|
+
|
60
|
+
def match_this(routes, path)
|
61
|
+
match = []; @placeholders = {}; index = 0;
|
62
|
+
route = routes.split("/")
|
63
|
+
paths = path.split("/")
|
64
|
+
|
65
|
+
return false if route.size < paths.size
|
66
|
+
|
67
|
+
route.each do |a|
|
68
|
+
pending_match = true; matched = false; optional = 0;
|
69
|
+
b = paths[index]
|
70
|
+
|
71
|
+
while pending_match
|
72
|
+
matched = match_components(a, b)
|
73
|
+
pending_match = false
|
74
|
+
a, optional, pending_match = match_begin_of_optional_components(a, optional) unless matched || pending_match
|
75
|
+
a, optional, pending_match = match_end_of_optional_components(a, optional) unless matched || pending_match
|
76
|
+
matched, index, pending_match = match_optional_components(matched, optional, index) unless matched || pending_match
|
77
|
+
end
|
78
|
+
|
79
|
+
match << matched
|
80
|
+
index += 1
|
81
|
+
end
|
82
|
+
!match.include? false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(__dir__, "../","controller", "application_controller")
|
2
|
+
require File.join(__dir__, "mapper")
|
3
|
+
|
4
|
+
module Microframe
|
5
|
+
class Router
|
6
|
+
attr_reader :route, :mapper, :object
|
7
|
+
attr_accessor :request
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@route = Hash.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle_request(verb, path)
|
14
|
+
@mapper ||= Mapper.start(route)
|
15
|
+
handler = @mapper.map(verb, path) #get_handler(verb, path)
|
16
|
+
return missing_path unless handler
|
17
|
+
|
18
|
+
@request.params.merge!(@mapper.placeholders)
|
19
|
+
|
20
|
+
response = setup_controller(handler)
|
21
|
+
unless object.view_rendered
|
22
|
+
response = object.render_view
|
23
|
+
end
|
24
|
+
response
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_controller(handler)
|
28
|
+
controller = handler[:controller]
|
29
|
+
action = handler[:action]
|
30
|
+
get_handler_file(controller)
|
31
|
+
|
32
|
+
@object = Module.const_get(controller.capitalize + "Controller").new(request, controller, action)
|
33
|
+
object.send(action.to_sym)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def self.setup_verbs(*verbs)
|
38
|
+
verbs.each do |verb|
|
39
|
+
verb = verb.to_s
|
40
|
+
define_method(verb) { |path, handler| set_route(verb.upcase, path, handler) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
setup_verbs :get, :post, :patch, :put, :delete
|
45
|
+
|
46
|
+
def draw(&block)
|
47
|
+
instance_eval(&block)
|
48
|
+
@route.default = {}
|
49
|
+
end
|
50
|
+
|
51
|
+
def resources(name)
|
52
|
+
name = name.to_s
|
53
|
+
get("/#{name}", to: "#{name}#index")
|
54
|
+
get("/#{name}/new", to: "#{name}#new")
|
55
|
+
get("/#{name}/:id", to: "#{name}#show")
|
56
|
+
get("/#{name}/:id/edit", to: "#{name}#edit")
|
57
|
+
post("/#{name}", to: "#{name}#create")
|
58
|
+
patch("/#{name}/:id", to: "#{name}#update")
|
59
|
+
delete("/name/:id", to: "#{name}#destroy")
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def get_handler(verb, path)
|
65
|
+
route[verb][path]
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_route(verb, path, handler = {})
|
69
|
+
@route[verb] ||= {}
|
70
|
+
@route[verb][path] = setup_handler(handler)
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup_handler(handler)
|
74
|
+
controller, action = handler[:to].split("#")
|
75
|
+
{controller: controller, action: action}
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_handler_file(controller)
|
79
|
+
require File.join(".", "app", "controllers", controller + "_controller")
|
80
|
+
end
|
81
|
+
|
82
|
+
def missing_path
|
83
|
+
[404, {"Content-Type" => "application/html"}, ["<p>We are here but unfortunately, this page: #{request.host}#{request.path_info} isn't. Return home while we keep looking for it.</p>"]]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/microframe/version.rb
CHANGED
data/microframe.gemspec
CHANGED
@@ -22,11 +22,13 @@ Gem::Specification.new do |spec|
|
|
22
22
|
end
|
23
23
|
|
24
24
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
-
spec.bindir = "
|
26
|
-
spec.executables =
|
25
|
+
spec.bindir = "bin"
|
26
|
+
spec.executables = %w{microframe}
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
|
29
29
|
spec.add_runtime_dependency "bundler", "~> 1.10"
|
30
|
-
spec.
|
31
|
-
spec.add_development_dependency "
|
30
|
+
spec.add_runtime_dependency "thor", "~> 0.19.1"
|
31
|
+
spec.add_development_dependency "pry-nav", "~> 0.2.4"
|
32
|
+
spec.add_development_dependency "rake", '~> 10.4', '>= 10.4.2'
|
33
|
+
spec.add_development_dependency "minitest", '~> 5.8', '>= 5.8.3'
|
32
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: microframe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Osmond
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,38 +24,79 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.19.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.19.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-nav
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.2.4
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.4
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: rake
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
30
58
|
requirements:
|
31
59
|
- - "~>"
|
32
60
|
- !ruby/object:Gem::Version
|
33
|
-
version: '10.
|
61
|
+
version: '10.4'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 10.4.2
|
34
65
|
type: :development
|
35
66
|
prerelease: false
|
36
67
|
version_requirements: !ruby/object:Gem::Requirement
|
37
68
|
requirements:
|
38
69
|
- - "~>"
|
39
70
|
- !ruby/object:Gem::Version
|
40
|
-
version: '10.
|
71
|
+
version: '10.4'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 10.4.2
|
41
75
|
- !ruby/object:Gem::Dependency
|
42
76
|
name: minitest
|
43
77
|
requirement: !ruby/object:Gem::Requirement
|
44
78
|
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '5.8'
|
45
82
|
- - ">="
|
46
83
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
84
|
+
version: 5.8.3
|
48
85
|
type: :development
|
49
86
|
prerelease: false
|
50
87
|
version_requirements: !ruby/object:Gem::Requirement
|
51
88
|
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '5.8'
|
52
92
|
- - ">="
|
53
93
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
94
|
+
version: 5.8.3
|
55
95
|
description:
|
56
96
|
email:
|
57
97
|
- osmond.oranagwa@andela.com
|
58
|
-
executables:
|
98
|
+
executables:
|
99
|
+
- microframe
|
59
100
|
extensions: []
|
60
101
|
extra_rdoc_files: []
|
61
102
|
files:
|
@@ -67,8 +108,33 @@ files:
|
|
67
108
|
- README.md
|
68
109
|
- Rakefile
|
69
110
|
- bin/console
|
111
|
+
- bin/microframe
|
70
112
|
- bin/setup
|
71
113
|
- lib/microframe.rb
|
114
|
+
- lib/microframe/application/application.rb
|
115
|
+
- lib/microframe/application/generators/generator.rb
|
116
|
+
- lib/microframe/application/generators/samples/app_sample/Gemfile
|
117
|
+
- lib/microframe/application/generators/samples/app_sample/app/assets/images/.keep
|
118
|
+
- lib/microframe/application/generators/samples/app_sample/app/assets/javascripts/.keep
|
119
|
+
- lib/microframe/application/generators/samples/app_sample/app/assets/stylesheets/.keep
|
120
|
+
- lib/microframe/application/generators/samples/app_sample/app/controllers/.keep
|
121
|
+
- lib/microframe/application/generators/samples/app_sample/app/models/.keep
|
122
|
+
- lib/microframe/application/generators/samples/app_sample/app/views/layouts/application.html.erb.tt
|
123
|
+
- lib/microframe/application/generators/samples/app_sample/config.ru.tt
|
124
|
+
- lib/microframe/application/generators/samples/app_sample/config/routes.rb.tt
|
125
|
+
- lib/microframe/application/generators/samples/app_sample/db/config.rb.tt
|
126
|
+
- lib/microframe/application/generators/samples/app_sample/public/404.html.erb.tt
|
127
|
+
- lib/microframe/application/generators/samples/sample_controller.tt
|
128
|
+
- lib/microframe/application/generators/samples/sample_model.tt
|
129
|
+
- lib/microframe/controller/application_controller.rb
|
130
|
+
- lib/microframe/orm/base.rb
|
131
|
+
- lib/microframe/orm/class_queries.rb
|
132
|
+
- lib/microframe/orm/connection.rb
|
133
|
+
- lib/microframe/orm/instance_queries.rb
|
134
|
+
- lib/microframe/orm/query_utils.rb
|
135
|
+
- lib/microframe/orm/relationships.rb
|
136
|
+
- lib/microframe/routing/mapper.rb
|
137
|
+
- lib/microframe/routing/router.rb
|
72
138
|
- lib/microframe/version.rb
|
73
139
|
- microframe.gemspec
|
74
140
|
homepage: https://github.com/andela-ooranagwa/microframe
|
@@ -97,3 +163,4 @@ signing_key:
|
|
97
163
|
specification_version: 4
|
98
164
|
summary: A Microframe for building web apps
|
99
165
|
test_files: []
|
166
|
+
has_rdoc:
|