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

ApplicationModel のある風景 / Rails with ApplicationModel

hshimoyama
December 08, 2018

ApplicationModel のある風景 / Rails with ApplicationModel

Railsdm 2018 Day4 Nouvelle Vague section B [15:50-16:10 ]

Rails アプリケーションの成長に伴い、単一の ActiveRecord モデルにロジックを記述するのに不都合が出てきます。今回、それらの問題を『緩やかに』解消するための ApplicationModel 層の導入・活用方法と、既存のアプローチとの簡単な比較をご紹介出来ればと思います。

hshimoyama

December 08, 2018
Tweet

Other Decks in Programming

Transcript

  1. ApplicationModel

    ͷ͋Δ෩ܠ
    Hiroyasu Shimoyama

    Web engineer at giftee inc.

    [email protected]_h_s_

    View Slide

  2. Overview
    • ApplicationModel ಋೖͷഎܠͱϞνϕʔγϣϯ

    • ApplicationModel ૚ͷ঺հ

    • طଘͷΞϓϩʔνͱͷൺֱ

    View Slide

  3. Rails ͷϓϩμΫτ։ൃ
    • ॳΊ͸γϯϓϧ

    • ঃʑʹෳࡶʹ

    • ෳࡶ͞ͱͲ͏޲͖߹͍͔ͬͯ͘ʁ

    View Slide

  4. ෳࡶ͞
    • ආ͚ΒΕΔෳࡶ͞ͱɺආ͚ΒΕͳ͍ෳࡶ͞

    • ݻ༗ͷෳࡶ͞ͱɺҰൠతͳෳࡶ͞

    • ੔ཧ͞Εͨෳࡶ͞ͱɺແடংͳෳࡶ͞

    • ༧ଌՄೳͳෳࡶ͞ͱɺ༧ଌࠔ೉ͳෳࡶ͞

    View Slide

  5. Rails ͷϨʔϧ
    • Rails ͷෳࡶ͞Λཧղ͢Δ͜ͱͰ

    • ආ͚ΒΕΔෳࡶ͞Λආ͚Δ

    • Ұൠతͳෳࡶ͞Λղܾ͢Δ

    • ෳࡶ͞Λ੔ཧͯ͠ίϯτϩʔϧ͢Δ

    • ༧ଌՄೳʹ͢Δ

    View Slide

  6. Rails MVC

    View Slide

  7. γϯϓϧͳੈք
    • 1 Model

    • 1 View

    • 1 Controller

    View Slide

  8. C M
    V

    View Slide

  9. routes ΍ DB table Λߟ͑Δ
    • 1 Model

    • 1 DB table

    • 1 View

    • 1 Controller

    • 1 REST resource

    View Slide

  10. C M
    V
    T
    R

    View Slide

  11. গ͠ෳࡶͳੈք
    • ಉҰͷσʔλΛҟͳΔϦιʔεͱͯ͠ݟͤΔ

    • ҟͳΔ REST resource

    View Slide

  12. C
    M
    V
    T
    R
    C’
    V’
    R’

    View Slide

  13. ΋͏গ͠ෳࡶͳੈք
    • ϦιʔεΛҟͳΔίϯςΩετͰݟΔ

    • ؅ཧը໘ / API / etc.

    • namespace

    View Slide

  14. R C
    V
    R’ C’
    V’
    R C
    V
    Customer::
    M T
    Admin::

    View Slide

  15. ΋ͬͱෳࡶͳੈք
    • ݱ࣮͸ΑΓݫ͘͠ɺෳࡶʹͳΔҰํ

    • ݟͤํ͕૿͑Δ : Ϧιʔεͷ૿Ճ

    • ༻్͕૿͑Δ : ίϯςΩετͷ૿Ճ

    View Slide

  16. R
    Customer::
    M T
    C
    R’ C’
    R’’ C’’
    R’’’ C’’’
    R C
    R’ C’
    R’’ C’’
    R C
    R C
    Api::
    Admin::
    Etc::

    View Slide

  17. ߋʹෳࡶͳੈք
    • ͦΕͧΕ͕୲͏੹຿΋૿Ճ͍ͯ͘͠

    • ௨஌ / ඇಉظॲཧ / ֎෦APIґଘ / ঢ়ଶ؅ཧ / etc.

    • Model ͷෳࡶ͞ ++

    View Slide

  18. R
    Customer::
    M T
    C
    R’ C’
    R’’ C’’
    R’’’ C’’’
    R C
    R’ C’
    R’’ C’’
    R C
    R C
    Api::
    Admin::
    Etc::

    View Slide

  19. ୯ҰͷϞσϧʹ
    ෳࡶ͕͞ूத

    View Slide

  20. ୯ҰϞσϧͷ໰୊
    • ѻ͍͍ͨσʔλ → 1 Table (ͱͦͷؔ࿈) → 1 Model

    • σʔλΛѻ͏શͯͷෳࡶ͞ → 1 Model

    View Slide

  21. R
    Customer::
    M T
    C
    R’ C’
    R’’ C’’
    R’’’ C’’’
    R C
    R’ C’
    R’’ C’’
    R C
    R C
    Api::
    Admin::
    Etc::

    View Slide

  22. ղܾͷΞϓϩʔν
    • ϞσϧΛ෼ׂ͢Δ

    • ϩδοΫΛॻ͘ͷʹઐ೦͢ΔͨΊͷϞσϧ

    • Rails ͷϨʔϧʹ͓͍ͯ༧ଌՄೳͳ໊শ

    REST
    resource
    Controller View Model
    DB
    Table
    /users UsersController users/* User users
    /admin/users
    Admin::

    UsersController
    admin/users/*
    User

    →Admin::User
    users

    View Slide

  23. R
    Customer::
    M T
    C
    R’ C’
    R’’ C’’
    R’’’ C’’’
    R C
    R’ C’
    R’’ C’’
    R C
    R C
    Api::
    Admin::
    Etc::
    Customer::M
    Customer::M’
    Customer::M’’
    Customer::M’’’
    Api::M
    Api::M’
    Api::M’’
    Admin::M
    Etc::M

    View Slide

  24. Ͳ͏ϨʔϧʹࡌͤΔ͔
    • ʰςʔϒϧʹඥ෇͔ͳ͍Ϟσϧ૚ʱΛۃྗϨʔϧ͔Β֎Ε
    ͳ͍Α͏ʹఆٛ͠ɺͦΕΛཧղ͢Δ͜ͱͰ

    • ආ͚ΒΕΔෳࡶ͞Λආ͚Δ

    • Ұൠతͳෳࡶ͞Λղܾ͢Δ

    • ෳࡶ͞Λ੔ཧͯ͠ίϯτϩʔϧ͢Δ

    • ༧ଌՄೳʹ͢Δ

    View Slide

  25. ApplicationModel

    View Slide

  26. • Controller ͕ Model ʹظ଴͢Δڞ௨ͷৼΔ෣͍Λදݱ͢
    Δ

    • ςʔϒϧʹඥ෇͍ͨϞσϧ → ApplicationRecord

    • ςʔϒϧʹඥ෇͔ͳ͍Ϟσϧ → ApplicationModel
    ApplicationModel

    View Slide

  27. • ApplicationRecord Model Λѻ͏Α͏ʹѻ͍͍ͨ

    • Attributes

    • όϦσʔγϣϯ

    • ؔ࿈ͷදݱ

    • etc.
    ApplicationModel ʹ

    ظ଴͢Δػೳͷྫ

    View Slide

  28. • ActiveModel ϕʔε

    • gem (virtus, dry-rb, reform) ϕʔε
    ApplicationModel ͷ࣮૷

    View Slide

  29. • ○ : Rails ͷػೳͰ࣮ݱग़དྷΔ

    • × : ActiveModel::Attribute ͕ Internal API

    • × : ػೳతʹ෺଍Γͳ͍͕࣌͋Δ (ؔ࿈ (Nesting) ౳)

    • : ࣗલ࣮૷ → ݻ༗ͷෳࡶ͞ͷݩ
    ActiveModel ϕʔε
    class ApplicationModel
    include ActiveModel::Model
    include ActiveModel::Attributes
    end

    View Slide

  30. • ○ : ࡉ͔͘ΧελϚΠζग़དྷΔ

    • ○ : ػೳతʹදݱग़དྷΔ෯͕޿͍

    • × : ֤छ gem ͷ஌͕ࣝඞཁ

    • × : ApplicationRecord ͱه๏͕ҟͳΔ

    • attribute/property(reform), validation/required(dry-rb)
    gem (dry-rb, reform) ϕʔε

    View Slide

  31. • ௚ۙͷϓϩδΣΫτ͸ ActiveModel ϕʔεΛબ୒

    • ؔ࿈ = Nesting ͕ແ͍ͷ͕ݫ͍͠

    • ࣗલ࣮૷ͯ͠͠·ͬͨ෦෼͕ෛ࠴Խͯͦ͠͏

    • ݱঢ়ͲΕ΋Ұ௕Ұ୹͋Γͦ͏

    • dry-rb : ʰͲͷ gem Λ૊Έ߹Θ͔ͤͨʱ͕ෳࡶ

    • reform : Form ͱ͍͏໊෇͚ʹҾͬுΒΕΔ
    ͲΕΛબͿ΂͖͔ʁ

    View Slide

  32. • ෼ׂͨ͠ Model ΛͲ͏ DRY ʹอ͔ͭʁ

    • όϦσʔγϣϯ

    • ڞ௨ػೳ

    • ApplicationModel Model ͷ attributes ͱ
    ApplicationRecord Model ͷ attributes ͷಉظ
    TIPS

    View Slide

  33. • ڞ௨ͷόϦσʔγϣϯϧʔϧ

    • ApplicationRecord ͷ Model ʹॻ͘

    • ಛఆ༻్ͷΑΓݫີͳόϦσʔγϣϯ

    • ApplicationModel ͷ Model ʹॻ͘

    • ͦΕΒΛڞ௨Խ͢Δͱ͖͸ CustomValidator
    DRY : όϦσʔγϣϯ

    View Slide

  34. • ҎԼͷͲͪΒ͔

    • Concerns

    • ApplicationModel Model

    • ΦϓγϣφϧͳৼΔ෣͍ͷ࣌͸લऀɺ୯Ұػೳͱͯ͠੒ཱ
    ͢Δ৔߹͸ޙऀΛબ୒͢Δ͜ͱ͕ଟ͍
    DRY : ڞ௨ػೳ

    View Slide

  35. • ApplicationModel Model ͱͯ͠ड͚औΓɺvalidation ʹ໰
    ୊͕ແ͔ͬͨ࣌ɺActiveRecord Model ʹӬଓԽΛґཔ͢
    Δ

    • Ͳͷ attribute ͕Ͳͷ attribute ʹରԠ͍ͯ͠Δͷ͔ʁ

    • ͲͷλΠϛϯάͰ஋Λίϐʔ͢Δͷ͔ʁ

    • ͦΕΒΛࣗಈԽ͢Δػೳ͸༻ҙ͞Ε͍ͯΔͷ͔ʁ
    Sync : attributes

    View Slide

  36. • ActiveModel ϕʔεͷ ApplicationModel Ͱ͸ࣗલ࣮૷

    Sync : attributes
    class Admin::User < ApplicationModel
    associate :user, User, default: -> { User.new }
    attribute :name, :string, for: :user
    validates_associated :user
    def save
    sync_attributes
    return false unless valid?
    user.save
    end
    end

    View Slide

  37. Sync : attributes
    class Admin::UsersController < Admin::ApplicationController
    def new
    @admin_user = Admin::User.new
    end
    def create
    @admin_user = Admin::User.new(admin_user_create_params)
    if @admin_user.save
    redirect_to @admin_user
    else
    render :new
    end
    end
    def edit
    @admin_user = Admin::User.new(user: ::User.find(params[:id]))
    end
    def update
    @admin_user = Admin::User.new(admin_user_update_params)
    if @admin_user.save
    redirect_to @admin_user
    else
    render :edit
    end
    end
    # …
    end

    View Slide

  38. • Ϩʔϧ͔Β͋·Γ֎Ε͍ͯͳ͍ (ͱࢥ͏)

    • σʔλ͸୯Ұͷ ApplicationRecord Model Λܦ༝͢Δ

    • ActiveRecord::Attributes ͰߦͬͯΔ cast ౳ͷॲཧ͕
    ͋Ε͹ͦ͜ʹॻ͘

    • ໊෇͚౳Ͱ͋·ΓࠔΒͳ͍
    ApplicationModel ͷ

    Կ͕خ͍͠ͷ͔

    View Slide

  39. طଘͷΞϓϩʔνͱͷൺֱ
    • ApplicationRecord Model Λ෼ׂ͢Δ

    • PORO (Plane Old Ruby Object)

    • Service / Form

    • Rails MVC Λ֦ு͢Δ

    View Slide

  40. Rails MVC Model ૚ͰରԠ
    • ApplicationRecord Model Λ෼ׂ͢Δ

    • ActiveRecordͷϞσϧ͕1ͭͩͱͭΒ͍(@hanachin_)

    https://qiita.com/hanachin_/items/ba1dd93905567d88145c

    • PORO (Pure Old Ruby Object)

    • RailsͷଠͬͨϞσϧΛμΠΤοτͤ͞Δํ๏ʹ͍ͭ
    ͯ (@willnet)

    https://tech.medpeer.co.jp/entry/2017/11/08/120000

    View Slide

  41. ApplicationRecord Model
    Λ෼ׂ͢Δ
    • ActiveRecordͷϞσϧ͕1ͭͩͱͭΒ͍(@hanachin_)

    https://qiita.com/hanachin_/items/ba1dd93905567d88145c

    • ϒϩάهࣄͰݕ౼͞Ε͍ͯΔ௨Γɺඇৗʹ্ख͘work ͢
    Δ

    • ApplicationRecord Model ෼ׂͰ΋ྑ͍ͱࢥ͏

    • ʰActiveRecordҎ֎ͷ૚ͭ͘Δͱҙ֎ͱ໘౗ʱͰ΋
    ݴٴ͞Ε͍ͯΔ௨Γɺ͔֬ʹ໘౗

    View Slide

  42. ApplicationRecord Model
    Λ෼ׂ͢Δ
    • ApplicationModel ͷར఺

    • DB migration ࣌ʹ໘౗͕গͳ͍ (ignore_columns)

    • ActiveRecord::AssociationTypeMismatch ղফύζϧ
    ʹͳΒͳ͍

    • σʔλӬଓԽՕॴΛߜΕΔ

    View Slide

  43. PORO
    • RailsͷଠͬͨϞσϧΛμΠΤοτͤ͞Δํ๏ʹ͍ͭͯ (@willnet)

    https://tech.medpeer.co.jp/entry/2017/11/08/120000

    • ApplicationModel ͸ better PORO

    • Ϟσϧ૚ʹ͋ΔΫϥε͸ ApplicationRecord ΋͘͠͸
    ApplicationModel Λܧঝͨ͠ΫϥεͷΈɺͱ͍͏੤໿ʹ
    ΑΓɺϞσϧ૚ʹظ଴͢Δڞ௨ͷৼΔ෣͍Λఆ͍ٛͯ͠Δ

    • PORO ͷํ͕ࣗ༝ͳར఺΋͋ΔͷͰ͓޷ΈͰ

    View Slide

  44. Service / Form
    • Service / Form ͷྑ͍ͱ͜Ζ

    • ApplicationModel ͔Βߋʹ෼ׂ͞ΕɺϑΥʔΧε͢
    Δ੹຿͕গͳ͍

    • ੈؒతʹ͋Δఔ౓ೝ஌͞Ε͍ͯͯɺ֓೦͕ʢൺֱతʣ
    ఻ΘΓ΍͍͢

    • (ҙ֎ͱ GraphQL mutation ͱ૬ੑ͕ྑ͍ͱࢥ͏)

    View Slide

  45. Service / Form
    • Service / Form ͷͭΒ͍ͱ͜Ζ

    • ৽͍֓͠೦ͷಋೖ͕ඞཁͰϨʔϧ͔Βएׯ֎ΕΔ

    • ໊લ෇͚΍ݺͼग़͠खॱͷηΦϦʔཱ͓֬ͯ͠Βͣɺ
    ਪଌ͕೉͍͠

    • ApplicationRecord Model ෼ׂͷ߲Ͱ৮Εͨ
    ApplicationModel ͷ໘౗͞Λ Service / Form ΋౿ऻ
    ͍ͯ͠Δ

    View Slide

  46. Rails MVC Λ֦ு
    • ઃܭख๏͸ड͚ೖΕΒΕ͍ͯΔ͕ɺRails Ͱͷ࣮ݱํ๏͕
    ཱ֬͞Ε͍ͯͳ͍΋ͷ

    • Clean Architecture

    • Layered Architecture

    • Rails Ͱͷ࣮ݱํ๏ཱ͕֬͞Ε͍ͯΔ΋ͷ

    • Trailblazer

    View Slide

  47. Rails MVC Λ֦ு
    • ݸਓతʹ͸ಋೖʹ৻ॏ

    • ͜ΕΒΛಋೖ͢ΔΤϯδχΞ͸શମΛʰઃܭ͢Δʱ෦෼ʹ
    ڧΈΛ࣋ͬͨਓ͕ଟ͘ɺඞͣ͠΋ӡ༻Λಘҙͱ͍ͯ͠ͳ͍

    • Ҿ͖ܧ͙ϝϯόʔ͕ಋೖ͞Εͨઃܭख๏ʹशख़͍ͯ͠ͳ͍
    Մೳੑͷ΄͏͕ߴ͍

    • େن໛։ൃͰϝϦοτΛे෼ʹڗडग़དྷΔ͔ɺઃܭख๏ʹ͍ͭͯ
    ਂ͘शख़ͨ͠ϝϯόʔΛἧ͑ଓ͚ΒΕΔͷͰ͋Ε͹…

    • ͱʹ͔͘ɺϨʔϧ͔Βେ͖͘ҳ୤͢ΔͷͰಋೖʹʰ֮ޛʱ͕ඞཁ

    View Slide

  48. ApplicationModel 

    ΛબͿ΂͖͔ʁ
    • ٻΊΒΕΔ੹຿෼ׂͷཻ౓ͰબΜͰྑͦ͞͏

    • 1 ApplicationRecord

    • N ApplicationRecord

    • N ApplicationModel + 1 ApplicationRecord

    • N Forms + N’ Services + 1 ApplicationRecord

    • Trailblazer, Clean Architecture, Layered Architecture

    View Slide

  49. ·ͱΊ
    • ApplicationModel Λಋೖ͢Δͱɺscaffold Ͱ࡞ͬͨϞσϧ
    ͷΑ͏ʹϩδοΫهड़૚Λಋೖग़དྷ·͢

    • طଘͷΞϓϩʔνʹൺ΂ͯར఺ܽ఺͸͋Δ͚ΕͲɺϨʔϧ
    ʹԊͬͨ։ൃ͸͠΍͍͢ͱࢥ͍·͢

    • બ୒ࢶͷҰͭͱͯ͠ࢹ໺ʹ͓͍ͯ௖͚ͨΒ޾͍Ͱ͢

    View Slide

  50. “Arigato!”

    View Slide