構築する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 use
bundle 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