Slide 1

Slide 1 text

Rails

Slide 2

Slide 2 text

࠷ॳʹ

Slide 3

Slide 3 text

Rails νϡʔτϦΞϧ1 ΍Ζ͏ ͱ͍͏ͷΛ·͓͍֮ͣ͑ͯͯ(࠷ޙʹ΋ݴ͏͚Ͳ) 1 http://railstutorial.jp/

Slide 4

Slide 4 text

Կނ͔ 1. ࠓ೔͚ͩͰ৭ʑͳ͜ͱΛڭ͑·͢ɻ 2. Ұؾʹ֮͑Δͷ͸ແཧͰࣗ৴Λࣦ͏͔΋͠Ε·ͤΜɻ 3. ͔͠΋໌೔͔Β͸ Rails ࿔Γ·ͤΜɻ 4. ͱ͍͏Θ͚ͰɺRails ๨Ε͔͚ͯΔͱࢥͬͨΒ Rails νϡʔ τϦΞϧ1 Λࢥ͍ग़͢ͱྑ͍Ͱ͠ΐ͏ɻ 1 http://railstutorial.jp/

Slide 5

Slide 5 text

HTTP ʹ͍ͭͯ

Slide 6

Slide 6 text

HTTP(Hypertext Transfer Protocol) ͬ͘͟Γઆ໌ 1. αʔόͱΫϥΠΞϯτͰ΍ΓͱΓ͢Δ௨৴ϓϩτίϧ 2. hypertext ͱ͔ݴͬͯΔ͚ͲόΠφϦ΋ૹͬͯΔͷͰؾʹ ͠ͳ͍Ͱ͓̺ 3. ϒϥ΢βɺΞϓϦͱαʔόͰ΍ΓͱΓ͢Δن֨Ͱ͢

Slide 7

Slide 7 text

HTTP(Hypertext Transfer Protocol) ͸·ΓͲ͜Ζ 1. εςʔτϨεͳϓϩτίϧͰ͢ 2. ௨৴Λ։࢝ग़དྷΔͷ͸ΫϥΠΞϯτ͔ΒͷΈͰ͢

Slide 8

Slide 8 text

1. εςʔτϨεͳϓϩτίϧͰ͢ ঢ়ଶΛ࣋ͪ·ͤΜ…… ͱ͔ݴΘΕͯ΋Θ͔Γʹ͍͘ͱࢥ͏ͷ Ͱ

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

2. ௨৴Λ։࢝Ͱ͖Δͷ͸ΫϥΠΞ ϯτ͔ΒͷΈͰ͢ 1. ͳͷͰ push ௨஌ͳͲ͸ग़དྷ·ͤΜ 2. push ௨஌ͬΆ͍෺Λ΍ΔͨΊʹ͸৭ʑେมʢServer Sent Events ͱ͔ௐ΂Δͱ৭ʑग़ͯ͘Δʣ

Slide 11

Slide 11 text

HTTP(Hypertext Transfer Protocol) ৮ͬͯΈ·͠ΐ͏ $ telnet cookpad.com 80 Trying 54.65.132.171... Connected to cookpad.com. Escape character is '^]'. ͦͷ··ԼهͷΑ͏ʹଧͬͯΈ·͢ɻ GET / HTTP/1.1 Host: cookpad.com ͦͷޙɺReturn key Λೋճԡ͠·͢ɻ ͩΒʙ ͬͱΫοΫύουͷσʔλ͕औಘग़དྷ·ͨ͠ɻ

Slide 12

Slide 12 text

HTTP(Hypertext Transfer Protocol) 4 1ߦ໨ʢϦΫΤετߦʣ 4 GETʢHTTP ϝιουʣ 4 / (Path) 4 HTTP/1.1 ʢϓϩτίϧ໊ʣ 4 ೋߦ໨Ҏ߱ʢϝοηʔδϔομʣ 4 Host: cookpad.comʢϗετϔ ομʣ

Slide 13

Slide 13 text

HTTP(Hypertext Transfer Protocol) Path ෦෼Λม͑ͯΈ·͠ΐ͏ GET /search HTTP/1.1 Host: cookpad.com ऴྃ͸ Ctrl + ] Λ͓ͨ͠ޙʹ quit ͱίϚϯυΛଧͯ͹ग़དྷ· ͢ɻ

Slide 14

Slide 14 text

HTTP(Hypertext Transfer Protocol) HTTP ϝιου෦෼Λม͑ͯΈ·͠ΐ͏ HEAD /search HTTP/1.1 Host: cookpad.com ಉ͡ Path Ͱ΋ GET ͷ࣌ͱ͸ҧ͏΋ͷ͕ฦ͖ͬͯ·ͨ͠ɻ

Slide 15

Slide 15 text

REST ࢥ૝ʹ͍ͭͯ

Slide 16

Slide 16 text

REST ࢥ૝ʹ͍ͭͯ ͬ͘͟Γઆ໌ 4 ૢ࡞ͷର৅ͱͳΔϦιʔεΛ URL Ͱදݱ͢Δ 4 ͦΕʹ HTTP ͷϝιουΛ࢖ͬͯૢ࡞͢Δ

Slide 17

Slide 17 text

REST ࢥ૝ʹ͍ͭͯ ྫ͑͹ /items/5 ͱ͍͏ URL ͕Ұͭͷ item Λද͍ͯͯ͠ 4 HTTP ϝιουͷ GET ͰΞΫηε͢Δͱͦͷ item ͕औಘ Ͱ͖Δ 4 HTTP ϝιουͷ PATCH ͰΞΫηε͢Δͱͦͷ item ͷ৘ ใΛߋ৽Ͱ͖Δ 4 HTTP ϝιουͷ DELETE ͰΞΫηε͢Δͱͦͷ item Λ ࡟আͰ͖Δ

Slide 18

Slide 18 text

REST ࢥ૝ʹ͍ͭͯ ಉ͡Α͏ʹ /items ͱ͍͏ URL ͸ item ͷू߹Λද͍ͯ͠ΔͷͰ 4 HTTP ϝιουͷ GET ͰΞΫηε͢Δͱ item ͷू߹ʢҰ ཡʣ͕औಘͰ͖Δ 4 ྫ͑͹ /items/1, /items/2, /items/3, /items/4 …… ౳ 4 HTTP ϝιουͷ POST ͰΞΫηε͢Δͱ item ͷू߹ʹ৽͠ ͍ item Λ௥Ճ͢Δ ͱ͍͏;͏ʹͳΓ·͢

Slide 19

Slide 19 text

Rails

Slide 20

Slide 20 text

Rails ͷ MVC ੌ͘୯७ʹॲཧΛॻ͘ͱ…… 4 controllerʢͱ routesʣ ͸Ϣʔβʔ͔ΒͷೖྗΛݩʹ model Λऔಘ͠ɺview ʹ౉͠·͢ 4 view ͸౉͞Εͨ model Λදࣔ͠·͢ ͱ͍͏ಈ͖Λ͠·͢ɻ୯७Ͱ͢Ͷɻ

Slide 21

Slide 21 text

ͬͦ͘͞ Rails ΞϓϦΛ࡞Γ·͠ΐ ͏ ࠓճ࡞ΔΞϓϦ͸ը૾ͷ URL Λ౤ߘͯ͠ΈΜͳͰͦͷը૾ʹίϝϯτ͕ ग़དྷΔΞϓϦέʔγϣϯʹͳΓ·͢ɻ ͖͞΄Ͳͷ REST తʹݴ͏ͱϦιʔε͸ 4 ը૾ͷ URL 4 ը૾ͷ URL ʹର͢Δίϝϯτ ͷ 2 ͭʹͳΓ·͢ɻ

Slide 22

Slide 22 text

ͬͦ͘͞࡞Γ͸͡Ί·͠ΐ͏ $ rails new bokete -T Ͱ Rails ΞϓϦͷͻͳܗ͕ग़དྷ·͢ɻ $ cd bokete ͯͦ͠ͷσΟϨΫτϦʹೖΓ·͢ɻ ࠓޙ͸͜ͷσΟϨΫτϦΛΞϓϦέʔγϣϯͷ HOME ͱͯ͠ ѻ͍جຊతʹ͸͜͜ͰίϚϯυΛ࣮ߦ͠·͢ɻ

Slide 23

Slide 23 text

Bundler ৭ʑͳϥΠϒϥϦΛूத؅ཧͯ͘͠ΕΔ΋ͷͰ͢ɻ ·ͣ͸ Rspec ͱ haml Λ௥Ճ͠·͢ɻ Gemfile ʹԼهΛ௥ه͠·͢ gem "haml-rails", "~> 0.9" gem 'rspec-rails', '~> 3.0', group: [:development, :test]

Slide 24

Slide 24 text

haml Խ Gemfile هࡌޙɺԼهΛ࣮ߦ͠·͢ $ bundle install ͜ΕͰϥΠϒϥϦͷΠϯετʔϧ͕ऴΘΓ·ͨ͠ɻ ࣍ʹςϯϓϨʔτΛ haml ʹ౷Ұ͠·͢ (ݩʑ͸ ERB ͩͬͨ΋ͷΛ haml ʹίϯόʔτ͠·͢) $ rails generate haml:application_layout convert $ rm app/views/layouts/application.html.erb

Slide 25

Slide 25 text

Ұ୴֬ೝ $ rails server Λ࣮ߦ͠ɺىಈΛ֬ೝͰ͖ͨΒ http://localhost:3000 ʹΞΫηεͯ͠Έ·͠ΐ͏ɻ

Slide 26

Slide 26 text

RSpec ४උ $ rails generate rspec:install Ͱ rspec ͷॳظԽΛߦ͍·͢ $ bundle exec rspec Ͱ GREEN Λ֬ೝͨ͠Β commit ͓͖ͯ͠·͠ΐ͏ $ git init $ git add . $ git commit -m "init"

Slide 27

Slide 27 text

image Ϟσϧ࡞੒

Slide 28

Slide 28 text

image Ϟσϧ࡞੒ ը૾ URL ͱ λΠτϧΛอ࣋͢ΔϞσϧΛ࡞੒͠·͢ɻ $ rails generate model image url:string title:string invoke active_record create db/migrate/xxxxxxxxxxx_create_images.rb create app/models/image.rb invoke rspec create spec/models/image_spec.rb DB ͷߏ଄Λมߋ͢Δ migration ϑΝΠϧͱϓϩάϥϛϯά͔Β DB ͷσʔλΛૢ࡞͢ΔϞσϧ͕࡞੒͞Ε·ͨ͠ɻ

Slide 29

Slide 29 text

image Ϟσϧ࡞੒ DB ఆٛ ઌͣ͸ DB ͷߏ଄Λมߋ͢Δ migration ϑΝΠϧΛ࿔Γ·͢ db/migrate/xxxxxxxxxxxcreateimages.rb Λ։͖ url ͱ title ΧϥϜΛ NOT_NULL ʹ͠·͢ class CreateImages < ActiveRecord::Migration def change create_table :images do |t| t.string :url, null: false # ௥Ճ t.string :title, null: false # ௥Ճ t.timestamps null: false end end end

Slide 30

Slide 30 text

image Ϟσϧ࡞੒ DB ఆٛ ࣮ࡍʹσʔλϕʔεʹ migration ϑΝΠϧΛ൓ө͠·͢ɻ ࠓճ͸ςετ༻ͷ DB ʹ൓өͤ͞·͢ $ bin/rake db:migrate RAILS_ENV=test rspec ࣮ߦͯ͠Έ·͠ΐ͏ $ bundle exec rspec pending ʹͳΓ·͢Ͷʢmodel Կ΋࣮૷͍ͯ͠ͳ͍ͷͰʣ

Slide 31

Slide 31 text

image Ϟσϧ࡞੒ όϦσʔγϣϯ ͬͦ͘͞ model Λ࣮૷͍͖ͯ͠·͠ΐ͏ɻDB ͷ੍໿ΛϰΝϦσʔγϣϯ͠·͢ɻ require 'rails_helper' RSpec.describe Image, type: :model do describe "validation" do describe "url" do let(:no_url_image) { Image.new(url: nil, title: "title") } it "require url" do expect(no_url_image).to_not be_valid expect(no_url_image.errors[:url]).to_not be_empty end end end end rspec Λ࣮ߦ͢Δͱ੺͘ͳΓ·͢Ͷ

Slide 32

Slide 32 text

image Ϟσϧ࡞੒ όϦσʔγϣϯ valid Ͱ͸ͳ͍͜ͱΛظ଴ͨ͠ͷʹ valid ͩͬͨͱݴΘΕ·͢Ͷɻ validation Λ model ʹ௥Ճ͠ valid Ͱ͸ແ͘͠·͠ΐ͏ɻ class Image < ActiveRecord::Base validates :url, presence: true end ಉ͡Α͏ʹ title ͷ ϰΝϦσʔγϣϯ΋࣮૷͠·͠ΐ͏ɻ rspec Λ࣮ߦ͢͠΂ͯ௨Δ͜ͱΛ֬ೝͯ͠ίϛοτ͠·͢ɻ $ git add . $ git commit -m "Add image model"

Slide 33

Slide 33 text

Image ίϯτϩʔϥʔ࡞੒ ͬͦ͘͞࡞ͬͨϞσϧΛදࣔ͢ΔػೳΛ࡞Γ·͢ɻ Images Λѻ͏ ImagesController Λ࡞੒͠·͢ɻ app/controllers/images_controller.rb class ImagesController < ApplicationController end

Slide 34

Slide 34 text

Image ίϯτϩʔϥʔ࡞੒ Spec ΋༻ҙ͠·͢ spec/controllers/images_controller_spec.rb require 'rails_helper' RSpec.describe ImagesController, type: :controller do describe "#index" do it "assigns @images" do get :index expect(assigns(:images)).to_not be_nil end end end ςετͷ಺༰ͷઆ໌͸ޙ΄Ͳ͠·͢ͷͰͱΓ࣮͋͑ͣߦͯ͠Έ·͠ΐ͏

Slide 35

Slide 35 text

routes ͱ resources Failure/Error: get :index ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"images"} images ͱ͍͏ controller ͷ index ͍ͬͯ͏ action ʹϚον ͢Δ route ͕ແ͍ΑͱݴΘΕ·͢ɻ

Slide 36

Slide 36 text

routes ͱ resources config/routes.rb ͱ͍͏ϑΝΠϧʹԼهΛ͔͍ͯΈ·͢ Rails.application.routes.draw do resources :images end ͪΐͬͱલʹઆ໌ͨ͠ʮREST ࢥ૝ʹ͍ͭͯʯΛࢥ͍ग़͍ͯͩ͘͠͞ 4 ૢ࡞ͷର৅ͱͳΔϦιʔεΛ URL Ͱදݱ͢Δ 4 ͦΕʹ HTTP ͷϝιουΛ࢖ͬͯૢ࡞͢Δ routes ʹ images ͱ͍͏ϦιʔεΛૢ࡞͢Δͱઃఆͨ͠Θ͚Ͱ͢ɻ

Slide 37

Slide 37 text

routes ͱ resources $ rake routes Prefix Verb URI Pattern Controller#Action images GET /images(.:format) images#index POST /images(.:format) images#create new_image GET /images/new(.:format) images#new edit_image GET /images/:id/edit(.:format) images#edit image GET /images/:id(.:format) images#show PATCH /images/:id(.:format) images#update PUT /images/:id(.:format) images#update DELETE /images/:id(.:format) images#destroy Ͳͷ HTTP ϝιουͰͲͷ URL ʹɺΞΫηε͢ΔͱɺͲͷ Controller ͷɺͲͷ Action ͕ݺ͹ΕΔͷ͔ग़͖ͯ·ͨ͠ɻ

Slide 38

Slide 38 text

routes ͱ resources spec Ͱ֬ೝ͍ͯ͠Δͷ͸ GET ϝιουͰ index ʹΞΫηε͢Δͷ΋Ͱͨ͠ɻ ͜Ε͸ URI Pattern ͱͯ͠͸ /images ʹͳΓ·͢ɻ ͜Ε͸ઌఔͷʮREST ࢥ૝ʹ͍ͭͯʯͰݴ͏ͱ 4 HTTP ϝιουͷ GET ͰΞΫηε͢Δͱ item ͷू߹ʢҰཡʣ͕औಘͰ͖ Δ 4 ྫ͑͹ /items/1, /items/2, /items/3, /items/4 …… ౳ ʹͳΓ·͢ɻ Ͱ͸ɺroute Λઃఆͨ͠ͷͰ rspec Λ࣮ߦͯ͠Έ·͠ΐ͏ɻ

Slide 39

Slide 39 text

Image ίϯτϩʔϥʔ࡞੒ Failure/Error: get :index AbstractController::ActionNotFound: The action 'index' could not be found for ImagesController ImagesController ʹ index ΞΫγϣϯ͕ແ͍ͱݴΘΕ·ͨ͠ɻ ௥Ճ͠·͠ΐ͏ class ImagesController < ApplicationController def index end end rspec Λ࣮ߦͯ͠Έ·͠ΐ͏ɻ

Slide 40

Slide 40 text

Image ίϯτϩʔϥʔ࡞੒ Failure/Error: get :index ActionView::MissingTemplate: Missing template images/index, application/index with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml, :jbuilder]}. Searched in: * "#" ࠓ౓͸ Template ͕ແ͍ͱݴΘΕ·ͨ͠ app/views/images/index.html.haml ͱ͍͏ϑΝΠϧΛ࡞Γ ·͢ rspec Λ࣮ߦͯ͠Έ·͠ΐ͏ɻ

Slide 41

Slide 41 text

Image ίϯτϩʔϥʔ࡞੒ Failure/Error: expect(assigns(:images)).to_not be_nil expected: not nil got: nil ࠓ౓͸ ͳʹ΍Β not nil Λظ଴͍ͯ͠Δͷʹ nil ͩͱݴΘΕ·ͨ͠ɻ ͯ͞ɺઌ΄Ͳͷ spec Ͱ͕͢ get :index expect(assigns(:images)).to_not be_nil GET ϝιουͰ index ʹΞΫηεͨ͠Β imagesʢimage ͷू߹ʣ͕ΞαΠ ϯ͞Ε͍ͯΔ͜ͱΛ֬ೝ͍ͯ͠·ͨ͠ɻ

Slide 42

Slide 42 text

Image ίϯτϩʔϥʔ࡞੒ Ͱ͸࣮ࡍʹΞαΠϯͯ͠Έ·͠ΐ͏ class ImagesController < ApplicationController def index @images = Image.all end end rspec Λ࣮ߦͯ͠Έ·͠ΐ͏ɻ͢΂ͯ௨Γ·͢Ͷɻ

Slide 43

Slide 43 text

index view ࡞੒ ςετ͕͢΂ͯ௨ͬͨͷͰ࣮ࡍʹ֬ೝͯ͠Έ·͢ɻ ·ͣ͸։ൃ؀ڥͷ DB ΛηοτΞοϓ͠ىಈͯ͠Έ·͢ɻ $ bin/rake db:migrate RAILS_ENV=development $ rails server http://localhost:3000/images/ ʹΞΫηεͯ͠Έ·͠ΐ͏ɻ

Slide 44

Slide 44 text

index view ࡞੒ ·ͩ view ΛԿ΋࡞͍ͬͯͳ͍ͷͰදࣔ͞Εͳ͍ͷ͸౰ͨΓલͰ͢Ͷɻ ·ͣ͸ app/views/images/index.html.haml ʹ %h1 ը૾Ұཡ ͱɺॻ͍ͯϦϩʔυͯ͠Έ·͠ΐ͏ɻ

Slide 45

Slide 45 text

index view ࡞੒ haml ʹ͍ͭͯ ͬ͘͟Γ 4 html tag ߏ଄Λ YAML ͬΆ͘දͨ͠ςϯϓϨʔτΤϯδϯ 4 % Ͱී௨ʹλά -> %ul 4 - Ͱ ruby ͷߏจ -> - @images.each do |image| 4 = Ͱ ग़ྗ -> = image.title

Slide 46

Slide 46 text

index view ࡞੒ Image ͕Ұͭ΋σʔλϕʔεʹొ࿥͍ͯ͠ͳ͍ͷͰͦ΋ͦ΋Ұཡʹ΋ग़͢͜ͱ͕ग़དྷ·ͤΜɻ ొ࿥ͯ͠Έ·͠ΐ͏ɻ $ rails console Loading development environment (Rails 4.2.2) irb(main):001:0> Image.create!(url: "http://i.giphy.com/I6l7Kwu0GLvAA.gif", title: "starwars") index.html.haml ʹදࣔ෦෼Λ௥Ճ͠·͢ %h1 ը૾Ұཡ %dl - @images.each do |image| %dt= image.title %dd= image_tag image.url Ϧϩʔυ͢Δͱදࣔ͞Ε·͢

Slide 47

Slide 47 text

controller ͱ view ͞Βͬͱ͓͞Β͍ routes ແ͍Α -> action ແ͍Α -> ςϯϓϨʔτແ͍Α -> ม਺Ξ αΠϯ͞Εͯͳ͍Α spec Λॻ͍͓ͯ͘͜ͱʹΑΓɺ࣮ߦΛ͢Δͨͼʹ΍Δ΂͖͜ͱΛ ڭ͑ͯ΋Β͍ͳ͕ΒҰาͮͭਐΊ·ͨ͠ɻ ͦͯ͠Τϥʔ͕ແ͘ͳͬͨΒ view Λ࣮૷͠·ͨ͠ɻ ࠓճ͸ view ͸ςετΛॻ͔ͣʹ໨Ͱ֬ೝ͠ͳ͕Β࣮૷͠·ͨ͠ɻ ͜͜ͰҰ୴ίϛοτ͓͖ͯ͠·͠ΐ͏ɻ

Slide 48

Slide 48 text

image ొ࿥ը໘ جૅ͸આ໌ͨ͠ͷͰ͘͘͞͞ߦ͖·͢ spec/controllers/images_controller_spec.rb ʹొ࿥ը໘ͷ spec Λ௥Ճ͠·͢ɻ describe "#new" do it "assigns @image" do get :new expect(assigns(:image)).to_not be_nil end end spec ௨͢ͱ new ΞΫγϣϯ͕ແ͍ͱݴΘΕ·͢

Slide 49

Slide 49 text

image ొ࿥ը໘ def new @image = Image.new end view ͕ແ͍ͱݴΘΕ·͢

Slide 50

Slide 50 text

image ొ࿥ը໘ app/views/images/new.html.haml spec ͕௨ΔΑ͏ʹͳΔͷͰ࣮ࡍͷ view Λॻ͖·͢ = form_for @image do |f| = f.label :title = f.text_field :title = f.label :url = f.text_field :url = f.submit http://localhost:3000/images/new Λ։͍ͯΈ·͢

Slide 51

Slide 51 text

image ొ࿥ը໘ REST తʹ new ͷ֓೦͸ແ͍ͷͰݴ༿Ͱઆ໌͢Δͷ΋೉͍͠ͷ Ͱઌʹ࣮૷ΛਐΊͯΈ·ͨ͠ɻ ຊ౰ʹλΠτϧͷ௨Γొ࿥ը໘Ͱ͢Ͷɻ ͜ͷը໘Ͱೖྗͨ͠΋ͷͰ࣮ࡍʹొ࿥Λ͢ΔͨΊͷॲཧΛݺͼ ग़͠·͢ɻ Ұ୴ίίͰίϛοτ͠·͠ΐ͏ɻ

Slide 52

Slide 52 text

form_for ʹ͍ͭͯ = form_for @image do |f| form_for ͸Ҿ਺ʹ౉͞Ε͍ͯΔΦϒδΣΫτʹΑͬͯݺͼग़͠ઌΛม͑ͯ͘Ε·͢ɻ ྫ͑͹ @image ͕ DB ʹطʹอଘ͞Ε͍ͯͨΒ PUT /images/:id(.:format) images#update ͕ݺ͹Εɺ·ͩอଘ͞Ε͍ͯͳ͍৔߹͸ POST /images(.:format) images#create ͕ݺ͹Ε·͢ɻ

Slide 53

Slide 53 text

form_for ʹ͍ͭͯ ͭ·Γ Controller Ͱ @image = Image.new ͱ͖ͯͬ͠͞ͷ view Λදࣔͨ࣌͠͸৽نొ࿥ @image = Image.find(params[:id]) ͱ͖ͬ͞ͷ view Λදࣔͨ࣌͠͸طଘσʔλͷฤूʹͳΔΑ͏ ʹࣗಈతʹݺͼग़͠ઌΛม͑ͯ͘Ε·͢

Slide 54

Slide 54 text

image ৽نొ࿥ ࣮ࡍʹσʔλΛొ࿥͢Δ෦෼Λ࡞੒͠·͠ΐ͏ spec/controllers/images_controller_spec.rb ʹ৽نొ࿥ͷ spec Λ௥Ճ͠·͢ɻ describe "#create" do it "create new image" do expect { post :create, image: { url: "http://example.com/", title: "test" } }.to change { Image.count }.from(0).to(1) end end ࠓճ͸࣮ࡍʹొ࿥͞Εͯݸ਺͕ 0 -> 1 ʹͳ͍ͬͯΔ͜ͱΛ֬ೝ͍ͯ͠·͢ spec ௨͢ͱ create ΞΫγϣϯ͕ແ͍ͱݴΘΕ·͢

Slide 55

Slide 55 text

image ৽نొ࿥ def create Image.create(params.require(:image).permit(:url, :title)) end spec ௨͢ͱ view ͕ແ͍ͱݴΘΕ·͢

Slide 56

Slide 56 text

image ৽نొ࿥ ొ࿥׬ྃը໘Λग़͢ͷͰ΋ྑ͍Ͱ͕͢ࠓճ͸ొ࿥͕੒ޭͨ͠Β ҰཡϖʔδʹભҠ͢ΔΑ͏ʹ͠·͠ΐ͏ def create Image.create(params.require(:image).permit(:url, :title)) redirect_to action: :index end http://localhost:3000/images/new Λ։͍ͯొ࿥Ͱ͖Δ͜ ͱΛ֬ೝͰ͖ͨΒίϛοτ͠·͠ΐ͏

Slide 57

Slide 57 text

ొ࿥ը໘΁ͷϦϯΫ app/views/images/index.html.haml ʹԼهΛ௥Ճ͠·͢ɻ = link_to "ը૾Λ౤ߘ͢Δ", new_image_path ઌ΄Ͳ࣮ߦͨ͠ rake routes Ͱग़͖ͯͨ prefix ʹ _path Λ ͚ͭΔͱͦ͜΁ͷ path ʹͳΓ·͢ɻ ͳͷͰࠓճ͸ new_image_path ʹͳΓ·͢ɻ ·ͨίϛοτ͠·͢ɻ

Slide 58

Slide 58 text

ը૾ݸผϖʔδ spec/controllers/images_controller_spec.rb describe "#show" do let(:image) { Image.create(url: "http://example.com/", title: "test") } it "assigns @image" do get :show, id: image.id expect(assigns(:image)).to eq image end end ͬ͘͞Γ rspec ࣮ߦͯ͠ action ແ͍ͱݴΘΕ·͢ɻ

Slide 59

Slide 59 text

ը૾ݸผϖʔδ def show @image = Image.find(params[:id]) end spec ௨͢ͱ view ͕ແ͍ͱݴΘΕ·͢

Slide 60

Slide 60 text

ը૾ݸผϖʔδ app/views/images/show.html.haml %h1= @image.title = image_tag @image.url app/views/images/index.html.haml ΋ͪΐͬͱม͑·͢ %dd = link_to image do = image_tag image.url ಈ࡞֬ೝ͕Ͱ͖ͨΒίϛοτ͠·͢ɻ

Slide 61

Slide 61 text

ը૾࡟আ spec/controllers/images_controller_spec.rb describe "destroy" do let!(:image) { Image.create(url: "http://example.com/", title: "test") } it "destroy image" do expect { delete :destroy, id: image.id }.to change { Image.count }.from(1).to(0) end end ͬ͘͞Γ rspec ࣮ߦͯ͠ action ແ͍ͱݴΘΕ……

Slide 62

Slide 62 text

ը૾࡟আ def destroy Image.find(params[:id]).destroy redirect_to action: :index end ࡟আޙ΋ index ΁ߦ͘Α͏ʹ͠·͢ spec ͕௨Δ͜ͱΛ֬ೝ͠·͢ɻ

Slide 63

Slide 63 text

ը૾࡟আ app/views/images/show.html.haml ʹ࡟আ༻ͷϦϯΫΛ௥ Ճ͠·͢ %h1= @image.title = image_tag @image.url = link_to "࡟আ", @image, method: :delete ಈ࡞֬ೝ͠ίϛοτ͠·͢ɻ

Slide 64

Slide 64 text

github ΁ push 1. New repository ΛΫϦοΫ͠৽͍͠ repository Λ࡞Γ·͢ 2. repository name ͸ ࣗ෼ͷ໊લ -rails-app ʹ͍ͯͩ͘͠͞ɻ 1. ԶͳΒ yoshiori-shoji-rails-app ޙ͸खॱ௨Γ git remote add origin git@xxxx:yoshiori/yoshiori-shoji-rails-app.git git push -u origin master Ͱ͢ɻʢϦϩʔυͯ͠Έ·͠ΐ͏ʣ

Slide 65

Slide 65 text

github ͔Β clone ࣍ͷ։ൃ͸ PR ΛૹͬͯΈ·͢ 1. ྡͷਓͱϖΞΛ૊ΜͰ͍ͩ͘͞ 2. ͦͷਓͷΞϓϦΛ git clone ͠·͢ 3. bundle install & bin/rake db:migrate ͠·͢ ͊͞ɺࠓ͔Β͸ίνϥΛ࿔Γ·͢ɻ

Slide 66

Slide 66 text

branch ࣍͸ը૾ʹίϝϯτΛ෇͚ΔػೳΛ࡞͍͖ͬͯ·͢ɻ ৽͍͠ػೳͰ͢ͷͰϒϥϯνΛ࡞ͬͯ࡞ۀ͠·͠ΐ͏ɻ $ git checkout -b add_images_comment $ git branch * add_images_comment master ࣗ෼͕ͲͷϒϥϯνʹډΔ͔֬ೝ͓͖ͯ͠·͠ΐ͏ ʢ͍͍ͩͨͷਓ͕λʔϛφϧʹ΋ΤσΟλʹ΋ग़ΔΑ͏ʹ͠·͢ʣ

Slide 67

Slide 67 text

ίϝϯτ model ͷ࡞੒ ίϝϯτϞσϧΛ࡞੒͠·͢ɻ ࠓճ͸ը૾ʹԿݸ΋ίϝϯτΛ෇͚ΒΕΔΑ͏ʹ͢ΔͷͰҰରଟͷؔ࿈ͱͯ͠ද͠·͢ $ rails generate model comment image:references body:text class CreateComments < ActiveRecord::Migration def change create_table :comments do |t| t.references :image, index: true, foreign_key: true, null: false t.text :body, null: false t.timestamps null: false end end end body ΧϥϜΛ NOT_NULL ʹ͠·͢

Slide 68

Slide 68 text

ίϝϯτ model ͷ࡞੒ ͬ͘͞ͱόϦσʔγϣϯΛ࣮૷͍͖ͯ͠·͠ΐ͏ require 'rails_helper' RSpec.describe Comment, type: :model do describe "validation" do let(:image) { Image.create(url: "http://example.com/", title: "test") } describe "body" do subject(:no_body_comment) { image.comments.build(body: nil) } it "require" do expect(no_body_comment).to_not be_valid expect(no_body_comment.errors[:body].size).to be 1 end end end end

Slide 69

Slide 69 text

ίϝϯτ model ͷ࡞੒ DB ʹมߋ͕͋ͬͨͷͰ $ bin/rake db:migrate RAILS_ENV=test Λ࣮ߦ͔ͯ͠Β spec Λ࣮ߦ͢Δͱམͪ·͢ɻ Failure/Error: subject(:no_body_comment) { image.comments.build(body: nil) } NoMethodError: undefined method `comments' for # # ./spec/models/comment_spec.rb:8:in `block (4 levels) in

Slide 70

Slide 70 text

ϦϨʔγϣϯγοϓ ϞσϧͦΕͧΕʹؔ࿈৘ใΛ࣋ͨͤ·͢ class Image < ActiveRecord::Base validates :url, presence: true validates :title, presence: true + has_many :comments end class Comment < ActiveRecord::Base belongs_to :image end ͜ΕͰ Image ͱ Comment ΛҰରଟͱͯؔ͠࿈෇͚ΒΕ·ͨ͠ɻ

Slide 71

Slide 71 text

ϦϨʔγϣϯγοϓ ͜ΕͰ image.comments.build ͱ࣮ߦ͢Δͱ image ʹؔ࿈ͮ ͍ͨ Comment Λ৽͘͠࡞੒͢Δ͜ͱ͕ग़དྷ·͢ɻ ࣮ࡍ͸Լهॲཧ͸΄΅ಉͩ͡ͱࢥͬͯ΋Βͬͯେৎ෉Ͱ͢ > image.comments.build(body: "test") > Comment.new(image_id: image.id, body: "test")

Slide 72

Slide 72 text

ίϝϯτ model ͷ࡞੒ ͯ͞ɺspec ʹ໭͖ͬͯ·͢ class Comment < ActiveRecord::Base validates :body, presence: true belongs_to :image end

Slide 73

Slide 73 text

ίϝϯτ model ͷ࡞੒ ؔ࿈΋ςετ͓͖ͯ͠·͠ΐ͏ describe "image_id" do context "empty" do subject(:no_image_id_comment) { Comment.new(image_id: nil, body: "body") } it "invalid" do expect(no_image_id_comment).to_not be_valid expect(no_image_id_comment.errors[:image].size).to be 1 end end context "illegal id" do subject(:illegal_image_id_comment) { Comment.new(image_id: image.id + 1, body: "body") } it "invalid" do expect(illegal_image_id_comment).to_not be_valid expect(illegal_image_id_comment.errors[:image].size).to be 1 end end end

Slide 74

Slide 74 text

ίϝϯτ model ͷ࡞੒ class Comment < ActiveRecord::Base validates :body, presence: true validates :image, presence: true belongs_to :image end spec ͕௨Δ͜ͱΛ֬ೝͯ͠ίϛοτ͠·͢ɻ

Slide 75

Slide 75 text

ίϝϯτ౤ߘ spec/controllers/comments_controller_spec.rb require 'rails_helper' RSpec.describe CommentsController, type: :controller do let(:image) { Image.create(url: "http://example.com/", title: "text") } describe "#create" do it "create new comment" do expect { post :create, image_id: image.id, comment: { body: "ίϝϯτ" } }.to change { Comment.count }.from(0).to(1) end end end

Slide 76

Slide 76 text

ίϝϯτ౤ߘ app/controllers/comments_controller.rb class CommentsController < ApplicationController end spec ࣮ߦ͢Δͱ·ͨ route ͕ઃఆ͞Ε͍ͯͳ͍ͱݴΘΕ· ͢ɻ

Slide 77

Slide 77 text

ؔ࿈ resources ͷઃఆ ࠓճ͸ը૾ʹෳ਺ίϝϯτΛ෇͚ΒΕΔΑ͏ʹ͠·͢ɻ ͭ·Γɺը૾ 1 ʹ͍ͭͨίϝϯτҰཡΛද͢ path ͸ /images/1/comments ʹͳͬͯཉ͍͠Ͱ͢Ͷɻ

Slide 78

Slide 78 text

ؔ࿈ resources ͷઃఆ ͜ΕΛ routes Ͱද͢ͱ resources :images do resources :comments end ͱද͠·͢ɻ rake routes ͯ͠ URI ͕௥Ճ͞Ε͍ͯΔ͜ͱΛ֬ೝͯ͠Έ· ͠ΐ͏

Slide 79

Slide 79 text

ίϝϯτ౤ߘ ࣮ࡍͷ create ΞΫγϣϯΛ࣮૷͠·͢ class CommentsController < ApplicationController def create image = Image.find(params[:image_id]) image.comments.create(params.require(:comment).permit(:body)) redirect_to image_path(image) end end image Λऔಘͯͦ͠Εʹؔ࿈͢ΔίϝϯτΛ৽͘͠࡞੒͠·͢ɻ ׬ྃͨ͠Β image ͷݸผϖʔδʹભҠ͢ΔΑ͏ʹ͠·ͨ͠ɻ spec ͕௨Δ͜ͱΛ֬ೝ͠·͠ΐ͏

Slide 80

Slide 80 text

ίϝϯτ౤ߘ ίϝϯτ౤ߘ͸ը૾ϖʔδ͔Β͍ͨ͠ͷͰը૾ϖʔδʹ form Λ௥Ճ͠·͢ app/views/images/show.html.haml %h2 ίϝϯτ %ul - @image.comments.each do |comment| %li = comment.body = form_for [@image, Comment.new] do |f| = f.text_field :body = f.submit form_for ΁ͷ౉͠ํ͕ͪΐͬͱบ͕͋ΔͷͰ஫ҙͰ͢

Slide 81

Slide 81 text

ίϝϯτ౤ߘ $ bin/rake db:migrate ͨ͠ޙʹ http://localhost:3000/images/1 ʹΞΫηε͠ಈ࡞֬ೝΛͯ͠໰୊͕ͳ͔ͬͨΒίϛοτ͠· ͢ɻ

Slide 82

Slide 82 text

Pull request Ͱ͸࣮૷ͨ͠ίϝϯτػೳΛϓϧϦΫΤετͱͯ͠ग़ͯ͠Έ·͢ɻ 1. ͖ͬ͞ͷ clone ͨ͠ϦϙδτϦͷϖʔδͰ fork ϘλϯΛԡ͢ 2. fork ͨ͠ url Ͱ git remote add mine #{url} ͢Δ 3. git push mine add_images_comment 4. fork ͨ͠ϖʔδΛ։͖ϓϧϦΫΤετϘλϯΛԡ͢ ऴΘͬͨΒٯʹࣗ෼ͷϦϙδτϦ΁͖ͨ PR ΛϚʔδ͠·͠ΐ͏ ࣗ෼ͷϓϩδΣΫτͷσΟϨΫτϦʹ໭Γ git pull origin master ͠ɺઌ΄ͲϚʔδͨ͠΋ͷ͕ϩʔΧϧʹ൓ө͞ΕͨͷΛ֬ೝ ͠·͠ΐ͏ɻ

Slide 83

Slide 83 text

API Խ

Slide 84

Slide 84 text

API Խ ࠓ͔Β json API Λ࡞͍͖ͬͯ·͠ΐ͏ɻ ·ͣ͸؆୯ʹ JSON ͷ spec Λॻ͚Δ rspec-json_matcher Λಋೖ͠·͢ɻ Gemfile ʹ gem "rspec-json_matcher", group: :test Λ଍͠ bundle install ͠·͢

Slide 85

Slide 85 text

API Խ spec/spec_helper.rb ʹԼهΛ଍͠·͢ require "rspec/json_matcher" RSpec.configuration.include RSpec::JsonMatcher

Slide 86

Slide 86 text

API Խ rake routes ͨ࣌͠ͷදࣔ images GET /images(.:format) images#index ͜͜ͷ URI Pattern ͷඞͣޙΖʹ෇͍͍ͯΔ (.:format) ͕ΩϞͰ͢ɻ Ͳ͏͍͏͜ͱ͔ͱ͍͏ͱ http://localhost:3000/images ʹΞΫηε͢Δͱී ௨ʹ html ͕ฦ͖ͬͯ·͕͢ɺhttp://localhost:3000/images.json ͱ֦ு ࢠ෩ʹ format Λࢦఆͯ͠ΞΫηε͢Δͱ json ͕ฦͬͯ͘ΔΑ͏ʹग़དྷ·͢3ɻ 3 format ͷࢦఆͷ࢓ํ͸ଞʹ΋͋Γ·͢

Slide 87

Slide 87 text

API Խ Ͱ͸ͬͦ͘͞ spec Ͱ͢ɻࠓճ͸ json ͕ฦͬͯ͘Δ͜ͱ͕େࣄͳͷͰ request spec Λॻ͖·͢ɻ spec/requests/images_spec.rb Λ࡞Γ·͢ require "rails_helper" RSpec.describe Image, type: :request do let!(:image) { Image.create(url: "http://example.com/", title: "test") } describe "GET /images.json" do it "return json" do get "/images.json" expect(response.body).to be_json( images: [ id: image.id, title: "test", url: "http://example.com/", ], ) end end end

Slide 88

Slide 88 text

API Խ spec Λ࣮ߦͯ͠ΈΔͱ·ͨςϯϓϨʔτ͕ແ͍ͱݴΘΕ·͕͢Α͘ݟΔͱ formats ͸ json ʹͳ͍ͬͯ·͢ɻࠓճ͸ rails ඪ४ͷ jbuilder Ͱॻ͍ͯ Έ·͢ app/views/images/index.json.jbuilder Λ࡞Γ·͢ json.images @images, :id, :title, :url spec Λ࣮ߦ͠௨Δ͜ͱΛ֬ೝͨ͠Βϒϥ΢βͰ΋ http://localhost: 3000/images.json Λ։͍ͯ֬ೝͯ͠Έ·͠ΐ͏ɻ ໰୊ͳ͚Ε͹ίϛοτ͠·͢ɻ

Slide 89

Slide 89 text

API Խ ͜ͷ·· show ΋࣮૷ͯ͠Έ·͠ΐ͏ describe "GET /images/:id.json" do let!(:comment) { image.comments.create!(body: "test") } it "return json" do get "/images/#{image.id}.json" expect(response.body).to be_json( id: image.id, title: "test", url: "http://example.com/", comments: [ { id: comment.id, body: "test", }, ], ) end end

Slide 90

Slide 90 text

API Խ app/views/images/show.json.jbuilder json.(@image, :id, :title, :url) json.comments @image.comments, :id, :body spec Λ࣮ߦ͠௨Δ͜ͱΛ֬ೝͨ͠Βϒϥ΢βͰ΋ http:// localhost:3000/images/1.json Λ։͍ͯ֬ೝͯ͠Έ·͠ΐ ͏ɻ ໰୊ͳ͚Ε͹ίϛοτ͠·͢ɻ

Slide 91

Slide 91 text

API Խ ౤ߘ΋࡞͍͖ͬͯ·͠ΐ͏ describe "POST /images.json" do it "create images" do post "/images.json", image: { url: "http://example.com", title: "test" } expect(response.status).to be 201 end end spec Λ࣮ߦͯ͠Έ·͠ΐ͏ 302(ϦμΠϨΫτʣ͕ฦ͖ͬͯͯ͠·͍·͠ ͨͶɻ͔֬ϒϥ΢βͰͷಈ࡞͸౤ߘޙɺindex ϖʔδͰϦμΠϨΫτ͢ΔΑ ͏ʹ͍ͯ͠·ͨ͠ɻAPI ͷ࣌͸ͦΕ͸ෆཁͰ͢Ͷɻࠓճ͸ 201 ͚ͩฦͬͯ͘ ΔΑ͏ʹ͠·͢ɻ

Slide 92

Slide 92 text

API Խ def create Image.create!(params.require(:image).permit(:title, :url)) respond_to do |format| format.html { redirect_to action: :index } format.json { head 201 } end end ͜ͷΑ͏ʹ format ʹΑͬͯॲཧΛ෼͚Δ͜ͱ͕ग़དྷ·͢ɻ

Slide 93

Slide 93 text

API Խ ࣮ࡍʹίϚϯυϥΠϯ͔Β֬ೝͯ͠Έ·͠ΐ͏ $ curl -X POST -d "image[url]=http://example.com/&image[title]=test" http://localhost:3000/images.json rails ͷϩάΛݟΔͱ෼͔ΔͷͰ͕͢ Can't verify CSRF token authenticity CSRF token ͕ແ͍ͨΊ஄͔Ε͍ͯ·͢ɻ

Slide 94

Slide 94 text

API Խ ຊདྷͳΒ͹ API ͸ Controller Λ෼͚ͯผͷೝূʢOAuth ౳ʣʹ͠· ͕͢ɺͪΐͬͱॏ͗͢ΔͷͰࠓճ͸ CSRF token ͷνΣοΫΛແޮʹ ͠·͢ɻʢઈରʹ࣮ࡍͷ։ൃͰߦͬͯ͸͍͚·ͤΜʣ app/conrtollers/apprication_controller.rb ͷԼهΛॻ͖׵͑· ͢ - protect_from_forgery with: :exception + protect_from_forgery with: :null_session ΋͏Ұ౓ίϚϯυϥΠϯ͔Βୟ͍ͯΈͯ໰୊ͳ͚Ε͹ίϛοτ͠·͢

Slide 95

Slide 95 text

API Խ ίϝϯτ΋౤ߘͰ͖ΔΑ͏ʹ͠·͢ spec/requests/comments_spec.rb require "rails_helper" RSpec.describe Comment, type: :request do let(:image) { Image.create(url: "http://example.com/", title: "test") } describe "POST /images/:id/comments.json" do it "create comments" do post "/images/#{image.id}/comments.json", comment: { body: "test" } expect(response.status).to be 201 end end end

Slide 96

Slide 96 text

API Խ app/conrtollers/comments_controller.rb class CommentsController < ApplicationController def create image = Image.find(params[:image_id]) image.comments.create(params.require(:comment).permit(:body)) respond_to do |format| format.html { redirect_to image_path(image) } format.json { head 201 } end end end spec ͕௨Δ͜ͱΛ֬ೝͨ͠Βίϛοτ͠·͠ΐ͏

Slide 97

Slide 97 text

root ઃఆ root ΁ͷΞΫηε΋ը૾Ұཡʹ͠·͢ config/routes.rb ʹԼهΛ௥Ճ͠·͢ root "images#index" ๨Εͣʹίϛοτ͓͖ͯ͠·͠ΐ͏

Slide 98

Slide 98 text

heroku ΁

Slide 99

Slide 99 text

heroku ΁ Gemfile Λগ͠मਖ਼͠·͢ 1. sqlite3 Λ group :development, :test ϒϩοΫͷத΁Ҡ ಈ 2. ԼهΛ௥Ճ group :production do gem 'rails_12factor' gem 'pg' end

Slide 100

Slide 100 text

heroku ΁ $ bundle install ͯ͠ίϛοτ $ heroku create $ git push heroku master $ heroku run rake db:migrate $ heroku open ֬ೝͯ͠Έ·͠ΐ͏

Slide 101

Slide 101 text

͕࣌ؒ͋ͬͨΒௐ΂ͯΈΑ͏ʂ ࠓ೔͸࣌ؒͷؔ܎Ͱࡉ͔͘આ໌Ͱ͖ͳ͔ͬͨ΋ͷͰ͢ɻ 4 HTTP 4 REST 4 MVC 4 RDB 4 OAuth 4 CSRF

Slide 102

Slide 102 text

࠷ޙʹ

Slide 103

Slide 103 text

Rails νϡʔτϦΞϧ1 ΍Ζ͏ 1. ࠷ॳཧղͰ͖ͳͯ͘΋ 3 ճҐ΍Δͱ͍ͩͿ֮͑Δ 2. Web ։ൃͲ͏΍Μ͚ͩͬͬͯࢥͬͨ࣌ͱ͔ʹ͞Βͬͱ΍Δ ͱ·ͨࢥ͍ग़ͤΔ 1 http://railstutorial.jp/