diff --git a/blog_demo.rb b/blog_demo.rb new file mode 100644 index 0000000..b2585c5 --- /dev/null +++ b/blog_demo.rb @@ -0,0 +1,27 @@ +$LOAD_PATH.unshift(File.expand_path('lib', __dir__)) +require 'prism' +require 'net/http' +require_relative 'examples/blog/app' + +server = Prism::Server.new(Blog, port: 0).start +port = server.port +puts "blog demo server on port #{port}" +puts "database file: #{File.join(__dir__, 'examples/blog/db/development.pstore')}" +puts '-' * 40 + +Net::HTTP.start('127.0.0.1', port) do |http| + create = http.post( + '/posts', + URI.encode_www_form(title: 'Hello from Prism', body: 'This record was written through the ORM-lite file store.'), + 'Content-Type' => 'application/x-www-form-urlencoded' + ) + puts "POST /posts -> #{create.code} Location=#{create['location']}" + + listing = http.get('/posts') + puts "GET /posts -> #{listing.code}" + puts listing.body +end + +server.stop +puts '-' * 40 +puts 'blog demo done (process about to exit; data stays on disk for the restart check)' diff --git a/demo.rb b/demo.rb new file mode 100644 index 0000000..0de5d99 --- /dev/null +++ b/demo.rb @@ -0,0 +1,40 @@ +$LOAD_PATH.unshift(File.expand_path('lib', __dir__)) +require 'prism' +require 'net/http' +require_relative 'examples/app' + +server = Prism::Server.new(ExampleApp, port: 0).start +port = server.port +puts "demo server on port #{port}" +puts '-' * 40 + +Net::HTTP.start('127.0.0.1', port) do |http| + hello = http.get('/hello/Ruby') + puts "GET /hello/Ruby -> #{hello.code}" + puts hello.body + + search = http.get('/search?q=prism&page=2') + puts "GET /search?q=prism&page=2 -> #{search.code} #{search.body}" + + echo = http.post('/echo', JSON.generate(name: 'foksiu', role: 'admin'), 'Content-Type' => 'application/json') + puts "POST /echo -> #{echo.code} #{echo.body}" + + files = http.get('/files/docs/readme.txt') + puts "GET /files/docs/readme.txt -> #{files.code} #{files.body}" + + status = http.get('/api/status') + puts "GET /api/status -> #{status.code} #{status.body}" + + first = http.get('/count') + cookie = first['set-cookie'].split(';').first + puts "GET /count -> #{first.body} (cookie issued: #{!first['set-cookie'].nil?})" + second = http.get('/count', 'Cookie' => cookie) + puts "GET /count (with cookie) -> #{second.body}" + + redirect = http.get('/old') + puts "GET /old -> #{redirect.code} Location=#{redirect['location']}" +end + +server.stop +puts '-' * 40 +puts 'demo done' diff --git a/examples/app.rb b/examples/app.rb new file mode 100644 index 0000000..1a06c13 --- /dev/null +++ b/examples/app.rb @@ -0,0 +1,63 @@ +$LOAD_PATH.unshift(File.expand_path('../lib', __dir__)) +require 'prism' + +class ExampleApp < Prism::Application + enable_sessions(secret: 'prism-demo-secret') + use Prism::Middleware::Logger + + helpers do + def layout(title, inner) + erb(<<~TEMPLATE, locals: { title: title, inner: inner }) + + <%= title %> + <%== inner %> + TEMPLATE + end + end + + get '/' do + html('

Prism

') + end + + get '/hello/:name' do + greeting = erb('

Hello, <%= name %>!

', locals: { name: params['name'] }) + layout('Hello', greeting) + end + + get '/search' do + json(query: params['q'], page: params['page']) + end + + post '/echo' do + json(received: params.to_h) + end + + get '/files/*' do + json(path: params['splat']) + end + + group '/api' do + get '/status' do + json(ok: true) + end + end + + get '/count' do + session['count'] = (session['count'] || 0) + 1 + json(count: session['count']) + end + + get '/old' do + redirect '/', 301 + end +end + +if __FILE__ == $PROGRAM_NAME + server = Prism::Server.new(ExampleApp, port: (ARGV[0] || 0).to_i).start + puts "Prism example listening on #{server.url}" + trap('INT') do + server.stop + exit + end + sleep +end diff --git a/examples/blog/app.rb b/examples/blog/app.rb new file mode 100644 index 0000000..df671bf --- /dev/null +++ b/examples/blog/app.rb @@ -0,0 +1,23 @@ +require 'prism' + +APP_ROOT = __dir__ + +Prism::Orm.connect(File.join(APP_ROOT, 'db', 'development.pstore')) +Prism::Orm.migrator(File.join(APP_ROOT, 'db', 'migrate')).migrate! + +Prism::Controller.views_root(File.join(APP_ROOT, 'app', 'views')) +Prism::Controller.layout(:application) + +Dir[File.join(APP_ROOT, 'app', 'models', '*.rb')].sort.each { |file| require file } +Dir[File.join(APP_ROOT, 'app', 'controllers', '*.rb')].sort.each { |file| require file } + +class Blog < Prism::Application + set :views, File.join(APP_ROOT, 'app', 'views') + enable_sessions(secret: 'blog-demo-secret') + use Prism::Middleware::Logger + use Prism::Middleware::ParamsParser + use Prism::Middleware::Static, root: File.join(APP_ROOT, 'public') + + root(to: 'posts#index') + resources :posts, only: %i[index show create] +end diff --git a/examples/blog/app/controllers/posts_controller.rb b/examples/blog/app/controllers/posts_controller.rb new file mode 100644 index 0000000..ce43279 --- /dev/null +++ b/examples/blog/app/controllers/posts_controller.rb @@ -0,0 +1,24 @@ +class PostsController < Prism::Controller + layout :application + + def index + render(:index, locals: { posts: Post.order(:created_at, :desc), notice: flash[:notice], errors: [] }) + end + + def show + render(:show, locals: { post: Post.find(params['id']) }) + rescue Prism::Orm::RecordNotFound + halt(404, 'Post not found') + end + + def create + post = Post.new(title: params['title'], body: params['body']) + if post.save + flash[:notice] = "Post ##{post.id} created" + redirect url_for(:posts) + else + status(422) + render(:index, locals: { posts: Post.order(:created_at, :desc), notice: nil, errors: post.errors.full_messages }) + end + end +end diff --git a/examples/blog/app/models/post.rb b/examples/blog/app/models/post.rb new file mode 100644 index 0000000..8ccece0 --- /dev/null +++ b/examples/blog/app/models/post.rb @@ -0,0 +1,3 @@ +class Post < Prism::Orm::Model + validates :title, presence: true, length: { minimum: 3 } +end diff --git a/examples/blog/app/views/layouts/application.erb b/examples/blog/app/views/layouts/application.erb new file mode 100644 index 0000000..b504c69 --- /dev/null +++ b/examples/blog/app/views/layouts/application.erb @@ -0,0 +1,5 @@ + + + <%= defined?(title) ? title : 'Prism App' %> + <%== content %> + diff --git a/examples/blog/app/views/posts/_post.erb b/examples/blog/app/views/posts/_post.erb new file mode 100644 index 0000000..ca3f80c --- /dev/null +++ b/examples/blog/app/views/posts/_post.erb @@ -0,0 +1,4 @@ +
  • +

    <%= post.title %>

    +

    <%= post.body %>

    +
  • diff --git a/examples/blog/app/views/posts/index.erb b/examples/blog/app/views/posts/index.erb new file mode 100644 index 0000000..abbf442 --- /dev/null +++ b/examples/blog/app/views/posts/index.erb @@ -0,0 +1,21 @@ +

    Blog

    +<% if notice %> +

    <%= notice %>

    +<% end %> +<% unless errors.empty? %> + +<% end %> +
    + + + +
    + diff --git a/examples/blog/app/views/posts/show.erb b/examples/blog/app/views/posts/show.erb new file mode 100644 index 0000000..c84a437 --- /dev/null +++ b/examples/blog/app/views/posts/show.erb @@ -0,0 +1,2 @@ +

    <%= post.title %>

    +

    <%= post.body %>

    diff --git a/examples/blog/bin/server b/examples/blog/bin/server new file mode 100755 index 0000000..7386e59 --- /dev/null +++ b/examples/blog/bin/server @@ -0,0 +1,6 @@ +require_relative '../app' + +server = Prism::Server.new(Blog, port: (ARGV[0] || 3000).to_i).start +puts "listening on #{server.url}" +trap('INT') { server.stop; exit } +sleep diff --git a/examples/blog/config.ru b/examples/blog/config.ru new file mode 100644 index 0000000..f6ac059 --- /dev/null +++ b/examples/blog/config.ru @@ -0,0 +1,3 @@ +require_relative 'app' + +run Blog diff --git a/examples/blog/db/migrate/20260828014505_create_posts.rb b/examples/blog/db/migrate/20260828014505_create_posts.rb new file mode 100644 index 0000000..27632df --- /dev/null +++ b/examples/blog/db/migrate/20260828014505_create_posts.rb @@ -0,0 +1,13 @@ +class CreatePosts < Prism::Orm::Migration + def up + create_table :posts do |t| + t.string :title + t.text :body + t.timestamps + end + end + + def down + drop_table :posts + end +end