LoginSignup
14
18

More than 3 years have passed since last update.

Rails APIプロジェクトを新規作成し、API疎通確認してherokuにdeployまでの備忘録

Last updated at Posted at 2019-06-16

構築するRails環境

  • Github
  • ruby 2.5.8
  • rails 5.1.6
  • apiモードで作成
  • local DBはsqlite, productionはpostgresqlを使用
  • global領域にrails等はインストールしたくない
  • herokuのsslに対応させる
  • herokuにdeploy

でき上がるrailsアプリができること

  • ユーザ作成
  • ログイン
  • ログインしてるユーザーはルアーの使い方を投稿できる(微妙にマニアックですみません)
  • ユーザーとルアーの使い方のデータは一対多

Githubでプロジェクト作成

  • GithubでRepository新規作成
  • git clone

環境を整える

  • git cloneしたディレクトリ配下に移動

  • rubyのバージョンを設定

rbenv local 2.5.8

  • rubyのバージョンを確認

rbenv version

  • bundle initでGemfileを作成

bundle init

  • Gemfileの編集 ここで今回使いたいrubyバージョンとrailsバージョンを指定
ruby '2.5.8'
gem 'rails', '5.1.6'
  • グローバルではなくプロジェクトの --path vendor/bundle 配下にrailsをinstall

bundle install --path vendor/bundle

[DEPRECATED] The--pathflag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please usebundle config set path 'vendor/bundle', and stop using this flag

globalに設定

bundle config set path 'vendor/bundle'

新規Rails Appの作成

  • プロジェクトディレクトリの--path vendor/bundle配下にrailsが入ったので、rails new でrails appを新規作成。
  • git repositoryと同じ名前のプロジェクト名にしたいときは rails new .
  • 今回はAPIモードで作りたいので --api オプション
  • -B オプションをつけて、このタイミングでは bundle install しない

bundle exec rails new . --api -B

MySQLではじめたい場合
bundle exec rails new . --api -B --database=mysql

  • Gemfileを上書きしていいか聞かれるので Y (yes)で上書き

  • Railsプロジェクトに必要なpumaとかGemfileが入る

  • 作成されたGemfileを編集

ruby '2.5.8'
gem 'rails', '5.1.6'
gem 'puma', '~> 3.7'

group :development, :test do
  gem 'sqlite3', '1.3.13'
  gem 'byebug', '9.0.6', platform: :mri
end

group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :production do
  gem 'pg', '0.20.0'
end

  • 適用したいGemfileがようやくできたので、このGemfileで bundle instal
  • macにpostgresqlをインストールしていない&localではsqliteを使うので、--without production オプションをつけて本番環境はローカルmacに構築されないようにする

bundle install --path vendor/bundle --without production

Rails Appの機能作成

  • scaffold, referenceは使わずにやってます。

  • user modelの作成

bundle exec rails g model user name:string password:string token:token

  • lure modelの作成

bundle exec rails g model lure name:string usage:string

  • DBの作成

bundle exec rails db:migrate

  • 一対多関係を作成

bundle exec rails g migration add_user_id_to_lures user_id:integer

bundle exec rails db:migrate

  • User Modelの編集
class User < ApplicationRecord
  has_secure_token
  has_many :lures, dependent: :destroy
end
  • Lure Modelの編集
class Lure < ApplicationRecord
  belongs_to :user
end
  • User Controllerの作成

bundle exec rails g controller users

  • Lure Controllerの作成

bundle exec rails g controller lures

  • routeを設定
  • ~~/api/v1/login みたいにして、APIバージョンが上がることを想定した作りにしておきたいのでrouteは以下のように
Rails.application.routes.draw do
  namespace 'api' do
    namespace 'v1' do
      resources :users
      resources :lure
    end
  end
end
  • UsersControllerの編集
  • この時、app -> controllers ディレクトリ配下にapiディレクトリを作成
  • さらにapiディレクトリ配下にv1ディレクトリを作成
  • UsersController LuresControllerファイルをapp/controllers/api/v1ディレクトリ配下に移動
  • class Api::V1::UsersControllerはAPIモジュール配下のv1モジュール配下のUsersControllerという意味(モジュール名は大文字始まり)
class Api::V1::UsersController < ApplicationController
  # 
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    users = User.order(created_at: :desc)
    render json: { status: 'SUCCESS', message: 'loaded users', data: users }
  end

  def show
    user = User.find(params[:id])
    render json: { status: 'SUCCESS', message: 'loaded the user', data: user }
  end

  def create
    user = User.new(user_params)
    if user.save
      render json: { status: 'SUCCESS', message: 'User was successfully created.', data: user }
    else
      render json: { status: :unprocessable_entity, message: user.errors }
    end
  end

  def destroy
    user = User.find(params[:id])
    user.destroy
    render json: { status: 'SUCCESS', message: 'deleted the user', data: user }
  end

  def update
    user = User.find(params[:id])
    if user.update(user_params)
      render json: { status: 'SUCCESS', message: 'updated the user', data: user }
    else
      render json: { status: 'SUCCESS', message: 'loaded the user', data: user }
    end
  end

    private

    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      params.require(:user).permit(:name, :password, :token)
    end
end
class Api::V1::LuresController < ApplicationController
  include ActionController::HttpAuthentication::Token::ControllerMethods
  # tokenある人だけ以下を実行できます
  before_action :authenticate

  def index
    lures = Lure.order(created_at: :desc)
    render json: { status: 'SUCCESS', message: 'loaded lures', data: lures }
  end

  def show
    lure = Lure.find(params[:id])
    render json: { status: 'SUCCESS', message: 'loaded the lure', data: lure }
  end

  def create
    lure = @auth_user.lures.build(lure_params)
    logger.debug("lure_params:::")
    logger.debug(lure_params)
    if lure.save
        render json: { status: 'SUCCESS', message: 'Lure was successfully created.', data: lure }
      else
        render json: { status: :unprocessable_entity, message: lure.errors }
      end
  end

  def destroy
    lure = Lure.find(params[:id])
    lure.destroy
    render json: { status: 'SUCCESS', message: 'deleted the lure', data: lure }
  end

  def update
    lure = Lure.find(params[:id])
    if lure.update(lure_params)
      render json: { status: 'SUCCESS', message: 'updated the lure', data: lure }
    else
      render json: { status: 'SUCCESS', message: 'loaded the lure', data: lure }
    end
  end

    private
    def authenticate
      authenticate_or_request_with_http_token do |token,options|
        @auth_user = User.find_by(token: token)
        @auth_user != nil ? true : false
      end
    end

    def lure_params
      params.require(:lure).permit(:name, :usage)
    end
end
  • rails 起動

bundle exec rails s

  • curlコマンドでuser作成

curl -X POST -H 'Content-Type:application/json' -d '{ "name": "bright", "password": "password" }' http://0.0.0.0:3000/api/v1/users

  • レスポンスが以下のようであればOK
{"status":"SUCCESS","message":"User was successfully created.","data":{"id":4,"name":"bright","password":"password","token":"UK789txu3ZsripoXnugPjVG3","created_at":"2019-06-13T11:41:23.017Z","updated_at":"2019-06-13T11:41:23.017Z"
  • ログインの作成
  • ログインはアクションがあればいいのでコントローラだけ作成
bundle exec rails g controller login login
  • routesの編集
Rails.application.routes.draw do
  get 'login/login'
  namespace 'api' do
    namespace 'v1' do
      resources :users
      resources :lure
      post 'login/login'
    end
  end
end
  • ログインコントローラの編集
class Api::V1::LoginController < ApplicationController
  def login
    login_user = User.find_by(name:params[:name], password:params[:password])
    if login_user != nil
      render json: { status: 'SUCCESS', message: 'user logged in', data: login_user.token }
    else
      render json: { status: 'FAILER', message: 'no auth' }
    end
  end
end
  • 作成したユーザでログインできるか疎通確認

curl -X POST -H 'Content-Type:application/json' -d '{ "name": "bright", "password": "password" }' http://0.0.0.0:3000/api/v1/login/login

  • トークンが返って来ればOK

  • 返ってきたtokenをAuthorization HEADERに加えて、ルアーを作成してみる

curl -X POST -H 'Authorization: Token UK789txu3ZsripoXnugPjVG3' -H 'Content-Type:application/json' -d '{ "name": "Spinnerbait", "usage": "it can be used as a fish finder, a deep water bait, a shallow water bait, a bait that covers a lot of area in a short time." }' http://0.0.0.0:3000/api/v1/lures

  • 以下のレスポンスが返って来ればOK
{"status":"SUCCESS","message":"Lure was successfully created.","data":{"id":1,"name":"Spinnerbait","usage":"it can be used as a fish finder, a deep water bait, a shallow water bait, a bait that covers a lot of area in a short time.","created_at":"2019-06-13T13:23:41.359Z","updated_at":"2019-06-13T13:23:41.359Z","user_id":4}}
  • ルアーをGETしてみる

curl -X GET -H 'Authorization: Token UK789txu3ZsripoXnugPjVG3' -H 'Content-Type:application/json' http://0.0.0.0:3000/api/v1/lures/1

{"status":"SUCCESS","message":"loaded the lure","data":{"id":1,"name":"Spinnerbait","usage":"it can be used as a fish finder, a deep water bait, a shallow water bait, a bait that covers a lot of area in a short time.","created_at":"2019-06-13T13:23:41.359Z","updated_at":"2019-06-13T13:23:41.359Z","user_id":4}}

herokuにdeploy

  • herokuにプロジェクト作成

heroku create

  • herokuにpush

git push heroku master

  • heroku環境でmigrate

heroku run rails db:migrate

curl -X POST -H 'Content-Type:application/json' -d '{ "name": "bright", "password": "password" }' https:// [herokuに発行されたAPP ID] .herokuapp.com/api/v1/users

{"status":"SUCCESS","message":"User was successfully created.","data":{"id":1,"name":"bright","password":"password","token":" [token]","created_at":"2019-06-13T13:42:44.413Z","updated_at":"2019-06-13T13:42:44.413Z"}}
  • ログインできるか確認

curl -X POST -H 'Content-Type:application/json' -d '{ "name": "bright", "password": "password" }' https://[herokuに発行されたAPP ID].herokuapp.com/api/v1/login/login

{"status":"SUCCESS","message":"user logged in","data":" [herokuに発行されたAPP ID]"}
  • token使ってルアーの使い方を作成

curl -X POST -H 'Authorization: Token [herokuに発行されたAPP ID]' -H 'Content-Type:application/json' -d '{ "name": "Spinnerbait", "usage": "it can be used as a fish finder, a deep water bait, a shallow water bait, a bait that covers a lot of area in a short time." }' https://[herokuに発行されたAPP ID].herokuapp.com/api/v1/lures

  • responseが以下であればOK
{"status":"SUCCESS","message":"Lure was successfully created.","data":{"id":1,"name":"Spinnerbait","usage":"it can be used as a fish finder, a deep water bait, a shallow water bait, a bait that covers a lot of area in a short time.","created_at":"2019-06-13T13:45:27.939Z","updated_at":"2019-06-13T13:45:27.939Z","user_id":1}}

参考

https://www.gitignore.io/api/rails
https://www.sejuku.net/blog/26617
https://qiita.com/ochiochi/##items/966b884eb17045dfb929

14
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18