Created
May 7, 2017 06:42
-
-
Save elorest/6d00f941dc66ff2a03e346ab41ff6c28 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "http" | |
require "./*" | |
module Amber::Controller | |
class Base | |
include Render | |
include Redirect | |
include Callbacks | |
protected getter request = HTTP::Request.new("GET", "/") | |
protected getter response = HTTP::Server::Response.new(IO::Memory.new) | |
protected getter raw_params = HTTP::Params.parse("") | |
protected getter context : HTTP::Server::Context? | |
protected getter params : Amber::Validators::Params = Amber::Validators::Params.new(HTTP::Params.parse("t=t")) | |
def initialize(@context : HTTP::Server::Context) | |
set_context(@context.not_nil!) | |
end | |
def initialize | |
end | |
def set_context(@context : HTTP::Server::Context) | |
@request = context.request | |
@response = context.response | |
@raw_params = context.params | |
@params = Amber::Validators::Params.new(@raw_params) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Amber::DSL | |
module Callbacks | |
macro before_action | |
def before_filters : Nil | |
filters.register :before do | |
{{yield}} | |
end | |
end | |
end | |
macro after_action | |
def after_filters : Nil | |
filters.register :after do | |
{{yield}} | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Amber::Controller | |
module Callbacks | |
macro included | |
include Amber::DSL::Callbacks | |
property filters : Filters = Filters.new | |
def run_before_filter(action) | |
if self.responds_to? :before_filters | |
self.before_filters | |
@filters.run(:before, action) | |
@filters.run(:before, :all) | |
end | |
end | |
def run_after_filter(action) | |
if self.responds_to? :after_filters | |
self.after_filters | |
@filters.run(:after, action) | |
@filters.run(:after, :all) | |
end | |
end | |
end | |
end | |
record Filter, precedence : Symbol, action : Symbol, blk : -> Nil do | |
end | |
# Builds a BeforeAction filter. | |
# | |
# The yielded object has an `only` method that accepts two arguments, | |
# a key (`Symbol`) and a block ->`Nil`. | |
# | |
# ``` | |
# FilterChainBuilder.build do |b| | |
# filter :index, :show { some_method } | |
# filter :delete { } | |
# end | |
# ``` | |
record FilterBuilder, filters : Filters, precedence : Symbol do | |
def only(action : Symbol, &block : -> Nil) | |
add(action, &block) | |
end | |
def only(actions : Array(Symbol), &block : -> Nil) | |
actions.each { |action| add(action, &block) } | |
end | |
def all(&block : -> Nil) | |
filters.add Filter.new(precedence, :all, block) | |
end | |
def add(action, &block : -> Nil) | |
filters.add Filter.new(precedence, action, block) | |
end | |
end | |
class Filters | |
include Enumerable({Symbol, Array(Filter)}) | |
property filters = {} of Symbol => Array(Filter) | |
def register(precedence : Symbol) : Nil | |
with FilterBuilder.new(self, precedence) yield | |
end | |
def add(filter : Filter) | |
filters[filter.precedence] ||= [] of Filter | |
filters[filter.precedence] << filter | |
end | |
def run(precedence : Symbol, action : Symbol) | |
filters[precedence].each do |filter| | |
filter.blk.call if filter.action == action | |
end | |
end | |
def [](name) | |
filters[name] | |
end | |
def []?(name) | |
fetch(name) { nil } | |
end | |
def fetch(name) | |
filters.fetch(name) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Amber | |
class Route | |
property :controller, :handler, :action, :verb, :resource, :valve, :params,:scope | |
property wholeproc : Proc(HTTP::Server::Context, Symbol, String) | |
def initialize(@verb : String, | |
@resource : String, | |
@wholeproc, | |
@controller = Controller::Base.new, | |
@handler : Proc(String) = ->{ "500" }, | |
@action : Symbol = :index, | |
@valve : Symbol = :web, | |
@scope : String = "") | |
end | |
def trail | |
"#{verb.to_s.downcase}#{scope}#{resource}" | |
end | |
def trail_head | |
"head#{scope}#{resource}" | |
end | |
def call(context) | |
# controller.set_context(context) | |
# controller.run_before_filter(:all) | |
# controller.run_before_filter(action) | |
# content = handler.call | |
# controller.run_after_filter(action) | |
# controller.run_after_filter(:all) | |
# content | |
wholeproc.call(context, action) unless wholeproc.is_a?(String) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Amber::DSL | |
record Pipeline, pipeline : Pipe::Pipeline do | |
def plug(pipe) | |
pipeline.plug pipe | |
end | |
end | |
record Router, router : Pipe::Router, valve : Symbol, scope : String do | |
RESOURCES = [:get, :post, :put, :patch, :delete, :options, :head, :trace, :connect] | |
macro route(verb, resource, controller, action) | |
puts "{{verb.id}} {{resource.id}} {{controller.id}} {{action.id}}" | |
%controller = {{controller.id}}.new | |
%handler = ->%controller.{{action.id}} | |
%verb = {{verb.upcase.id.stringify}} | |
%wholeproc = ->(context : HTTP::Server::Context, action : Symbol){ | |
controller = {{controller.id}}.new(context) | |
controller.run_before_filter(:all) | |
controller.run_before_filter(action) | |
content = controller.{{ action.id }} | |
controller.run_after_filter(action) | |
controller.run_after_filter(:all) | |
content | |
} | |
%route = Amber::Route.new(%verb, {{resource}}, %wholeproc, %controller, %handler, {{action}}, valve, scope) | |
router.add(%route) | |
end | |
{% for verb in RESOURCES %} | |
macro {{verb.id}}(*args) | |
route {{verb}}, \{{*args}} | |
end | |
{% end %} | |
# TODO Clean this up | |
macro resources(path, controller, actions = [:index, :edit, :new, :show, :create, :update, :delete]) | |
{% if actions.includes?(:index) %} | |
get "{{path.id}}", {{controller}}, :index | |
{% end %} | |
{% if actions.includes?(:edit) %} | |
get "{{path.id}}/:id/edit", {{controller}}, :edit | |
{% end %} | |
{% if actions.includes?(:new) %} | |
get "{{path.id}}/new", {{controller}}, :new | |
{% end %} | |
{% if actions.includes?(:show) %} | |
get "{{path.id}}/:id", {{controller}}, :show | |
{% end %} | |
{% if actions.includes?(:create) %} | |
post "{{path.id}}", {{controller}}, :create | |
{% end %} | |
{% if actions.includes?(:update) %} | |
patch "{{path.id}}/:id", {{controller}}, :update | |
put "{{path.id}}/:id", {{controller}}, :update | |
{% end %} | |
{% if actions.includes?(:delete) %} | |
delete "{{path.id}}/:id", {{controller}}, :delete | |
{% end %} | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment