microframe 0.1.0 → 0.1.1
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 +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:
|