diff --git a/app/controllers/tests_controller.rb b/app/controllers/tests_controller.rb index 1526a689..15bb134a 100644 --- a/app/controllers/tests_controller.rb +++ b/app/controllers/tests_controller.rb @@ -8,4 +8,8 @@ def create end + def show + render inline: '<%= Test.find(params[:id].to_i) %>' + end + end diff --git a/app/views/tests/create.html.erb b/app/views/tests/create.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/config.ru b/config.ru index 3060cc20..67b662e4 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,4 @@ require_relative 'config/environment' +use AppLogger run Simpler.application diff --git a/config/environment.rb b/config/environment.rb index 7a0d38c3..09f789a0 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,3 +1,4 @@ require_relative '../lib/simpler' +require_relative '../lib/middleware/app_logger' Simpler.application.bootstrap! diff --git a/config/routes.rb b/config/routes.rb index 4a751251..14066154 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Simpler.application.routes do get '/tests', 'tests#index' post '/tests', 'tests#create' + get '/test/:id', 'tests#show' end diff --git a/lib/middleware/app_logger.rb b/lib/middleware/app_logger.rb new file mode 100644 index 00000000..307c3388 --- /dev/null +++ b/lib/middleware/app_logger.rb @@ -0,0 +1,37 @@ +require 'logger' + +class AppLogger + def initialize(app, **options) + @logger = Logger.new(Simpler.root.join('log/app.log')) + @app = app + end + + def call(env) + @response = @app.call(env) + @logger.info(request(env)) + @logger.info(handler(env)) + @logger.info(parameters(env)) + @logger.info(response(env)) + + @response + end + + private + + def request(env) + "Request: #{env['REQUEST_METHOD']} #{env['PATH_INFO']}" + end + + def handler(env) + "Handler: #{env['simpler.controller'].class.name}##{env['simpler.action']}" + end + + def parameters(env) + "Parameters: #{env['simpler.params']}" + end + + def response(env) + "Response: #{@response[0]} [#{@response[1]['Content-Type']}] #{env['simpler.template_path']}" + end + +end diff --git a/lib/simpler/application.rb b/lib/simpler/application.rb index 711946a9..1d1af1be 100644 --- a/lib/simpler/application.rb +++ b/lib/simpler/application.rb @@ -28,10 +28,13 @@ def routes(&block) def call(env) route = @router.route_for(env) + return not_found unless route + controller = route.controller.new(env) action = route.action + params = route.params - make_response(controller, action) + make_response(controller, action, params) end private @@ -50,8 +53,12 @@ def setup_database @db = Sequel.connect(database_config) end - def make_response(controller, action) - controller.make_response(action) + def make_response(controller, action, params) + controller.make_response(action, params) + end + + def not_found + Rack::Response.new('Not Found', 404, { 'Content-Type' => 'text/plain' }).finish end end diff --git a/lib/simpler/controller.rb b/lib/simpler/controller.rb index 9383b035..6ba7e505 100644 --- a/lib/simpler/controller.rb +++ b/lib/simpler/controller.rb @@ -11,9 +11,10 @@ def initialize(env) @response = Rack::Response.new end - def make_response(action) + def make_response(action, params) @request.env['simpler.controller'] = self @request.env['simpler.action'] = action + @request.env['simpler.params'] = params set_default_headers send(action) @@ -32,6 +33,19 @@ def set_default_headers @response['Content-Type'] = 'text/html' end + def set_header(key, value) + @response[key] = value + end + + def set_status(code) + @response.status = code + end + + def set_render_params(**options) + set_header('Content-Type', options[:content_type]) if options.has_key? :content_type + set_status(options[:status]) if options.has_key? :status + end + def write_response body = render_body @@ -43,11 +57,16 @@ def render_body end def params - @request.params + @request.params.merge(@request.env['simpler.params']) end - def render(template) - @request.env['simpler.template'] = template + def render(*args, **options) + set_render_params(**options) + @request.env['simpler.template'] = if args.length.zero? + options.except(:content_type, :status) + else + { erb: args } + end end end diff --git a/lib/simpler/router.rb b/lib/simpler/router.rb index 14b3415c..45086e9b 100644 --- a/lib/simpler/router.rb +++ b/lib/simpler/router.rb @@ -19,7 +19,9 @@ def route_for(env) method = env['REQUEST_METHOD'].downcase.to_sym path = env['PATH_INFO'] - @routes.find { |route| route.match?(method, path) } + route = @routes.find { |route| route.match?(method, path) } + route.set_params(path) + route end private diff --git a/lib/simpler/router/route.rb b/lib/simpler/router/route.rb index 4c66b4b7..1f0ea0b1 100644 --- a/lib/simpler/router/route.rb +++ b/lib/simpler/router/route.rb @@ -2,7 +2,7 @@ module Simpler class Router class Route - attr_reader :controller, :action + attr_reader :controller, :action, :params def initialize(method, path, controller, action) @method = method @@ -12,7 +12,11 @@ def initialize(method, path, controller, action) end def match?(method, path) - @method == method && path.match(@path) + @method == method && (path =~ Regexp.new(@path.gsub(/:(\w+)/, '\w+'))) == 0 + end + + def set_params(path) + @params = path.match(Regexp.new(@path.gsub(/:(\w+)/, '(?<\1>.+)'))).named_captures.transform_keys!(&:to_sym) end end diff --git a/lib/simpler/view.rb b/lib/simpler/view.rb index 19a73b34..ff82e687 100644 --- a/lib/simpler/view.rb +++ b/lib/simpler/view.rb @@ -1,22 +1,48 @@ require 'erb' +require 'json' module Simpler class View VIEW_BASE_PATH = 'app/views'.freeze + VIEW_TYPES = %i[erb plain json inline].freeze def initialize(env) @env = env + @view_type = @env['simpler.template'].nil? ? :erb : set_view_type + @view_body = @env['simpler.template'].nil? ? nil : @env['simpler.template'][@view_type] + end + + def set_view_type + available_types = @env['simpler.template'].keys.intersection(VIEW_TYPES) + available_types.nil? ? :erb : available_types[0] end def render(binding) - template = File.read(template_path) + @binding = binding - ERB.new(template).result(binding) + send @view_type end private + def erb + template = File.read(template_path) + ERB.new(template).result(@binding) + end + + def plain + @view_body + end + + def json + @view_body.to_json + end + + def inline + ERB.new(@env['simpler.template'][@view_type]).result(@binding) + end + def controller @env['simpler.controller'] end @@ -26,11 +52,11 @@ def action end def template - @env['simpler.template'] + @view_body end def template_path - path = template || [controller.name, action].join('/') + @env['simpler.template_path'] = path = template || [controller.name, action].join('/') Simpler.root.join(VIEW_BASE_PATH, "#{path}.html.erb") end diff --git a/log/app.log b/log/app.log new file mode 100644 index 00000000..bc40e158 --- /dev/null +++ b/log/app.log @@ -0,0 +1,12 @@ +I, [2023-04-02T12:47:44.696636 #22331] INFO -- : Request: GET /tests +I, [2023-04-02T12:47:44.696723 #22331] INFO -- : Handler: TestsController#index +I, [2023-04-02T12:47:44.696751 #22331] INFO -- : Parameters: {} +I, [2023-04-02T12:47:44.696774 #22331] INFO -- : Response: 200 [text/html] tests/index +I, [2023-04-02T12:48:58.203803 #22331] INFO -- : Request: GET /test/1 +I, [2023-04-02T12:48:58.212994 #22331] INFO -- : Handler: TestsController#show +I, [2023-04-02T12:48:58.213071 #22331] INFO -- : Parameters: {:id=>"1"} +I, [2023-04-02T12:48:58.213111 #22331] INFO -- : Response: 200 [text/html] +I, [2023-04-02T12:50:48.216637 #22331] INFO -- : Request: POST /tests +I, [2023-04-02T12:50:48.216711 #22331] INFO -- : Handler: TestsController#create +I, [2023-04-02T12:50:48.216745 #22331] INFO -- : Parameters: {} +I, [2023-04-02T12:50:48.216773 #22331] INFO -- : Response: 200 [text/html] tests/create