Rails APIスタートアップガイドのメモ

概要

Rails APIで立ち上げるまでにやること一覧。

事前準備

json-server で、DB構造を設計しておく。
db.sjonの中身は冗長的に書く(リレーション張れないため)。

{
    "users": [
        {
            "id": 1,
            "wallet_address": "HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg"
        },
        {
            "id": 2,
            "wallet_address": "5U3bH5b6XtG99aVWLqwVzYPVpQiFHytBD68Rz2eFPZd7"
        }
    ],
    "products": [
        {
            "id": 1,
            "barcode": "45019517",
            "name": "ポカリスエット ペットボトル(500mL)"
        },
        {
            "id": 2,
            "barcode": "4901777018686",
            "name": "サントリー天然水 2Lペット"
        }
    ],
    "characters": [
        {
            "id": 1,
            "product_id": 1,
            "name": "ポカリスエットン",
            "total_rarity": 1,
            "image": "https://bafybeibvl5c2j3izinxxukzjidnuvlf66qviheb7yrqxo2eefvok7ntqdq.ipfs.dweb.link/791.gif"
        },
        {
            "id": 2,
            "product_id": 2,
            "name": "天然水神様",
            "total_rarity": 2,
            "image": "https://bafybeibikwgxr6d3zp33rsh4iguvoylxrebhlri72g24g445ohanfnkoqe.ipfs.dweb.link/147.gif"
        }
    ],
    "scan_histories": [
        {
            "id": 1,
            "timestamp": "1655084185",
            "wallet_address": "HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg",
            "barcode": "45019517",
            "characters": {
                "name": "いろはスケル",
                "image": "https://bafybeibvl5c2j3izinxxukzjidnuvlf66qviheb7yrqxo2eefvok7ntqdq.ipfs.dweb.link/791.gif"
            },
            "mint_histories": {
                "mint_address": "XtBt31GCF5enFg7YG1YkH33Y5w1SruGMcz7GttUVUpH"
            }
        },
        {
            "id": 2,
            "timestamp": "1655175600",
            "wallet_address": "HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg",
            "barcode": "4901777018686",
            "characters": {
                "name": "天然水神様",
                "image": "https://bafybeibikwgxr6d3zp33rsh4iguvoylxrebhlri72g24g445ohanfnkoqe.ipfs.dweb.link/147.gif"
            }
        }
    ],
    "deposit_histories": [
        {
            "id": 1,
            "scan_history_id": 1,
            "timestamp": "1655084185",
            "tx_id": "",
            "tx_status": "success"
        }
    ],
    "mint_histories": [
        {
            "id": 1,
            "scan_history_id": 1,
            "timestamp": "1655084185",
            "mint_address": "XtBt31GCF5enFg7YG1YkH33Y5w1SruGMcz7GttUVUpH",
            "tx_status": "success"
        }
    ]
}

ステップ

Rails API作成

% rails new <アプリ名> --api

Gem用意

ポイントは、jbuilderとrack-corsをアクティブにすること。
jbuilderはview側でJSONを自由に書けて、rack-corsはクロスドメイン対応で必要。

Gemfile

source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.1.2"

gem "rails", "~> 7.0.3"
gem "sqlite3", "~> 1.4"
gem "puma", "~> 5.0"
gem "jbuilder"
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
gem "bootsnap", require: false
gem "rack-cors"

group :development, :test do
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
end

group :development do
  gem "spring"
end

Gemをインストール

% bundle install --path vendor/bundle

Scaffold

json-serverの骨子をもとに、scaffoldで、MVCの雛形を作る。

% rails g scaffold <モデル名> <カラム名:型>
% rails db:migrate

リレーションを張る場合(外部参照キー)は、「モデル名:references」を記述。
(例)user:references (user_id:referencesではない)

CORS設定

クロスドメイン対応で、暫定的に全許可設定。

config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "*"

    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

脆弱なため、本番リリース前にはちゃんとした設定が必要。

Rails API起動

% rails s -p <ポート番号>

メモ

render json

Controllerで「render json」するとViewは読み込まれず、Controller側で制御して出力される。「View名.json.jbuilder」のファイルを作っても無視される。

render json: @mint_history

「View名.json.jbuilder」のファイルは、Controller側で「@変数名」で渡せば、View側で自由に扱える。

Controllerのshowに記述がないのに動く

デフォルトだと、before_actionでfindがセットされているため。
以下のような記述。

before_action :set_mint_history, only: %i[ show update destroy ]

〜〜〜

def set_mint_history
    @mint_history = MintHistory.find(params[:id])
end

references(外部参照キー)に後追いでunique設定

scaffoldでreferences設定したあとに、unique設定したい場合。
マイグレーションするときに、「add_index」でuniqeu設定すると、indexありますというエラーが出る。

% rails db:migrate
〜〜〜
ActiveRecord::StatementInvalid: SQLite3::SQLException: "index" already exists

これは、まずindexを削除してから、あらためてindex設定すればOK(remove_indexを先に書いてadd_indexを書く)。

class ChangeColumnOnMintHistory < ActiveRecord::Migration[7.0]
  def change
    remove_index :mint_histories, column: :scan_history_id
    add_index :mint_histories, :scan_history_id, unique: true
  end
end