Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahastudio/3de871a488ace6bc6f84 to your computer and use it in GitHub Desktop.
Save ahastudio/3de871a488ace6bc6f84 to your computer and use it in GitHub Desktop.

GitHub 저장소 만들기

https://github.com/new

woowahan-api-demo -> https://github.com/ahastudio/woowahan-api-demo

GitHub 저장소를 origin으로 설정하고 push하기

$ git remote add origin git@github.com:ahastudio/woowahan-api-demo.git
$ git push -u origin master

Codacy로 정적분석

https://www.codacy.com/

그냥 GitHub 계정으로 가입하고 프로젝트 추가하면 됩니다.

https://www.codacy.com/app/ahastudio/woowahan-api-demo

Coding Standard

http://www.extremeprogramming.org/rules/standards.html

Ruby Style Guide

https://github.com/dalzony/ruby-style-guide/blob/master/README-koKR.md

RuboCop

https://github.com/bbatsov/rubocop

$ gem install rubocop --no-document
$ rubocop

엄청난 고통!

빠져나갈 구멍 만들기

https://github.com/bbatsov/rubocop/blob/master/config/default.yml

https://github.com/bbatsov/rubocop/blob/master/config/enabled.yml

$ vi .rubocop.yml
Documentation:
  Enabled: false

AllCops:
  Exclude:
    - 'Gemfile'
    - 'Rakefile'
    - 'Guardfile'
    - 'config.ru'
    - 'bin/**/*'
    - 'db/**/*'
    - 'config/**/*'
$ rubocop | grep "Line is too long"
$ vi app/channels/application_cable/channel.rb
$ vi app/channels/application_cable/connection.rb
$ vi test/controllers/posts_controller_test.rb
$ vi test/test_helper.rb

혹시라도 문제가 생겼는지 확인.

$ bin/rake test

app/controllers/posts_controller.rb는 고쳐도 새로운 에러가 발생한다. 잠시 후에 개선하기로 하고 일단 다음으로 넘어간다.

"Method has too many lines" check not smart enough

$ rubocop | grep "Prefer single-quoted strings when you don't need string interpolation or special symbols"
$ vi test/controllers/posts_controller_test.rb

Vim에서 정규표현식을 이용해 문자열 바꾸기.

:%s/"/'/g

혹시라도 문제가 생겼는지 확인.

$ bin/rake test
$ rubocop | grep "Keep a blank line before and after private"
$ vi app/controllers/posts_controller.rb

혹시라도 문제가 생겼는지 확인.

$ bin/rake test
$ rubocop | grep "Inconsistent indentation detected"
$ vi app/controllers/posts_controller.rb

혹시라도 문제가 생겼는지 확인.

$ bin/rake test

Compact Style 피하기

$ rubocop | grep "Use nested module/class definitions instead of compact style"
$ vi test/test_helper.rb
module ActiveSupport
  class TestCase
    # (중략)
  end
end

혹시라도 문제가 생겼는지 확인.

$ bin/rake test

Responders

https://github.com/plataformatec/responders

$ vi Gemfile

G -> 파일 끝으로 이동 o -> 다음 줄에 추가

gem 'responders', '~> 2.0'
$ bundle
$ bin/rails generate responders:install

자동으로 추가된 코드 수정.

$ vi app/controllers/application_controller.rb
:%s/"/'/g
$ vi app/controllers/posts_controller.rb

respond_to 추가.

class PostsController < ApplicationController
  respond_to :html, :json

respond_with로 변경.

  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)
    @post.save
    respond_with(@post)
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    @post.update(post_params)
    respond_with(@post)
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post.destroy
    respond_with(@post)
  end

혹시라도 문제가 생겼는지 확인.

$ bin/rake test

모두 통과하는지 확인.

$ rubocop

Commit!

작업이 한 단계 끝났다면? Commit을 잊지 마세요.

$ git add .
$ git commit

RefactorCop으로 지켜보기

http://refactorcop.com/

https://github.com/ahastudio/woowahan-api-demo -> http://refactorcop.com/ahastudio/woowahan-api-demo

Validation 작업에 대한 확신 얻기

어떻게 해야 Validation이 올바르게 됐다고 할 수 있을까?

  1. 제목과 내용을 모두 넣는다 -> Save 성공
  2. 제목을 빼먹고 내용만 넣는다 -> Save 실패
  3. 제목만 넣고 내용을 빼먹는다 -> Save 실패
$ vi test/models/post_test.rb
require 'test_helper'

class PostTest < ActiveSupport::TestCase
  test 'create a new post' do
    post = Post.new
    post.title = '조은 글이다'
    post.body = '냉무'
    assert post.save
  end

  test 'cannot create a new post without title' do
    post = Post.new
    post.body = '냉무'
    assert_not post.save
  end

  test 'cannot create a new post without body' do
    post = Post.new
    post.title = '조은 글이다'
    assert_not post.save
  end
end
$ bin/rake test

다른 방법이 있을까?

공부할 때나, 작업할 때 항상 스스로에게 물어야 할 질문: “더 나은 다른 방법은 없을까요?”

  1. 제목과 내용을 모두 넣는다 -> Post 갯수 증가
  2. 제목을 빼먹고 내용만 넣는다 -> Post 갯수 변화 없음
  3. 제목만 넣고 내용을 빼먹는다 -> Post 갯수 변화 없음
  4. [새로운 조건] 제목과 내용 모두 빼먹는다 -> Post 갯수 변화 없음
$ vi test/models/post_test.rb
require 'test_helper'

class PostTest < ActiveSupport::TestCase
  test 'create a new post with valid attributes' do
    assert_difference -> { Post.count }, 1 do
      Post.create(title: '조은 글이다', body: '냉무')
    end
  end

  test 'cannot create a new post without title' do
    assert_no_difference -> { Post.count } do
      Post.create(title: '', body: '냉무')
    end
  end

  test 'cannot create a new post without body' do
    assert_no_difference -> { Post.count } do
      Post.create(title: '조은 글이다', body: '')
    end
  end

  test 'cannot create a new post without title and body' do
    assert_no_difference -> { Post.count } do
      Post.create(title: '', body: '')
    end
  end
end
$ bin/rake test

어떤 게 낫다고 할 수 없다. 다만, 어떻게 확신을 얻으려고 했는지 나와 남에게 설명할 수 있어야 한다.

RuboCop & Commit

$ rubocop
$ git add .
$ git commit

Git 브랜치 만들기

$ git checkout -b feature/post-api
$ git branch

브랜치 전환

$ git checkout master
$ git branch
$ git checkout feature/post-api
$ git branch

API 만들기

무엇을 만들 것인가?

  1. GET /posts.json -> 게시물 목록 얻기
  2. GET /posts/37.json -> 게시물 상세 보기

Controller 코드 생성.

$ bin/rails generate controller api/posts --no-helper --no-assets

게시물 목록 API

GET /api/posts.json

게시물 목록 얻기 작업 완료 조건

어떻게 확인할 것인가?

  1. HTTP 상태 코드는 200 = success 이다.
  2. JSON에 제목이 포함된다.
  3. JSON에 내용이 포함되지 않는다.

1번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
    end
  end
end

테스트 실행

$ bin/rake test

RESTful 경로 설정

$ vi config/routes.rb
  namespace :api do
    resources :posts, only: :index
  end

테스트 실행

$ bin/rake test

index 액션 추가

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    def index
    end
  end
end

테스트 실행

$ bin/rake test

2번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    setup do
      Post.create!(title: '제목', body: '조...조은 글이다')
    end

    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
    end
  end
end

테스트 실행

$ bin/rake test

일단 통과시키기

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    def index
      render json: { title: '제목' }
    end
  end
end

테스트 실행

$ bin/rake test

제대로 만들기

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    respond_to :json

    def index
      @posts = Post.all
      respond_with(@posts)
    end
  end
end

3번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    setup do
      Post.create!(title: '제목', body: '조...조은 글이다')
    end

    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_not_includes response.body, '조은 글이다'
    end
  end
end

테스트 실행

$ bin/rake test

Jbuilder

https://github.com/rails/jbuilder

기본으로 사용 중이다.

$ mkdir -p app/views/api/posts/
$ vi app/views/api/posts/index.json.jbuilder
json.array! @posts do |post|
  json.id post.id
  json.title post.title
end

테스트 실행

$ bin/rake test

눈으로 확인하기

$ curl http://api-demo.dev/api/posts.json

HTTPie를 쓰면 더 보기 좋다.

$ brew install httpie
$ http GET api-demo.dev/api/posts.json

RuboCop & Commit

$ rubocop
$ git add .
$ git commit

게시물 상세 API

GET /api/posts/<ID>.json

게시물 상세 보기 작업 완료 조건

어떻게 확인할 것인가?

  1. 올바른 ID를 받으면, HTTP 상태 코드는 200 = success 이다.
  2. JSON에 제목과 내용이 포함된다.
  3. 알 수 없는 ID를 받으면, HTTP 상태 코드는 404 = not found 다.

1번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    setup do
      @post = Post.create!(title: '제목', body: '조...조은 글이다')
    end

    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_not_includes response.body, '조은 글이다'
    end

    test 'GET #show' do
      get api_post_url(@post.id), params: { format: :json }
      assert_response :success
    end
  end
end

테스트 실행

$ bin/rake test

RESTful 경로 설정

$ vi config/routes.rb
  namespace :api do
    resources :posts, only: [:index, :show]
  end

테스트 실행

$ bin/rake test

show 액션 추가

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    respond_to :json

    def index
      @posts = Post.all
      respond_with(@posts)
    end

    def show
      respond_with(@post)
    end
  end
end

테스트 실행

$ bin/rake test

2번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    setup do
      @post = Post.create!(title: '제목', body: '조...조은 글이다')
    end

    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_not_includes response.body, '조은 글이다'
    end

    test 'GET #show' do
      get api_post_url(@post.id), params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_includes response.body, '조은 글이다'
    end
  end
end

테스트 실행

$ bin/rake test

찾아서 보여주기

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    respond_to :json

    def index
      @posts = Post.all
      respond_with(@posts)
    end

    def show
      @post = Post.find(params[:id])
      respond_with(@post)
    end
  end
end

테스트 실행

$ bin/rake test

Jbuilder 사용

$ vi app/views/api/posts/show.json.jbuilder
json.id @post.id
json.title @post.title
json.body @post.body
json.created_at @post.created_at

테스트 실행

$ bin/rake test

3번 테스트 작성

$ vi test/controllers/api/posts_controller_test.rb
require 'test_helper'

module Api
  class PostsControllerTest < ActionDispatch::IntegrationTest
    setup do
      @post = Post.create!(title: '제목', body: '조...조은 글이다')
    end

    test 'GET #index' do
      get api_posts_url, params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_not_includes response.body, '조은 글이다'
    end

    test 'GET #show (200)' do
      get api_post_url(@post.id), params: { format: :json }
      assert_response :success
      assert_includes response.body, '제목'
      assert_includes response.body, '조은 글이다'
    end

    test 'GET #show (404)' do
      get api_post_url('NOT-FOUND'), params: { format: :json }
      assert_response :not_found
    end
  end
end

테스트 실행

$ bin/rake test

예외 처리

ActiveRecord::RecordNotFound 예외를 rescue_from으로 처리.

$ vi app/controllers/api/posts_controller.rb
module Api
  class PostsController < ApplicationController
    rescue_from ActiveRecord::RecordNotFound, with: :not_found

    respond_to :json

    def index
      @posts = Post.all
      respond_with(@posts)
    end

    def show
      @post = Post.find(params[:id])
      respond_with(@post)
    end

    private

    def not_found
      head status: :not_found
    end
  end
end

테스트 실행

$ bin/rake test

눈으로 확인하기

$ http GET api-demo.dev/api/posts/1.json
$ http GET api-demo.dev/api/posts/NOT-FOUND.json

RuboCop & Commit

$ rubocop
$ git add .
$ git commit

Pull Request

작업 중인 브랜치를 origin으로 Push.

$ git push origin feature/post-api

GitHub 저장소에 가서 “Compare & pull request” 버튼 클릭.

https://github.com/ahastudio/woowahan-api-demo/compare/feature/post-api?expand=1 -> ahastudio/woowahan-api-demo#2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment