matrack 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ require_relative "resources"
2
+
3
+ module Matrack
4
+ class Application
5
+ attr_reader :router
6
+
7
+ def initialize
8
+ @router = Router.new
9
+ end
10
+
11
+ def call(env)
12
+ route = router.route_for(env)
13
+ if route
14
+ route.execute(env)
15
+ response_handler(route)
16
+ else
17
+ controller = BaseController.new(env)
18
+ body = controller.invalid_route
19
+ [404, {}, [body]]
20
+ end
21
+ end
22
+
23
+ def response_handler(route)
24
+ controller = route.mat_controller
25
+ if controller.response
26
+ controller.response
27
+ else
28
+ controller.render(route.action)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,63 @@
1
+ module Matrack
2
+ class BaseController
3
+ include Matrack::HelperTags
4
+ attr_reader :request, :response
5
+ attr_accessor :session
6
+
7
+ def initialize(env)
8
+ @request = Rack::Request.new(env)
9
+ @session = Session.new(env)
10
+ end
11
+
12
+ def params
13
+ request.params
14
+ end
15
+
16
+ def create_response(body, status = 200, headers = {})
17
+ @response = Rack::Response.new body, status, headers
18
+ end
19
+
20
+ def render(*args)
21
+ create_response(render_template(*args))
22
+ end
23
+
24
+ def render_template(view_name, locals = {})
25
+ template = Tilt::ERBTemplate.new(File.join(APP_PATH, "app", "views",
26
+ "layout", "application.html.erb"))
27
+ title = view_name.to_s.tr("_", " ").capitalize
28
+ view = "#{view_name}.html.erb"
29
+ view_template = Tilt::ERBTemplate.new(File.join(APP_PATH, "app", "views",
30
+ controller_name, view))
31
+ template.render(self, title: title) do
32
+ view_template.render(self, locals.merge!(get_instance_vars))
33
+ end
34
+ end
35
+
36
+ def invalid_route
37
+ template = Tilt::ERBTemplate.new(File.join(APP_PATH, "app", "views",
38
+ "layout", "invalid.html.erb"))
39
+ template.render(self)
40
+ end
41
+
42
+ def get_instance_vars
43
+ vars = {}
44
+ instance_variables.each do |var|
45
+ key = var.to_s.delete("@").to_sym
46
+ vars[key] = instance_variable_get(var)
47
+ end
48
+ vars
49
+ end
50
+
51
+ def controller_name
52
+ self.class.to_s.gsub(/Controller$/, "").to_snake_case
53
+ end
54
+
55
+ def authenticate(password)
56
+ Matrack::DataManager.password_hash(password)
57
+ end
58
+
59
+ def redirect_to(address)
60
+ create_response([], 302, "location" => address)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ class ::Object
2
+ def self.const_missing(const)
3
+ require const.to_s.to_snake_case
4
+ const_get(const)
5
+ end
6
+ end
@@ -0,0 +1,59 @@
1
+ module Matrack
2
+ module HelperTags
3
+
4
+ def email_validator
5
+ '[A-Za-z0-9_\-\.]+\@[A-Za-z0-9_\-\.]+\.[A-Za-z]{2,4}'
6
+ end
7
+
8
+ def textbox_tag(name, value = "", class_name = "", holder = "", req = nil,
9
+ disabled = nil)
10
+ tag = "<input type='text' name='#{name}' value='#{value}' "
11
+ tag += "placeholder='#{holder}' class='#{class_name}'"
12
+ tag += "required='#{req}'" unless req.nil?
13
+ tag += disabled.nil? ? ">" : " disabled='#{disabled}'>"
14
+ end
15
+
16
+ def password_tag(name, class_name = "", holder = "", req = nil,
17
+ disabled = nil)
18
+ tag = "<input type='password' name='#{name}' "
19
+ tag += "placeholder='#{holder}' class='#{class_name}'"
20
+ tag += "required='#{req}'" unless req.nil?
21
+ tag += disabled.nil? ? ">" : " disabled='#{disabled}'>"
22
+ end
23
+
24
+ def emailbox_tag(name, value = "", class_name = "", holder = "", req = nil,
25
+ disabled = nil, pattern = nil)
26
+ tag = "<input type='email' name='#{name}' value='#{value}' "
27
+ tag += "placeholder='#{holder}' class='#{class_name}'"
28
+ tag += "required='#{req}'" unless req.nil?
29
+ regex_pattern = pattern.nil? ? "#{email_validator}" : "#{pattern}"
30
+ tag += " pattern='#{regex_pattern}'"
31
+ tag += disabled.nil? ? ">" : " disabled='#{disabled}'>"
32
+ end
33
+
34
+ def submit_tag(name, value = "Submit", class_name = "")
35
+ tag = "<input type='submit' name='#{name}' value='#{value}' "
36
+ tag += "class='#{class_name}'>"
37
+ end
38
+
39
+ def link_tag(ref, class_name = "", title = "Link")
40
+ "<a href='#{ref}' class='#{class_name}'>#{title}</a>"
41
+ end
42
+
43
+ def image_tag(name, alt = "image")
44
+ "<img src='../../images/#{name}' alt= '#{alt}'>"
45
+ end
46
+
47
+ def include_stylesheet(name)
48
+ "<link href='../../css/#{name}.css' rel='stylesheet' type= 'text/css'>"
49
+ end
50
+
51
+ def include_javascript(name)
52
+ "<script src='../../js/#{name}.js' type='text/javascript'></script>"
53
+ end
54
+
55
+ def display_favicon
56
+ "<link rel='icon' type='image/png' href='../../images/favicon.png' />"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ class Route
2
+ attr_reader :matclass, :action, :mat_controller
3
+
4
+ def initialize(route_info)
5
+ matklass = route_info.last[:matclass].to_camel_case
6
+ @matclass = Object.const_get(matklass+"Controller")
7
+ @path = route_info.first
8
+ @action = route_info.last[:method].to_sym
9
+ end
10
+
11
+ def execute(env)
12
+ @mat_controller = matclass.new(env)
13
+ @mat_controller.send(action)
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ class Router
2
+ attr_reader :routes
3
+
4
+ def initialize
5
+ @routes = Hash.new { |hash, key| hash[key] = [] }
6
+ end
7
+
8
+ def draw(&block)
9
+ instance_eval(&block)
10
+ end
11
+
12
+ def root(root_path)
13
+ get "/", root_path
14
+ end
15
+
16
+ %w(get post put delete).each do |request_type|
17
+ define_method(request_type) do | path, options|
18
+ request_type = request_type.to_sym
19
+ if options.is_a? Hash
20
+ @routes[request_type] << [path, case_parser(options[:to])]
21
+ else
22
+ @routes[request_type] << [path, case_parser(options)]
23
+ end
24
+ end
25
+ end
26
+
27
+ def route_for(env)
28
+ path = env["PATH_INFO"]
29
+ verb = env["REQUEST_METHOD"].downcase.to_sym
30
+ route_info = routes[verb].detect do |route|
31
+ route.first == path || route.first == path.sub("/", "")
32
+ end
33
+ Route.new(route_info) if route_info
34
+ end
35
+
36
+ private
37
+
38
+ def case_parser(str)
39
+ matclass, method = str.split("#")
40
+ { matclass: matclass.to_camel_case, method: method.to_snake_case }
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ module Matrack
2
+ class Session
3
+ attr_accessor :request
4
+
5
+ def initialize(env)
6
+ @request = Rack::Request.new(env)
7
+ end
8
+
9
+ def [](key)
10
+ request.session[key.to_sym]
11
+ end
12
+
13
+ def []=(key, value)
14
+ request.session[key.to_sym] = value
15
+ end
16
+
17
+ def clear
18
+ request.session.clear
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ class ::String
2
+ def to_snake_case
3
+ gsub("::", "/").
4
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-", "_").downcase
6
+ end
7
+
8
+ def to_camel_case
9
+ return self if self !~ /_/ && self =~ /[A-Z]+.*/
10
+ split("_").map(&:capitalize).join
11
+ end
12
+
13
+ def to_b
14
+ return true if !self.nil? && (self == true || downcase == "true")
15
+ return false if self.nil? || downcase == "false" || self == false
16
+ false
17
+ end
18
+
19
+ def titleize
20
+ split.map!(&:capitalize).join(" ")
21
+ end
22
+
23
+ def pluralize
24
+ self + "s" unless self.end_with? "s"
25
+ end
26
+
27
+ end
28
+
29
+ class ::Array
30
+ def hash_getter
31
+ first.select{|k| k.is_a? String}
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Matrack
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,57 @@
1
+ module Matrack
2
+ class BaseModel < Queries
3
+ def initialize(hash = {})
4
+ hash.each_pair { |k,v| send("#{k}=", v) }
5
+ self
6
+ end
7
+
8
+ @@query_string = ""
9
+
10
+ class << self
11
+
12
+ def create_table
13
+ query_string = @@query_string.sub(/,[\s]$/,"")
14
+ create_table_fields(table_name,query_string)
15
+ @@query_string = ""
16
+ end
17
+
18
+ def property(name, type = "str", desc = {} )
19
+ field_hash = { name => type }
20
+ if verify_col_type(field_hash) == true
21
+ db_str = DataUtility.type_mapper(field_hash)
22
+ @@query_string += query_builder(db_str.keys, db_str.values, desc)
23
+ @@query_string += ", " unless @@query_string == ""
24
+ get_and_set_property(name)
25
+ else
26
+ puts db_error(verify_col_type(field_hash))
27
+ exit
28
+ end
29
+ end
30
+
31
+ def get_and_set_property(name)
32
+ define_method(name) do
33
+ instance_variable_get("@#{name}")
34
+ end
35
+ define_method("#{name}=") do |value|
36
+ instance_variable_set("@#{name}", "#{value}")
37
+ end
38
+ end
39
+
40
+ def create(field_hash)
41
+ passwordify(field_hash)
42
+ attributes = "#{field_hash.keys}".gsub(/:/, "").gsub(/\[|\]/,"")
43
+ values = "#{field_hash.values}".gsub(/\[|\]/,"").gsub(/\"/,"'")
44
+ db_conn.execute "INSERT INTO #{table_name} (#{attributes}) VALUES (#{
45
+ values});"
46
+ end
47
+
48
+ def passwordify(field_hash)
49
+ if field_hash.keys.include? :password
50
+ hashed_pass = password_hash(field_hash[:password])
51
+ field_hash[:password] = hashed_pass
52
+ end
53
+ field_hash
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ require "sqlite3"
2
+ require "digest/sha1"
3
+
4
+ module Matrack
5
+ class DataManager
6
+
7
+ class << self
8
+ def db_conn
9
+ db = SQLite3::Database.new "#{APP_PATH}/db/app.sqlite3"
10
+ db.results_as_hash = true
11
+ db
12
+ end
13
+
14
+ def db_error(message)
15
+ DataUtility.db_error(message)
16
+ end
17
+
18
+ def query_builder(name, type, desc)
19
+ name = name.join
20
+ type = type.join
21
+ primary_key = "PRIMARY KEY" if desc[:primary_key] == true
22
+ primary_key += " AUTOINCREMENT" if desc[:primary_key] == true &&
23
+ type == "INTEGER"
24
+ primary_key = primary_key ? primary_key : ""
25
+ null_value = desc[:nullable].nil? ? "NULL" : "NOT NULL"
26
+ null_value = "NOT NULL" if desc[:primary_key] == true
27
+ "#{name} #{type} #{primary_key} #{null_value}"
28
+ end
29
+
30
+ def allowed_field_types
31
+ ["int", "str", "time", "date"]
32
+ end
33
+
34
+ def create_table_fields(table_name, qry_str)
35
+ begin
36
+ db_conn.execute "CREATE TABLE IF NOT EXISTS #{table_name} (#{qry_str});"
37
+ rescue
38
+ puts db_error("Can not create table")
39
+ exit
40
+ end
41
+ end
42
+
43
+ def verify_col_type(field_hash)
44
+ return true if valid_col_types?(field_hash)
45
+ "Invalid column type(s) specified"
46
+ end
47
+
48
+ def valid_col_types?(field_hash)
49
+ field_hash.values.all? { |val| allowed_field_types.include? val.to_s }
50
+ end
51
+
52
+ def password_hash(password)
53
+ Digest::SHA1.hexdigest(password)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ class DataUtility
2
+ class << self
3
+ def type_mapper(field_hash)
4
+ db_data = {}
5
+ field_hash.each_pair do |k, v|
6
+ v = v.to_s
7
+ if v == "str" || v == "time" || v == "date"
8
+ db_data[k] = "VARCHAR"
9
+ elsif v == "int"
10
+ db_data[k] = "INTEGER"
11
+ end
12
+ end
13
+ db_data
14
+ end
15
+
16
+ def create_table_query(db_data)
17
+ db_str = ""
18
+ db_data.each_pair do |k,v|
19
+ db_str +=" " + "#{k}" + " " + "#{v}"
20
+ db_str += "," unless k == db_data.keys.last
21
+ end
22
+ db_str
23
+ end
24
+
25
+ def db_error(message)
26
+ <<-EOS
27
+ *************************************************
28
+ DB ERROR - #{message.to_s.titleize}
29
+ *************************************************
30
+ EOS
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ module Matrack
2
+ class FetchQueries < DataManager
3
+ class << self
4
+ def table_name
5
+ self.to_s.to_snake_case + "s"
6
+ end
7
+
8
+ def uniq_id
9
+ "#{self.to_s.to_snake_case}_id"
10
+ end
11
+
12
+ def execute(query)
13
+ objs = []
14
+ rows = db_conn.execute query
15
+ rows.each{|row| objs << self.new(row.reject!{ |k| !k.is_a? String }) }
16
+ objs
17
+ end
18
+
19
+ def all
20
+ execute "SELECT * FROM #{table_name}"
21
+ end
22
+
23
+ def find(id)
24
+ execute("SELECT * FROM #{table_name} WHERE (#{uniq_id} = #{id})").first
25
+ end
26
+
27
+ def last
28
+ offset = count - 1
29
+ execute("SELECT * FROM #{table_name} LIMIT(1) OFFSET(#{offset})").first
30
+ end
31
+
32
+ def limit(num)
33
+ execute "SELECT * FROM #{table_name} LIMIT(#{num})"
34
+ end
35
+
36
+ def first
37
+ execute("SELECT * FROM #{table_name} LIMIT(1)").first
38
+ end
39
+
40
+ def find_by(col, val)
41
+ execute("SELECT * FROM #{table_name} WHERE (#{col} = '#{val}')
42
+ LIMIT 1").first
43
+ end
44
+
45
+ # firstname: "name", lastname: "last"
46
+ def find_cols(col_hash)
47
+ clause = col_hash.map{|k,v| "#{k.to_s} = " "'#{v}'"}.join(" AND ")
48
+ execute("SELECT * FROM #{table_name} WHERE (#{clause})
49
+ LIMIT 1").first
50
+ end
51
+ end
52
+ end
53
+ end