パーフェクトRuby

パーフェクトRuby

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

最後、16章。

Sinatra 使ったことなかったので新鮮。
bootstrap のバージョンが違うので、そのままだとだめ。

  • ./lib/views/layout.haml
!!!
%html
  %head
    %meta(charset='utf-8')
    %title Todo Application
    %link(href='/css/bootstrap.min.css' rel='stylesheet' type='text/css')
    %link(href='/css/bootstrap-theme.min.css' rel='stylesheet' type='text/css')
  %body
    .navbar.navbar-default
      .container-fluid
        .navbar-header
          %a.navbar-brand(href='/tasks') Todo Application

        %ul.nav.navbar-nav
          %li{ class: ('active' unless @status) }
            %a(href='/tasks') ALL Tasks
          %li{ class: ('active' if @status == 'not_yet') }
            %a(href='/tasks?status=not_yet') NOT YET Tasks
          %li{ class: ('active' if @status == 'pending') }
            %a(href='/tasks?status=pending') PENDING Tasks
          %li{ class: ('active' if @status == 'done') }
            %a(href='/tasks?status=done') DONE Tasks

    .container
      != yield
  • lib/views/index.haml
%h1 Listing Tasks

%div
  %a(href='/tasks/new') New

%table.table.table-striped.table-hover.table-bordered
  %thead
    %tr
      %th ID
      %th Name
      %th Content
      %th Status
      %th Created Time
      %th{ colspan: 2 } Action
  %tbody
    - @tasks.each do |task|
      %tr
        %td= task.id
        %td= task.name
        %td= task.content
        %td= task.status
        %td= task.created_at.strftime("%Y/%m/%d %H:%M:%S")
        %td
          %a{ href: "/tasks/#{task.id}/edit" } Edit
        %td
          %form.form-inline(method='post'){ action: "/tasks/#{task.id}" }
            %input(name='_method' type='hidden' value='delete')
            %input.btn.btn-danger(type='submit' value='Delete' onclick='return confirm("Delete Task?")')
  • lib/views/new.haml
%h1 New Task

!= haml :_errors, locals: { task: @task }

%form.form-horizontal(method='post' action='/tasks')
  != haml :_form, locals: { task: @task }
  .form-group
    .col-sm-offset-2.col-sm-3
      %input.btn.btn-primary(name='commit' type='submit' value='Create')
  • lib/views/edit.haml
%h1 Editing Task

!= haml :_errors, locals: { task: @task }

%form.form-horizontal(method='post' action='/tasks/#{@task.id}')
  != haml :_form, locals: { task: @task }
  .form-group
    .col-sm-offset-2.col-sm-3
      %input.btn.btn-warning(name='commit' type='submit' value='Update')
      %input(name='_method' type='hidden' value='put')
  • lib/views/_form.haml
.form-group{ class: error_class(task, :name)}
  %label.col-sm-2.control-label(for='task_name') Name
  .col-sm-3
    %input#task_name.form-control(name='name' placeholder='例:買い物' type='text'){ value: task.name }
.form-group{ class: error_class(task, :content)}
  %label.col-sm-2.control-label(for='task_content') Content
  .col-sm-5
    %input#task_name.col-sm-5.form-control(name='content' placeholder='例:牛乳を買う' type='text'){ value: task.content }
- if task.persisted?
  .form-group
    %label.col-sm-2.control-label(for='task_status') Status
    .col-sm-3
      %select#task_status.form-control{ name: :status }
        != options_for_task_status(task)
  • lib/views/_errors.haml
- if task.errors.any?
  .alert.alert-danger
    %ul
      - task.errors.full_messages.each do |msg|
        %li= msg
  • lib/application.rb
require 'sinatra/base'
require 'haml'

require './lib/todo/db'
require './lib/todo/task'

module Todo
  class Application < Sinatra::Base
    use Rack::MethodOverride

    set :haml, escape_html: true

    helpers do
      def error_class(task, name)
        task.errors.has_key?(name) ? 'has-error' : ''
      end

      def options_for_task_status(task)
        Task.statuses.map { |key, _|
          selected = (key == task.status) ? ' selected' : ''
          %(<option value="#{key}"#{selected}>#{key.upcase}</option>)
        }.join
      end
    end

    configure do
      DB.prepare
    end

    get '/' do
      redirect '/tasks'
    end

    get '/tasks' do
      @tasks = Task.all

      if @status = params[:status]
        case @status
        when 'not_yet'
          @tasks = Task.not_yet
        when 'pending'
          @tasks = Task.pending
        when 'done'
          @tasks = Task.done
        else
          @status = nil
        end
      end

      haml :index
    end

    get '/tasks/new' do
      @task = Task.new

      haml :new
    end

    post '/tasks' do
      begin
        Task.create!(name: params[:name], content: params[:content])

        redirect '/'
      rescue ActiveRecord::RecordInvalid => e
        @task = e.record

        haml :new
      end
    end

    get '/tasks/:id/edit' do
      begin
        @task = Task.find(params[:id])

        haml :edit

      rescue ActiveRecord::RecordNotFound
        error 404
      end
    end

    put '/tasks/:id' do
      begin
        task = Task.find(params[:id])
        task.update(
          name: params[:name],
          content: params[:content],
          status: params[:status]
        )

        redirect '/'
      rescue ActiveRecord::RecordInvalid => e
        @task = e.record

        haml :edit
      rescue ActiveRecord::RecordNotFound
        error 404
      end
    end

    delete '/tasks/:id' do
      begin
        task = Task.find(params[:id])
        task.destroy

        redirect '/'
      rescue ActiveRecord::RecordNotFound
        error 404
      end
    end

    not_found do
      haml :not_found
    end
  end
end

f:id:yossk:20150519001046j:plain

f:id:yossk:20150519001058j:plain

f:id:yossk:20150519001105j:plain

f:id:yossk:20150519001116j:plain