diff --git a/app/controllers/tests_controller.rb b/app/controllers/tests_controller.rb index 1526a689..37357961 100644 --- a/app/controllers/tests_controller.rb +++ b/app/controllers/tests_controller.rb @@ -1,11 +1,12 @@ class TestsController < Simpler::Controller - def index @time = Time.now end - def create + def create; end + def show + status(201) + @test = Test.first(id: params['id']) end - end diff --git a/app/views/tests/show.html.erb b/app/views/tests/show.html.erb new file mode 100644 index 00000000..3719ba9c --- /dev/null +++ b/app/views/tests/show.html.erb @@ -0,0 +1,14 @@ + + +
+ +ID - <%= @test.id %>
+Title - <%= @test.title %>
+Level - <%= @test.level %>
+ + diff --git a/config.ru b/config.ru index 3060cc20..e065e105 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,5 @@ require_relative 'config/environment' +require_relative 'middleware/logger' +use Logger run Simpler.application diff --git a/config/routes.rb b/config/routes.rb index 4a751251..1700ff3a 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 '/tests/:id', 'tests#show' end diff --git a/lib/simpler/application.rb b/lib/simpler/application.rb index 711946a9..37445c26 100644 --- a/lib/simpler/application.rb +++ b/lib/simpler/application.rb @@ -28,6 +28,9 @@ def routes(&block) def call(env) route = @router.route_for(env) + return @router.not_found(env) unless route + + route.extract_params(env) controller = route.controller.new(env) action = route.action diff --git a/lib/simpler/controller.rb b/lib/simpler/controller.rb index 9383b035..0a005c9f 100644 --- a/lib/simpler/controller.rb +++ b/lib/simpler/controller.rb @@ -9,6 +9,8 @@ def initialize(env) @name = extract_name @request = Rack::Request.new(env) @response = Rack::Response.new + @request.params.merge!(env['params']) + @rendered = false end def make_response(action) @@ -36,19 +38,62 @@ def write_response body = render_body @response.write(body) + @rendered = true + end + + def set_content_type(content_type) + headers['Content-Type'] = content_type end def render_body View.new(@request.env).render(binding) end + def render_string(template) + @request.env['simpler.template'] = template + end + + def render_error(error_message) + status 500 + @response.write(error_message) + @response.finish + end + + def render_hash(params) + if params.key?(:plain) + render_plain(hash[:plain]) + else + render_error("Cannot render template with #{params.keys} options") + end + end + + def render_plain(text) + set_content_type('text/plain') + @response.write(text) + end + + def status(status) + response.status = status + end + + def headers + @response.headers + end + def params @request.params end def render(template) - @request.env['simpler.template'] = template + case template + when String + render_string(template) + when Hash + render_hash(template) + else + render_error("Cannot render #{template.class} template") + end + @rendered = true end - end end diff --git a/lib/simpler/router.rb b/lib/simpler/router.rb index 14b3415c..9958e851 100644 --- a/lib/simpler/router.rb +++ b/lib/simpler/router.rb @@ -22,6 +22,16 @@ def route_for(env) @routes.find { |route| route.match?(method, path) } end + def not_found(env) + method = env['REQUEST_METHOD'].downcase.to_sym + path = env['PATH_INFO'] + Rack::Response.new.then do |response| + response.status = 404 + response.write("[#{method} #{path}] route not found") + response.finish + end + end + private def add_route(method, path, route_point) @@ -36,6 +46,5 @@ def add_route(method, path, route_point) def controller_from_string(controller_name) Object.const_get("#{controller_name.capitalize}Controller") end - end end diff --git a/lib/simpler/router/route.rb b/lib/simpler/router/route.rb index 4c66b4b7..8da21fe6 100644 --- a/lib/simpler/router/route.rb +++ b/lib/simpler/router/route.rb @@ -13,8 +13,26 @@ def initialize(method, path, controller, action) def match?(method, path) @method == method && path.match(@path) + @method == method && path.match(to_regex(@path)) end + def extract_params(env) + request_path_items = env['PATH_INFO'].split('/') + path_items = @path.split('/').map { |item| item.sub(':', '') } + + params = Hash[path_items.zip(request_path_items)].delete_if { |k, v| k == v } + env['params'] = params + end + + private + + def to_regex(path) + path.split('/') + .map { |string| string.start_with?(':') ? '\d+' : string } + .join('/') + .concat('$') + .then { |regex| Regexp.new regex } + end end end end diff --git a/log/app.log b/log/app.log new file mode 100644 index 00000000..c6773863 --- /dev/null +++ b/log/app.log @@ -0,0 +1,211 @@ + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"2"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"2"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"2"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"2"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: NilClass# + Parameters: + Response: 404 [] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#index + Parameters: {} + Response: 200 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + + Request: GET + Handler: TestsController#show + Parameters: {"id"=>"1"} + Response: 201 [text/html] + \ No newline at end of file diff --git a/middleware/logger.rb b/middleware/logger.rb new file mode 100644 index 00000000..dc9f9642 --- /dev/null +++ b/middleware/logger.rb @@ -0,0 +1,34 @@ +class Logger + def initialize(app) + @app = app + end + + def call(env) + @env = env + status, headers, body = @app.call(env) + + log_content = collect_logs(status, headers, body) + logging(log_content) + + [status, headers, body] + end + + def logging(content) + filepath = File.expand_path('log/app.log') + write_mode = File.exist?(filepath) ? 'a' : 'w' + File.write(filepath, content, mode: write_mode) + end + + def collect_logs(status, headers, _body) + controller = @env['simpler.controller'].class.name + action = @env['simpler.action'] + template = @env['simpler.template'] || @env['simpler.render'] + parameters = @env['params'] + " + Request: #{@env['REQUEST_METHOD']} + Handler: #{controller}##{action} + Parameters: #{parameters} + Response: #{status} [#{headers['Content-Type']}] #{template} + " + end +end