From 2b5b900319e2fd31b23ca1199d4f213f7c7b48ba Mon Sep 17 00:00:00 2001 From: Yarex Marvin Date: Fri, 25 Nov 2022 10:56:54 +0400 Subject: [PATCH] simpler --- .gitignore | 1 + app/controllers/tests_controller.rb | 8 ++++-- app/views/tests/index.html.erb | 10 +++++-- app/views/tests/show.html.erb | 16 +++++++++++ config.ru | 3 +++ config/routes.rb | 2 ++ lib/simpler/application.rb | 32 ++++++++++++++-------- lib/simpler/controller.rb | 41 ++++++++++++++++++++++++----- lib/simpler/router.rb | 39 ++++++++++++++++++++++----- lib/simpler/router/route.rb | 2 +- lib/simpler/view.rb | 33 ++++++++++++++++------- middleware/logger.rb | 19 +++++++++++++ 12 files changed, 167 insertions(+), 39 deletions(-) create mode 100644 .gitignore create mode 100644 app/views/tests/show.html.erb create mode 100644 middleware/logger.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..87afabbb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +log/* \ No newline at end of file diff --git a/app/controllers/tests_controller.rb b/app/controllers/tests_controller.rb index 1526a689..1da3ff87 100644 --- a/app/controllers/tests_controller.rb +++ b/app/controllers/tests_controller.rb @@ -1,11 +1,15 @@ class TestsController < Simpler::Controller - def index @time = Time.now + @tests = Test.all + headers["Content-Type"] = "text/html" + status 201 end def create - end + def show + @test = Test.where(id: params[:id]).first + end end diff --git a/app/views/tests/index.html.erb b/app/views/tests/index.html.erb index 39fce580..c6e343f5 100644 --- a/app/views/tests/index.html.erb +++ b/app/views/tests/index.html.erb @@ -1,12 +1,18 @@ - + Index | Simpler application

Simpler framework at work!

<%= @time %>

+ + - \ No newline at end of file + diff --git a/app/views/tests/show.html.erb b/app/views/tests/show.html.erb new file mode 100644 index 00000000..f9e9f154 --- /dev/null +++ b/app/views/tests/show.html.erb @@ -0,0 +1,16 @@ + + + + + Simpler + + +

Simpler framework at work!

+ + <% if @test %> +

<%= @test.title %> (<%= @test.level %>)

+ <% else %> +

Not found

+ <% end %> + + \ No newline at end of file diff --git a/config.ru b/config.ru index 3060cc20..e9de18cd 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,6 @@ +require_relative 'middleware/logger' require_relative 'config/environment' + +use AppLogger, logdev: File.expand_path('log/app.log', __dir__) run Simpler.application diff --git a/config/routes.rb b/config/routes.rb index 4a751251..5b20f922 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Simpler.application.routes do get '/tests', 'tests#index' + get '/tests/:id', 'tests#show' post '/tests', 'tests#create' + end diff --git a/lib/simpler/application.rb b/lib/simpler/application.rb index 711946a9..75e02a50 100644 --- a/lib/simpler/application.rb +++ b/lib/simpler/application.rb @@ -1,12 +1,11 @@ -require 'yaml' -require 'singleton' -require 'sequel' -require_relative 'router' -require_relative 'controller' +require "yaml" +require "singleton" +require "sequel" +require_relative "router" +require_relative "controller" module Simpler class Application - include Singleton attr_reader :db @@ -26,11 +25,15 @@ def routes(&block) @router.instance_eval(&block) end - def call(env) + def call(env, logger) + @logger = logger route = @router.route_for(env) - controller = route.controller.new(env) + return not_found_page unless route + + controller = route.controller.new(env, @logger) action = route.action + @logger.info("Handler: " + controller.class.to_s + "#" + action.to_s) make_response(controller, action) end @@ -41,12 +44,12 @@ def require_app end def require_routes - require Simpler.root.join('config/routes') + require Simpler.root.join("config/routes") end def setup_database - database_config = YAML.load_file(Simpler.root.join('config/database.yml')) - database_config['database'] = Simpler.root.join(database_config['database']) + database_config = YAML.load_file(Simpler.root.join("config/database.yml")) + database_config["database"] = Simpler.root.join(database_config["database"]) @db = Sequel.connect(database_config) end @@ -54,5 +57,12 @@ def make_response(controller, action) controller.make_response(action) end + def not_found_page + [ + 404, + { "Content-Type" => "text/html" }, + ["

404 Page Not Found

"], + ] + end end end diff --git a/lib/simpler/controller.rb b/lib/simpler/controller.rb index 9383b035..af1800bf 100644 --- a/lib/simpler/controller.rb +++ b/lib/simpler/controller.rb @@ -1,35 +1,51 @@ -require_relative 'view' +require_relative "view" module Simpler class Controller + HTTP_CODE_STATUSES = { + "200" => "Ok", + "201" => "Created", + "400" => "Bad Request", + "404" => "Not Found", + "500" => "Internal Server Error", + }.freeze attr_reader :name, :request, :response - def initialize(env) + def initialize(env, logger) + @logger = logger @name = extract_name @request = Rack::Request.new(env) @response = Rack::Response.new + build_params(env) end def make_response(action) - @request.env['simpler.controller'] = self - @request.env['simpler.action'] = action + @request.env["simpler.controller"] = self + @request.env["simpler.action"] = action set_default_headers send(action) write_response + log_info @response.finish end private + def build_params(env) + array = env["REQUEST_PATH"].split("/") + @request.params[:id] = array[2].to_i if array[2].to_i && array[2].to_i != 0 + @logger.info("Parameters: #{@request.params.to_s} ") + end + def extract_name - self.class.name.match('(?.+)Controller')[:name].downcase + self.class.name.match("(?.+)Controller")[:name].downcase end def set_default_headers - @response['Content-Type'] = 'text/html' + @response["Content-Type"] = "text/html" end def write_response @@ -47,8 +63,19 @@ def params end def render(template) - @request.env['simpler.template'] = template + @request.env["simpler.template"] = template + end + + def status(status) + @response.status = status end + def headers + @response + end + + def log_info + @logger.info("Response: #{@response.status} #{HTTP_CODE_STATUSES[@response.status.to_s]} #{@response["Content-Type"]} #{@request.env["simpler.template_path"]}") + end end end diff --git a/lib/simpler/router.rb b/lib/simpler/router.rb index 14b3415c..dbb578b8 100644 --- a/lib/simpler/router.rb +++ b/lib/simpler/router.rb @@ -1,8 +1,7 @@ -require_relative 'router/route' +require_relative "router/route" module Simpler class Router - def initialize @routes = [] end @@ -16,16 +15,39 @@ def post(path, route_point) end def route_for(env) - method = env['REQUEST_METHOD'].downcase.to_sym - path = env['PATH_INFO'] + method = env["REQUEST_METHOD"].downcase.to_sym + path = env["PATH_INFO"] - @routes.find { |route| route.match?(method, path) } + # @routes.find { |route| route.match?(method, path) } + check_nested_route(method, path) + find_route(method, path) end private + def check_nested_route(method, path) + path_details = path.split("/") + + find_nested_route(method, path, path_details) if path_details[2].to_i + end + + def find_nested_route(method, path, path_details) + controller_name = path_details[1] + path_details[2] = ":id" + + path_for_matching = path_details.join("/") + nested_route = find_route(method, path_for_matching) + create_nested_route(method, path, nested_route, controller_name) if nested_route + end + + def create_nested_route(method, path, nested_route, controller) + route = find_route(method, path) + route_point = controller + "#" + nested_route.action + add_route(method, path, route_point) unless route + end + def add_route(method, path, route_point) - route_point = route_point.split('#') + route_point = route_point.split("#") controller = controller_from_string(route_point[0]) action = route_point[1] route = Route.new(method, path, controller, action) @@ -37,5 +59,10 @@ def controller_from_string(controller_name) Object.const_get("#{controller_name.capitalize}Controller") end + def find_route(method, path) + @routes.find do |route| + route.match?(method, path) + end + end end end diff --git a/lib/simpler/router/route.rb b/lib/simpler/router/route.rb index 4c66b4b7..e3948d9d 100644 --- a/lib/simpler/router/route.rb +++ b/lib/simpler/router/route.rb @@ -12,7 +12,7 @@ def initialize(method, path, controller, action) end def match?(method, path) - @method == method && path.match(@path) + @method == method && @path == path end end diff --git a/lib/simpler/view.rb b/lib/simpler/view.rb index 19a73b34..7419382a 100644 --- a/lib/simpler/view.rb +++ b/lib/simpler/view.rb @@ -1,39 +1,52 @@ -require 'erb' +require "erb" module Simpler class View - - VIEW_BASE_PATH = 'app/views'.freeze + VIEW_BASE_PATH = "app/views".freeze def initialize(env) @env = env end - def render(binding) + def render(bind) + custom = check_for_custom_template + return custom unless custom.nil? + template = File.read(template_path) - ERB.new(template).result(binding) + ERB.new(template).result(bind) end private def controller - @env['simpler.controller'] + @env["simpler.controller"] end def action - @env['simpler.action'] + @env["simpler.action"] end def template - @env['simpler.template'] + @env["simpler.template"] end def template_path - path = template || [controller.name, action].join('/') - + path = @template || [controller.name, action].join('/') + @env['simpler.template_path'] = "#{path}.html.erb" Simpler.root.join(VIEW_BASE_PATH, "#{path}.html.erb") end + def check_for_custom_template + @template = template + return nil unless @template.instance_of?(Hash) + + template_key = @template.keys[0] + template_value = @template[template_key] + + case template_key + when :plain then template_value + end + end end end diff --git a/middleware/logger.rb b/middleware/logger.rb new file mode 100644 index 00000000..6c90bfe0 --- /dev/null +++ b/middleware/logger.rb @@ -0,0 +1,19 @@ +require 'logger' + +class AppLogger + + def initialize(app, **option) + @logger = Logger.new(option[:logdev] || STDOUT) + @app = app + end + + def call(env) + @logger.info(log_request(env)) + @app.call(env, @logger) + end + + def log_request(env) + "Request: " + env['REQUEST_METHOD'] + " " + env['PATH_INFO'] + "?" + env['QUERY_STRING'] + end + +end \ No newline at end of file