diff --git a/Rakefile b/Rakefile index ac33200..8dd097f 100644 --- a/Rakefile +++ b/Rakefile @@ -8,7 +8,7 @@ task :migrate do # Always applies up to latest version for now version = nil - require_relative "db" + require_relative "lib/db" require "logger" Sequel.extension :migration DB.loggers << Logger.new($stdout) if DB.loggers.empty? diff --git a/lib/app.rb b/lib/app.rb index c376d90..d265456 100644 --- a/lib/app.rb +++ b/lib/app.rb @@ -5,6 +5,14 @@ require_relative "views" require "roda" module RankKing + module Models + require "sequel/model" + require_relative "db" + + class Pool < Sequel::Model + end + end + class App < Roda opts[:check_dynamic_arity] = false opts[:check_arity] = :warn @@ -26,19 +34,19 @@ module RankKing csp.frame_ancestors :none end - # css_opts = {cache: false, style: :compressed} + css_opts = {cache: false, style: :compressed} # :nocov: - # if ENV["RACK_ENV"] == 'development' - # css_opts.merge!(source_map_embed: true, source_map_contents: true, source_map_file: ".") - # end - # plugin :render_coverage if defined?(SimpleCov) + if ENV["RACK_ENV"] == 'development' + css_opts.merge!(source_map_embed: true, source_map_contents: true, source_map_file: ".") + end + plugin :render_coverage if defined?(SimpleCov) # :nocov: plugin :route_csrf plugin :flash # plugin :assets, css: "app.scss", css_opts: css_opts, timestamp_paths: true # plugin :render, escape: true, layout: "./layout", :template_opts=>{chain_appends: !defined?(SimpleCov), freeze: true, skip_compiled_encoding_detection: true} - # plugin :public + plugin :public plugin :Integer_matcher_max plugin :typecast_params_sized_integers, sizes: [64], default_size: 64 # plugin :hash_branch_view_subdir @@ -52,8 +60,7 @@ module RankKing plugin :common_logger, logger plugin :not_found do - @page_title = "File Not Found" - view(content: "") + Views::Layout.call(title: "File Not Found") end if ENV["RACK_ENV"] == "development" @@ -98,22 +105,90 @@ module RankKing # end # Unreloader.autoload("routes", delete_hook: proc{|f| hash_branch(File.basename(f).delete_suffix(".rb"))}){} - # def render(view, layout=Views::Layout.new) - # component.call + class Template < Phlex::HTML + def initialize(block) + @block = block + end + + def template + instance_eval(&@block) + end + end + + # def render(&block) + # template = Template.new(block) + # instance_variables + # .reject { _1.start_with?("@_") } + # .each { template.instance_variable_set(_1, instance_variable_get(_1)) } + # Views::Layout.call do + # plain "" + # end + # # Views::Layout.call(template) + # # Views::Layout.call do |layout| + # # layout.page_title "New Pool" + # # plain "" + # # end # end + def view(&block) + Class.new(Phlex::HTML, &block).call + end + route do |r| + # r.public # r.assets check_csrf! r.root do - Views::Layout.new(Views::Hello.new(name: "Bob")).call + if DB[:pools].empty? + r.redirect "/pools/new" + else + render do + h1 { "ohai" } + end + end end r.on "pools" do r.is "new" do - Views::Layout.new(Views::NewPool.new).call + r.get do + @csrf_token = csrf_token(r.path) + view do + Views::Layout.new(title: "New Pool") do + Views::NewPool.new(csrf_token: @csrf_token) + end + end + # Views::Layout.call(title: "New Pool") do + # render Views::NewPool.new(csrf_token: csrf_token(r.path)) + # end + # layout = Views::Layout.new do |layout| + # layout.page_title "New Pool" + # render Views::NewPool.new(csrf_token: csrf_token(r.path)) + # end + # layout.call + # @csrf_token = csrf_token(r.path) + # render do + # form(method: "post") do + # input(type: "hidden", name: "_csrf", value: @csrf_token) + # label(for: "name") + # input(type: "text", name: "name", id: "name", required: true) + # input(type: "submit", value: "Create") + # end + # end + end + + r.post do + pool = Models::Pool.create(name: r.params.fetch("name")) + r.redirect "/pools/#{pool.id}" + end + end + + r.is Integer do |id| + pool = Models::Pool[id] + render do + h2 { pool.name } + end end end end diff --git a/lib/models.rb b/lib/models.rb index aba51f5..4055c5b 100644 --- a/lib/models.rb +++ b/lib/models.rb @@ -10,6 +10,7 @@ end Sequel::Model.plugin :auto_validations Sequel::Model.plugin :require_valid_schema Sequel::Model.plugin :subclasses unless ENV["RACK_ENV"] == "development" +Sequel::Model.plugin :timestamps, update_on_create: true unless defined?(Unreloader) require "rack/unreloader" diff --git a/lib/views.rb b/lib/views.rb index af7d82b..86a8783 100644 --- a/lib/views.rb +++ b/lib/views.rb @@ -4,17 +4,17 @@ module RankKing module Views class Layout < Phlex::HTML - def initialize(view) - @view = view + def initialize(title: nil) + @title = title end - def template + def template(&block) doctype html(lang: "en") do head do meta(charset: "utf-8") meta(name: "viewport", content: "width=device-width, initial-scale=1") - title { "Rank King" } + title { ["Rank King", @title].compact.join(" - ") } end body do @@ -24,9 +24,7 @@ module RankKing nav - main do - render @view - end + main(&block) footer end @@ -35,8 +33,17 @@ module RankKing end class NewPool < Phlex::HTML + def initialize(csrf_token:) + @csrf_token = csrf_token + end + def template - plain "ohai" + form do + input(type: "hidden", name: "_csrf", value: @csrf_token) + label(for: "name") + input(type: "text", name: "name", id: "name", required: true) + input(type: "submit", value: "Create") + end end end end