【初心者向け】RailsAPIモードでCRUD処理を実装する方法
徒歩3分圏内にQBハウスがあることによって散歩ついでに散髪に行くことが可能になった23期スキンフェード昴です。
さて、今回はモダンなアプリ開発に欠かせない、rails apiモードに関して学習していきたいと思います。ちょっと長いです。
上から順に見ていくと、rails apiモードでデータのcrud処理ができるようになります。
いわゆるバックエンドにrails、フロントエンドにjavascriptのライブラリ(ReactやVueなど)の構成でアプリを作ることもできるんです。すごいです。rails apiモード。
では、早速開発を進めていきたいと思います。
- 開発環境
- apiモードでrails new
- db作成
- CORS(Cross-Origin Resource Sharing)の設定
- 適当なモデルの作成
- rails-erdで作成したDB設計図
- サーバーにアクセスしてみる
- ルーティングの構成を確認
- アルコールを作成してみる
- Curlを使ってデータを作成(post)してみる
- Curlを使って作成したアルコールを取得(get)してみる
- Curlを使って作成したアルコール詳細(show)を取得(get)してみる
- Curlを使って作成したアルコールを削除(delete)してみる
- Curlを使って作成したアルコールの情報を更新(put)してみる
- まとめ
開発環境
rails 6.1.4
ruby 2.6.7
node 12.22.6
mysql 5.7.36
apiモードでrails new
APIモードではMVCのV(ビュー)が存在しないため、rails newを実行した際にビューに関するファイルやGemが生成されません。
apiモードでrails newを実行すると、viewを生成しなくなる。APIモード = JSONを返すモードと解釈してもいいらしい。今回は、mysqlをDBとして扱う。
$ rails new api-sample -d mysql --api
db作成
$ rails db:create
Running via Spring preloader in process 64897
Created database 'api_sample_development'
Created database 'api_sample_test'
CORS(Cross-Origin Resource Sharing)の設定
ざっくり説明すると、 デフォルトでは、
React
等の別のオリジンからRailsAPI
にアクセス(GET
,POST
,PUT
,DELETE
など)することは制限されています
フロントとバックで切り分けることはsame origin policyに反した行為だそう。Webページを生成したドメイン以外へのHTTPリクエストへアクセス(クロスドメインアクセス)したい場合に有用なのがCORSとのこと。クロスドメインアクセスを実現する事ができる。
具体的に、config/initializer配下にcors.rbを作成することで、クロスドメインアクセスを実現できる。
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '<http://localhost:3000>'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end
Pumaの設定
バックエンドのport番号と被ることを防ぐために3010に変えておく。
portENV.fetch("PORT") { 3010 }
適当なモデルの作成
自分の好きなモデル名、カラム名を任意で作成する
rails g model Alcohol name:string alcohol_percentage:integer price:integer
rails g model Customer name:string favorite_alcohol:string
rails g model Owner name:string
rails g model Shop name:string
rails-erdで作成したDB設計図
サーバーにアクセスしてみる
rails s
お馴染みのyay you’re on railsが表示される
ルーティングの構成を確認
それぞれCRUDができる状態になっている
routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :customers, only: %i[index create update destroy]
resources :shops, only: %i[index create update destroy]
resources :alcohols, only: %i[index create update destroy show]
resources :owners, only: %i[index create update destroy]
end
end
# For details on the DSL available within this file, see <https://guides.rubyonrails.org/routing.html>
end
コンソールでも確認してみる。
$rails routes --expanded
--[ Route 1 ]--------------------------------------------------------------------------------------
Prefix | api_v1_customers
Verb | GET
URI | /api/v1/customers(.:format)
Controller#Action | api/v1/customers#index
--[ Route 2 ]--------------------------------------------------------------------------------------
Prefix |
Verb | POST
URI | /api/v1/customers(.:format)
Controller#Action | api/v1/customers#create
--[ Route 3 ]--------------------------------------------------------------------------------------
Prefix | api_v1_customer
Verb | PATCH
URI | /api/v1/customers/:id(.:format)
Controller#Action | api/v1/customers#update
--[ Route 4 ]--------------------------------------------------------------------------------------
Prefix |
Verb | PUT
URI | /api/v1/customers/:id(.:format)
Controller#Action | api/v1/customers#update
--[ Route 5 ]--------------------------------------------------------------------------------------
Prefix |
Verb | DELETE
URI | /api/v1/customers/:id(.:format)
Controller#Action | api/v1/customers#destroy
--[ Route 6 ]--------------------------------------------------------------------------------------
Prefix | api_v1_shops
Verb | GET
URI | /api/v1/shops(.:format)
Controller#Action | api/v1/shops#index
--[ Route 7 ]--------------------------------------------------------------------------------------
Prefix |
Verb | POST
URI | /api/v1/shops(.:format)
Controller#Action | api/v1/shops#create
--[ Route 8 ]--------------------------------------------------------------------------------------
Prefix | api_v1_shop
Verb | PATCH
URI | /api/v1/shops/:id(.:format)
Controller#Action | api/v1/shops#update
--[ Route 9 ]--------------------------------------------------------------------------------------
Prefix |
Verb | PUT
URI | /api/v1/shops/:id(.:format)
Controller#Action | api/v1/shops#update
--[ Route 10 ]-------------------------------------------------------------------------------------
Prefix |
Verb | DELETE
URI | /api/v1/shops/:id(.:format)
Controller#Action | api/v1/shops#destroy
--[ Route 11 ]-------------------------------------------------------------------------------------
Prefix | api_v1_alcohols
Verb | GET
URI | /api/v1/alcohols(.:format)
Controller#Action | api/v1/alcohols#index
--[ Route 12 ]-------------------------------------------------------------------------------------
Prefix |
Verb | POST
URI | /api/v1/alcohols(.:format)
Controller#Action | api/v1/alcohols#create
--[ Route 13 ]-------------------------------------------------------------------------------------
Prefix | api_v1_alcohol
Verb | PATCH
URI | /api/v1/alcohols/:id(.:format)
Controller#Action | api/v1/alcohols#update
--[ Route 14 ]-------------------------------------------------------------------------------------
Prefix |
Verb | PUT
URI | /api/v1/alcohols/:id(.:format)
Controller#Action | api/v1/alcohols#update
--[ Route 15 ]-------------------------------------------------------------------------------------
Prefix |
Verb | DELETE
URI | /api/v1/alcohols/:id(.:format)
Controller#Action | api/v1/alcohols#destroy
--[ Route 16 ]-------------------------------------------------------------------------------------
Prefix | api_v1_owners
Verb | GET
URI | /api/v1/owners(.:format)
Controller#Action | api/v1/owners#index
--[ Route 17 ]-------------------------------------------------------------------------------------
Prefix |
Verb | POST
URI | /api/v1/owners(.:format)
Controller#Action | api/v1/owners#create
--[ Route 18 ]-------------------------------------------------------------------------------------
Prefix | api_v1_owner
Verb | PATCH
URI | /api/v1/owners/:id(.:format)
Controller#Action | api/v1/owners#update
--[ Route 19 ]-------------------------------------------------------------------------------------
Prefix |
Verb | PUT
URI | /api/v1/owners/:id(.:format)
Controller#Action | api/v1/owners#update
--[ Route 20 ]-------------------------------------------------------------------------------------
Prefix |
Verb | DELETE
URI | /api/v1/owners/:id(.:format)
Controller#Action | api/v1/owners#destroy
アルコールを作成してみる
コントローラーの構成
api/v1/alcohols_controller.rb
class Api::V1::AlcoholsController < ApplicationController
def index
@alcohols = Alcohol.all
render json: @alcohols
end
def show
@alcohol = Alcohol.find(params[:id])
render json: @alcohol
end
def create
@shop = Shop.find(1)
@alcohols = @shop.alcohols.new(alcohol_params)
if @alcohols.save
render json: @alcohols
else
render nil
end
end
def update
set_alcohol
if @alcohol.update(alcohol_params)
render json: @alcohol
else
render nil
end
end
def destroy
set_alcohol
@alcohol.destroy!
render json: @alcohol
end
private
def set_alcohol
@alcohol = Alcohol.find(params[:id])
end
def alcohol_params
params.require(:alcohol).permit(:name, :price, :alcohol_percentage)
end
end
Curlを使ってデータを作成(post)してみる
$ curl -X POST -H "Content-Type: application/json" -d '{"name": "ビール" : "alcohol_percentage": 5 : "price" : 500}' <http://localhost:3000/api/v1/alcohols>
Curlを使って作成したアルコールを取得(get)してみる
$ curl <http://localhost:3010/api/v1/alcohols>
[{"id":1,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":500,"created_at":"2022-01-05T12:49:27.927Z","updated_at":"2022-01-05T12:49:27.927Z"},{"id":2,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":1000,"created_at":"2022-01-05T12:52:35.709Z","updated_at":"2022-01-05T12:52:35.709Z"},{"id":3,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":500,"created_at":"2022-01-05T12:53:32.557Z","updated_at":"2022-01-05T12:53:32.557Z"}]SubarunoMacBook-puro-3:api-sample subaru$
ブラウザにURLを打ち込んで直接アクセスすることもできる
Curlを使って作成したアルコール詳細(show)を取得(get)してみる
$ curl <http://localhost:3010/api/v1/alcohols/1>
{"id":1,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":500,"created_at":"2022-01-05T12:49:27.927Z","updated_at":"2022-01-05T12:49:27.927Z"}
$ curl <http://localhost:3010/api/v1/alcohols/2>
{"id":2,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":1000,"created_at":"2022-01-05T12:52:35.709Z","updated_at":"2022-01-05T12:52:35.709Z"}
Curlを使って作成したアルコールを削除(delete)してみる
$ curl -X DELETE <http://localhost:3010/api/v1/alcohols/1>
{"id":1,"name":"ビール","alcohol_percentage":5,"shop_id":1,"price":500,"created_at":"2022-01-05T12:49:27.927Z","updated_at":"2022-01-05T12:49:27.927Z"}
Curlを使って作成したアルコールの情報を更新(put)してみる
$ curl -X PUT <http://localhost:3010/api/v1/alcohols/2> -d 'alcohol[name]="濃いめのレモンサワー"&alcohol[price]=400&alcohol[alcohol_percentage]=5'
{"name":"\\"濃いめのレモンサワー\\"","price":400,"alcohol_percentage":5,"id":2,"shop_id":1,"created_at":"2022-01-05T12:52:35.709Z","updated_at":"2022-01-05T13:21:06.296Z"}
まとめ
- バックエンドをrailsのapiモードで実装することで、フロントエンドにjavascriptのライブラリ(ReactやVue)を使用する事が容易になる。
- Apiのレスポンスやリクエストを試す際には、CurlやPostmanが便利
【Rails】Rails6でAPIモードの環境構築をしっかりやる
https://github.com/r7kamura/autodoc
https://github.com/ruby-grape/grape
RailsでAPIを作成するために色々比較したので所感と実装方法のご紹介 - Qiita