Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions app/controllers/tests_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
class TestsController < Simpler::Controller

def index
@time = Time.now
render plain: 'Plain text response', status: 201, headers: { 'X-Custom' => 'Value' }
end

def create

def show
render plain: "Show test #{params[:id]}"
end

end
1 change: 0 additions & 1 deletion app/models/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@
# Integer :level, default: 0
# end
class Test < Sequel::Model

end
3 changes: 3 additions & 0 deletions config.ru
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
require_relative 'config/environment'
require_relative 'lib/middleware/logger'

use LoggerForSimpler
use Rack::ContentType
run Simpler.application
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Simpler.application.routes do
get '/tests', 'tests#index'
post '/tests', 'tests#create'
get '/tests/:id', 'tests#show'
end
55 changes: 55 additions & 0 deletions lib/middleware/logger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
require 'logger'

class LoggerForSimpler
def initialize(app)
@logger = create_logger
@app = app
end

def call(env)
request = Rack::Request.new(env)
status, headers, body = @app.call(env)
@logger.info(log_message(request, status, headers, env))

[status, headers, body]
end

private

def create_logger
log_dir = Simpler.root.join('log')
FileUtils.mkdir_p(log_dir) unless File.directory?(log_dir)

log_file = File.expand_path(Simpler.root.join('log/app.log'), __dir__) || STROUT
Logger.new(log_file)
end

def log_message(request, status, headers, env)
<<~LOG
Request: #{request.request_method} #{request.fullpath}
Handler: #{controller(env)}##{action(env)}
Parameters: #{request.params.inspect}
Response: #{status} [#{content_type(headers)}] #{template(env)}
LOG
end

def controller(env)
env['simpler.controller'] ? env['simpler.controller'].class.name : 'UnknownController'
end

def action(env)
env['simpler.action'] || 'unknown_action'
end

def template(env)
return "#{env['simpler.template']}.html.erb" if env['simpler.template']

controller_name = env['simpler.controller']&.name || 'unknown_controller'
action = env['simpler.action'] || 'unknown_action'
"#{controller_name}/#{action}.html.erb"
end

def content_type(headers)
headers['Content-Type'] || 'unknown_content_type'
end
end
2 changes: 0 additions & 2 deletions lib/simpler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
require_relative 'simpler/application'

module Simpler

class << self
def application
Application.instance
Expand All @@ -12,5 +11,4 @@ def root
Pathname.new(File.expand_path('..', __dir__))
end
end

end
9 changes: 7 additions & 2 deletions lib/simpler/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

module Simpler
class Application

include Singleton

attr_reader :db
Expand All @@ -28,6 +27,9 @@ def routes(&block)

def call(env)
route = @router.route_for(env)
return not_found unless route

env['simpler.route_params'] = route.extract_params(env['PATH_INFO']) || {}
controller = route.controller.new(env)
action = route.action

Expand All @@ -37,7 +39,7 @@ def call(env)
private

def require_app
Dir["#{Simpler.root}/app/**/*.rb"].each { |file| require file }
Dir["#{Simpler.root}/app/**/*.rb"].sort.each { |file| require file }
end

def require_routes
Expand All @@ -54,5 +56,8 @@ def make_response(controller, action)
controller.make_response(action)
end

def not_found
[404, {}, ['Not Found']]
end
end
end
45 changes: 36 additions & 9 deletions lib/simpler/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,41 @@

module Simpler
class Controller

attr_reader :name, :request, :response

def initialize(env)
@name = extract_name
@request = Rack::Request.new(env)
@response = Rack::Response.new
@render_options = {}
end

def make_response(action)
@request.env['simpler.controller'] = self
@request.env['simpler.action'] = action

set_default_headers
send(action)
write_response

@response.finish
end

def params
@request.params.merge(@request.env['simpler.route_params'])
end

private

def extract_name
self.class.name.match('(?<name>.+)Controller')[:name].downcase
end

def set_default_headers
@response['Content-Type'] = 'text/html'
end

def write_response
body = render_body
body = if @render_options.any?
render_from_options
else
render_body
end

@response.write(body)
end
Expand All @@ -46,9 +49,33 @@ def params
@request.params
end

def render(template)
@request.env['simpler.template'] = template
def render(options)
if options.is_a?(Hash)
@render_options = options
else
@request.env['simpler.template'] = options
end
end

def render_from_options
options = @render_options

@response.status = options[:status] if options[:status]

options[:headers]&.each { |key, value| @response[key] = value }

if options.key?(:plain)
@response['Content-Type'] = 'text/plain'
options[:plain]
elsif options.key?(:json)
@response['Content-Type'] = 'application/json'
options[:json].to_json
elsif options.key?(:html)
@response['Content-Type'] = 'text/html'
options[:html]
else
''
end
end
end
end
2 changes: 0 additions & 2 deletions lib/simpler/router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

module Simpler
class Router

def initialize
@routes = []
end
Expand Down Expand Up @@ -36,6 +35,5 @@ def add_route(method, path, route_point)
def controller_from_string(controller_name)
Object.const_get("#{controller_name.capitalize}Controller")
end

end
end
17 changes: 15 additions & 2 deletions lib/simpler/router/route.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
module Simpler
class Router
class Route

attr_reader :controller, :action

def initialize(method, path, controller, action)
@method = method
@path = path
@controller = controller
@action = action
@pattern = compile_path_pattern(path)
end

def match?(method, path)
@method == method && path.match(@path)
@method == method && path.match(@pattern)
end

def extract_params(path)
match = path.match(@pattern)
match&.named_captures&.transform_keys(&:to_sym)
end

private

def compile_path_pattern(path)
segments = path.split('/').map do |segment|
segment.start_with?(':') ? "(?<#{segment[1..]}>[^\/]+)" : segment
end
Regexp.new("^#{segments.join('/')}$")
end
end
end
end
4 changes: 1 addition & 3 deletions lib/simpler/view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

module Simpler
class View

VIEW_BASE_PATH = 'app/views'.freeze
VIEW_BASE_PATH = 'app/views'

def initialize(env)
@env = env
Expand Down Expand Up @@ -34,6 +33,5 @@ def template_path

Simpler.root.join(VIEW_BASE_PATH, "#{path}.html.erb")
end

end
end