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

cookpad-17day-tech-internship-2017-rails

 cookpad-17day-tech-internship-2017-rails

クックパッド17day技術インターンシップの前半、Railsへんの講義資料です

MOROHASHI Kyosuke

August 31, 2017
Tweet

More Decks by MOROHASHI Kyosuke

Other Decks in Programming

Transcript

  1. 

  2. [0]$ telnet cookpad.com 80 Trying 54.199.213.92... Connected to cookpad.com. Escape

    character is '^]'. GET / HTTP/1.1 Host: cookpad.com HTTP/1.1 301 Moved Permanently Content-Type: text/html; charset=iso-8859-1 Date: Wed, 22 Feb 2017 07:29:24 GMT Location: https://cookpad.com/ Server: Apache Content-Length: 228 Connection: keep-alive <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title>  )551
  3. ‣ HTTP/1.1 ‣ ௨৴͢ΔHTTPͷόʔδϣϯΛද͢ɻ޿͘࢖ΘΕ͍ͯΔͷ͸1.1 ‣ ݱ୅తͳ໰୊Λղܾ͢ΔͨΊHTTP/2΋ग़͖ͯͨ ‣ GET / HTTP/1.1

    ͷߦΛʮϦΫΤετϥΠϯʯͱݺͿ ‣ Host: cookpad.com ‣ 1αʔόͰෳ਺αʔϏεΛӡ༻Ͱ͖ΔͨΊɺ࿦ཧతʹͲͷαʔϏε΁ͷϦΫΤετͰ͋Δ͔Λࣔ͢ඞཁ͕ ͋Δ ‣ ۭߦ ‣ ϦΫΤετ͕ऴΘͬͨ΋ͷͱͯ͠αʔόͷॲཧ͕࢝·Δ ͦͷଞͷՕॴ 
  4. ‣ ඇಉظॲཧɺόονॲཧ ‣ JavaScript͘Θ͘͠ ‣ CSS͘Θ͘͠ ‣ RDBMSҎ֎ͷσʔλετΞ ‣ WebΞϓϦΛಈ͔͢Πϯϑϥ


    (Ϋϥ΢υɺεέʔϧΞ΢τɺίϯςφԽ) ͜ͷηογϣϯͰ΍Βͳ͍͜ͱ ཁࣗशPS͋ͱͰ࣭໰ͯ͠ 
  5. 

  6. 

  7. $ git clone https://ghe.example.com/<your name>/memo2.git $ cd memo2 $ bundle

    install $ (brew services start postgresql) $ ./bin/rails db:create $ ./bin/rails db:migrate $ ./bin/rails s -p 3000 $ open http://localhost:3000/memos 3BJMTΞϓϦέʔγϣϯΛىಈ͠Α͏ ‣ Ͳ͏ͳ͍ͬͯΔ͔ɺϒϥ΢βͰݟͯΈ·͠ΐ͏ 
  8. --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,4 @@ Rails.application.routes.draw do

    + resources :memos # For details on the DSL available within this file, see http://guides.rubyon routing.html end 3BJMT͸3&45ͱ͍͏ߟ͑ํʹ΋ͱ͍͍ͮͯΔ ‣ 3&QSFTFOUBUJPOBM4UBUF5SBOTGFS ‣ )551ϝιου Ͳ͏͍ͨ͠ ͱύε ΫΤϦ ͳʹΛ Λͱ͍͏૊Έ߹ΘͤΛɺ
 Ϧιʔε΁ͷૢ࡞ɺͱͯ͠ந৅Խ͠ɺΞʔΩςΫνϟͷத৺ʹஔ͘ߟ͑ํ ‣ ͦͷϦιʔε΁ͷૢ࡞Λ΋ͬͯɺΞϓϦέʔγϣϯͷॲཧΛ࣮ݱ͢Δɻ ‣ ࠓճ͸ɺѻ͏ϝϞNFNPΛɺͦͷ··Ϧιʔεͱͨ͠ɻ 
  9. $ ./bin/rails routes
 Prefix Verb URI Pattern Controller#Action memos GET

    /memos(.:format) memos#index POST /memos(.:format) memos#create new_memo GET /memos/new(.:format) memos#new edit_memo GET /memos/:id/edit(.:format) memos#edit memo GET /memos/:id(.:format) memos#show PATCH /memos/:id(.:format) memos#update PUT /memos/:id(.:format) memos#update DELETE /memos/:id(.:format) memos#destroy resources :memosͰఆٛ͞ΕΔૢ࡞ ‣ ෳ਺औಘɺ୯਺औಘɺ࡞੒ɺߋ৽ɺ࡟আ ‣ ࡞੒ɺߋ৽ͷͨΊͷϑΥʔϜΛؚΉը໘΋Ϧιʔεͱߟ͑ΒΕΔ ‣ /memos͕ϝϞͷू߹Λද͠ɺͦͷू߹Λऔಘ (&5 ͢Δ͜ͱΛ΋ͬͯɺ
 ʮϒϥ΢β্ʹϝϞΛҰཡදࣔʯͱ͍͏ΞϓϦέʔγϣϯͷॲཧΛදݱͨ͠ɻ 
  10. ‣ POST /groups/42/add_member ‣ ϘσΟͰ person_id = 4Λࢦఆ͠ɺάϧʔϓͷ add_member ॲཧΛݺͼग़͢

    ‣ POST /groups/42/memberships ‣ ϘσΟͰ person_id = 4Λࢦఆ͠ɺ"άϧʔϓʹࢀՃ ͍ͯ͠Δ͜ͱ"(membership)Λ࡞੒͢Δ ༨ஊ Ϧιʔε͸Ϟϊ͚ͩͰͳ͍ 
  11. +++ b/app/controllers/items_controller.rb @@ -0,0 +1,74 @@ +class MemosController < ApplicationController

    + before_action :set_memo, only: [:show, :edit, :update, :destroy] + + # GET /memos + # GET /memos.json + def index + @memos = Memo.all + end + *UFNT$POUSPMMFSJOEFY ‣ ϧʔςΟϯά͔Βݺ͹ΕΔͱ͖͸ANFNPTJOEFYAදه ‣ .FNP͸3BJMTඪ४ͷ03.ɺ"DUJWF3FDPSE#BTFΛܧঝͨ͠Ϋϥεɻ ‣ .FNPBMMͰɺNFNPTςʔϒϧͷશϨίʔυΛಡΈࠐΈɺ
 !NFNPTʹೖΕΔ 
  12. ‣ ϑϨʔϜϫʔΫͷಈ͖Λ͢΂ͯઃఆ͢Δ(configuration)͢ΔͷͰͳ͘ɺ
 Rails͕૝ఆ͢Δن໿(convention)ʹԊͬͯಈ͘ɻ ‣ ARΫϥεMemo͸ memos ςʔϒϧͷϨίʔυΛѻ͏ ‣ GET /memos͸

    MemosController#index ΛݺͼɺΞΫγϣϯॲཧޙ͸ app/ views/memos/index.html.* ͷςϯϓϨʔτΛϨϯμϦϯά͢Δ ‣ ม਺໊ͰܕΛදݱ͢ΔจԽ΋͋Δɻ ‣ Railsʹ׳ΕΔͱmemos͸ෳ਺ͷMemoΠϯελϯεΛ͋ΒΘ͢ม਺໊ͱ
 ಡΈऔΔɻ $POWFOUJPOPWFS$POpHVSBUJPO 
  13. ߟ͑ΔʮϢʔβ͝ͱϝϞʯͷσʔλߏ଄  ユーザ タイトル 内容 Alice きょうやること - インターンに参加する -

    懇親する Alice 買い出し ## 薬局 - 風邪薬 ## スーパー - 牛乳2本 - 卵があれば6つ Bob 明日の持ち物 印鑑
  14. ߟ͑ΔʮϢʔβʯͷॏෳΛݮΒ͢ /' /'  タイトル 内容 きょうやること - インターンに参加する -

    懇親する 買い出し ## 薬局 - 風邪薬 ## スーパー - 牛乳2本 - 卵があれば6つ 明日の持ち物 印鑑 ユーザ Alice Bob
  15. 3BJMT෺ཧઃܭ1, ',Λಋೖ͢Δ  id user_id タイトル 内容 1 1 きょうやること

    - インターンに参加する - 懇親する 2 1 買い出し ## 薬局 - 風邪薬 ## スーパー - 牛乳2本 - 卵があれば6つ 3 2 明日の持ち物 印鑑 id ユーザ 1 Alice 2 Bob
  16. $ ./bin/rails g model user name:string $ ./bin/rails g migration

    AddUserRefToMemos user:references $ ./bin/rails db:migrate VTFSTςʔϒϧͱɺNFNPTVTFS@JEΛ௥Ճ͢Δ 
  17. $ cat db/schema.rb create_table "memos", force: :cascade do |t| t.string

    "title" t.text "body" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "user_id" t.index ["user_id"], name: "index_memos_on_user_id", using: :btree end create_table "users", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end add_foreign_key "memos", "users" VTFSTςʔϒϧͱɺNFNPTVTFS@JEΛ௥Ճ͢Δ 
  18. ‣ ʮϝϞ͸1ਓͷϢʔβʹଐ͢Δʯ ‣ Memo belongs_to :user ‣ memos͕΋͍ͬͯΔuser_idʹΑͬͯɺଐ͢Δ1ਓͷϢʔβ Λࢀর͢Δ ‣

    ϢʔβΛࢀর͢ΔͨΊͷ#userͱ͍͏ϝιουͳͲ͕࢖͑ ΔΑ͏ʹͳΔ ଟରPSରͷʮଐ͢Δʯؔ࿈ੑ 
  19. ‣ ʮϢʔβ͸ɺෳ਺ͷϝϞΛॴ༗͍ͯ͠Δʯ ‣ User has_many :memos ‣ memos ͕΋͍ͬͯΔuser_id ʹΑͬͯɺॴ༗͢Δnݸ

    ͷϝϞΛࢀর͢Δ ‣ ෳ਺঎඼Λࢀর͢ΔͨΊͷ#memosͱ͍͏ϝιου ͳͲ͕࢖͑ΔΑ͏ʹͳΔ ରଟͷʮॴ༗͢Δʯؔ࿈ੑ 
  20. $ vim app/models/user.rb class User < ActiveRecord::Base has_many :memos end

    $ vim app/models/memo.rb class Memo < ActiveRecord::Base belongs_to :user end ؔ࿈Λઃఆ͢Δ 
  21. $ ./bin/rails console > user = User.find_by!(name: ‘alice') > user.name

    > user.memos > user.memos = Memo.all > memo = Memo.first > memo.user طଘͷϝϞ΋ಛఆͷϢʔβʹؔ࿈෇͚Δ 
  22. ‣ ʮϩάΠϯૢ࡞ʯ= ೝূͷ࣮૷͸΍Γ·ͤΜɻ
 ͍ΖΜͳ΋ͷ͕͋Δɻ ‣ Ϣʔβ໊ + ύεϫʔυ ‣ SNS

    (OAuth2 ΍ OpenID) ‣ ϫϯλΠϜύεϫʔυ+ϩάΠϯϦϯΫ ‣ SSLΫϥΠΞϯτೝূ ‣ ෺ཧσόΠε etc… ʲ஫ҙʳ͖ΐ͏΍Βͳ͍͜ͱ 
  23. ‣ େલఏ: HTTP͸ঢ়ଶΛ࣋ͨͳ͍ϓϩτίϧͰ͋Δɻ ‣ αʔόଆʹɺΫϥΠΞϯτঢ়ଶΛอ࣋Ͱ͖ͳ͍ɻ ‣ ෳ਺ฒΜͩαʔόͷͲΕʹϦΫΤετ͕ߦ͔ܾ͘ఆͰ͖ͳ͍ɻ ‣ ࣮༻తͳαʔϏεΛ࡞ΔͨΊʹ͸ɺٖࣅతʹʮঢ়ଶʯΛ
 ࣋ͨͤΔඞཁ͕͋Δɻ

    ‣ Ұ౓ϩάΠϯͨ͠Β͠͹Βͦ͘ͷਓͱͯ͠ೝূ͞Ε͍ͯΔɺͱ͔ɻ ‣ ͜ͷʮ͋Δ࣌ؒ୯ҐͰಉҰϢʔβ͕ܧଓతʹαʔϏεΛ࢖ͬ ͍ͯΔঢ়ଶʯΛηογϣϯͱݺͿɻ ηογϣϯͱ͸ 
  24. 

  25. 

  26. ‣ ίϯτϩʔϥͷ #session ͰΞΫηεͰ͖Δɻ ‣ ෳ਺ϦΫΤετΛލ͍ͰσʔλΛอ࣋Ͱ͖Δɻ ‣ ͋·Γͨ͘͞ΜͷσʔλΛೖΕͳ͍ͷ͕Rails way ‣

    ϩάΠϯϢʔβͷid΍ɺ஫จͷidͳͲ ‣ ϦΫΤετΛड͚ͨ͋ͱidͰDB͔ΒҾ͖௚ͯ͠࢖͏ RailsͰͷηογϣϯ࣮૷ 
  27.   (1) Cookie: (なし) (2) uid=42なセッション開始 (3) {uid: 42}

    をキー abcdeで保存 (4) Set-Cookie: sid=abcde (5) Cookie: sid=abcde (6) キーabcdeでセッション データを検索 (7) {uid: 42} として処理 Ұൠతͳηογϣϯͷ࣮ݱ
  28.  (1) Cookie: (なし) (2) uid=42なセッション開始 (3) Set-Cookie: {uid: 42}

    (4) Cookie: {uid: 42} (6) 署名を検証 (7) {uid: 42} として処理 RailsͷCookieετΞηογϣϯ
  29. $ vim app/views/sessions/new.html.haml = form_tag session_path, class: "form-horizontal" do .form-group

    .col-lg-offset-2.col-lg-4 %label ログインユーザ - opts = options_for_select(User.all.map {|u| [u.name, u.id] }) = select_tag :user_id, opts, class: 'form-control' .form-group .col-lg-offset-2.col-lg-10 = submit_tag 'ログインする', class: 'btn btn-primary' = link_to 'キャンセル', root_path, class: 'btn btn-default' $ vim app/controllers/sessions_controller.rb class SessionsController < ApplicationController def new end end $ open http://localhost:3000/session/new ϩάΠϯϑΥʔϜ͸TFTTJPOTOFXʹ͢Δ 
  30. ‣ (؆қ)ೝূ͢ΔΞΫγϣϯɺ `SessionsController#create`Λ࣮૷͠Α͏ ‣ ౉͞Ε͖ͯͨ user_id Ͱfindͯ͠sessionʹೖΕΔ ‣ ૣ͘ऴΘͬͨΒ: ‣

    φϏήʔγϣϯόʔʹ͜ͷϩάΠϯը໘΁ͷϦϯΫΛ͚ͭΑ͏ɻ ‣ RailsΨΠυͷηΩϡϦςΟ߲ΛಡΈɺηογϣϯݻఆ߈ܸʹֶ͍ͭͯ΅͏ ‣ ϩάΞ΢τͰ͖ΔΑ͏ʹ͠Α͏ ࣮श3: 20෼ 
  31. class SessionsController < ApplicationController def new end def create user

    = User.find_by(id: params[:user_id]) if user reset_session session[:user_id] = user.id redirect_to root_path, notice: 'Login successed' else redirect_to root_path, alert: 'Login failed' end end end ճ౴ྫ 
  32. ‣ ϩάΠϯதͷϢʔβΛը໘ʹදࣔ͠Α͏ ‣ session[:user_id]ͰҾ͖ɺίϯτϩʔϥͷΠϯελϯεม਺ʹೖΕΔ or ΞΫηαϝιουΛ࡞Ζ͏ ‣ ׳ྫͩͱ current_user ͱ͍͏໊લ

    ‣ Railsίϯτϩʔϥͷ helper_method એݴΛௐ΂ͯΈΑ͏ ‣ શίϯτϩʔϥͰ࢖͏ͨΊʹ ApplicaitionController ʹఆٛ͠Α͏ ‣ ը໘ͷͲ͔͜Ͱදࣔ͠Α͏ ‣ ૣ͘ऴΘͬͨΒ: ‣ ϩάΠϯঢ়ଶΛ൑ఆ͢ΔϝιουΛ࡞Ζ͏ ‣ φϏήʔγϣϯόʔͷϩάΠϯϦϯΫΛɺϩάΠϯத͸ϩάΞ΢τϦϯΫʹ͠Α͏ ࣮श4: 30෼ 
  33. class ApplicationController < ActionController::Base protect_from_forgery with: :exception helper_method :logged_in?, :current_user

    private def logged_in? current_user.present? end def current_user if session[:user_id] @current_user ||= User.find(session[:user_id]) end end end ճ౴ྫϝιουԽͯ͠ 
  34. %ul.nav.navbar-nav.navbar-right - if logged_in? %li %p.navbar-text Hello %strong= current_user.name %li=

    link_to "ログアウト", session_path, method: :delete - else %li= link_to "ログイン", new_session_path .container ճ౴ྫϏϡʔͰදࣔͰ͖ΔΑ͏ʹͨ͠ 
  35. ‣ ActiveRecordͰ User has_many memos ؔ࿈͕͋Δͱ ‣ user.memos ͰϢʔβʹؔ࿈͍ͮͨϝϞΛҾ͚Δ ‣

    user.memos.create! ͰϢʔβʹؔ࿈͍ͮͨϝϞΛ
 ࡞ΕΔ Ϣʔβ͝ͱʹϝϞΛ࡞Ζ͏ 
  36. ‣ (ERਤ) secret_memos belongs_to memos ‣ uuid ‣ expires_at ‣

    … ‣ ଟॏ౓Ͳ͏͢ΔɺফͤΔ?… %#ઃܭ