Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Trailblazerの紹介

kbaba1001
September 20, 2015

 Trailblazerの紹介

kbaba1001

September 20, 2015
Tweet

More Decks by kbaba1001

Other Decks in Programming

Transcript

  1. Trailblazer
    Trailblazer
    @kbaba1001
    Powered by Rabbit 2.1.6 and COZMIXNG

    View Slide

  2. 自己紹介
    kbaba1001
    Ruby on Rails

    View Slide

  3. 最近
    Rails をやめたいという話をたまに
    聞く気がする

    View Slide

  4. Railsのあるある
    規模が大きくなるとメンテナンス
    がつらい

    View Slide

  5. つらみ
    Fat Model
    ビジネスロジックのある
    Controller
    カオス partial

    View Slide

  6. つらみ…
    default_scope
    nested_attributes_for
    validation を if オプションで切
    り替え
    Rails Engine 使う gem の拡張

    View Slide

  7. では Rails をやめるべきな
    のか?
    別の言語(Go、Scala、Elixir)
    別のFW(padrino、lotus)
    先駆者になる(Trailblazer)

    View Slide

  8. Trailblazer
    https://leanpub.com/trailblazer

    View Slide

  9. 何?
    A new architecture for Rails.

    View Slide

  10. A new architecture

    View Slide

  11. A Concept-Driven OOP
    Framework
    app
    ├── concepts
    │ ├── comment
    │ │ ├── views
    │ │ │ ├── show.haml
    │ │ │ ├── list.haml
    │ │ ├── assets
    │ │ │ ├── comment.css.sass
    │ │ ├── cell.rb
    │ │ ├── operation.rb
    │ │ ├── twin.rb

    View Slide

  12. Trailblazer の特徴
    ビジネスロジックをMVCから分
    離して concepts 以下にまとめ

    MVCを疎結合にしてメンテナン
    ス性の向上する
    テストしやすくする

    View Slide

  13. MVC
    Modelにはassociationとscope
    だけ
    Viewはconcept毎にViewModel
    として分割
    ControllerにはHTTPエンドポイ
    ントとしてのロジックだけ

    View Slide

  14. ビジネスロジック
    CRUD
    validation/callback
    Viewのためのロジック
    Worker

    View Slide

  15. Model
    class Thing < ActiveRecord::Base
    has_many :comments, -> { order(created_at: :desc) }
    has_many :users, through: :authorships
    has_many :authorships
    scope :latest, lambda { all.limit(9).order("id DESC") }
    end

    View Slide

  16. Controller
    class ThingsController < ApplicationController
    def create
    run Thing::Create do |op|
    return redirect_to(thing_path op.model) # success.
    end
    render :new # re-render form.
    end

    View Slide

  17. View
    .comments
    = concept("comment/cell", collection: comments)

    View Slide

  18. Trailblazer
    Operation
    Cell

    View Slide

  19. Operation
    class Thing < ActiveRecord::Base
    class Create < Trailblazer::Operation
    include CRUD
    model Thing, :create
    contract do
    property :name
    property :description
    validates :name, presence: true
    validates :description, length: {in: 4..160}, allow_blank: true
    end
    def process(params)
    validate(params[:thing]) do |f|
    f.save
    end
    end
    end

    View Slide

  20. Controller
    class ThingsController < ApplicationController
    def create
    run Thing::Create do |op|
    return redirect_to(thing_path op.model) # success.
    end
    render :new # re-render form.
    end

    View Slide

  21. View
    普通のview
    cells

    View Slide

  22. cells
    ViewModel
    メソッドとassetsのあるpartial

    View Slide

  23. Viewからcellを呼び出す
    .comments
    = concept("comment/cell", collection: comments)

    View Slide

  24. cell
    # app/concepts/comment/cell.rb
    class Comment::Cell < Cell::Concept
    property :body
    property :author
    def show
    render
    end
    private
    def author_link
    link_to "#{author.email}", author
    end
    end

    View Slide

  25. cellのview
    # app/concepts/comment/views/show.erb
    %h3 New Comment
    %p= body
    %p= author_link

    View Slide

  26. テスト
    Operation、cellのテストを行うこ
    とでfeature、requestテストを減
    らす

    View Slide

  27. Operation Test
    it "persists valid" do
    thing = Thing::Create[
    thing: {
    name: "Rails",
    description: "Kickass web dev"
    }
    ].model
    thing.persisted?.must_equal true
    thing.name.must_equal "Rails"
    thing.description.must_equal "Kickass web dev"
    end

    View Slide

  28. Cell の Test
    class CommentCellTest < Cell::TestCase
    controller ThingsController
    it do
    html = concept("comment/cell")
    html = Capybara.string(html)
    comments = html.all(:css, ".comment")
    first = comments[0]
    comments[0].find(".header").must_have_content "[email protected]"
    comments[0].find(".header time")["datetime"].must_match /\d\d-/

    View Slide

  29. その他
    callback
    worker
    json

    View Slide

  30. 詳しくは
    https://leanpub.com/trailblazer
    Powered by Rabbit 2.1.6 and COZMIXNG

    View Slide