|
| 1 | +# SimpleMaster 導入ガイド |
| 2 | + |
| 3 | +## 目的 |
| 4 | +- マスターデータを Rails/ActiveRecord とは別に高速に扱う |
| 5 | +- Ruby オブジェクトとして参照でき、関連づけやキャッシュを定義できる |
| 6 | +- DB がなくても扱え、用途に応じて複数の dataset を切り替えられる |
| 7 | + |
| 8 | +## インストール |
| 9 | +Gemfile に追加して bundle します。 |
| 10 | + |
| 11 | +```ruby |
| 12 | +gem "simple_master" |
| 13 | +``` |
| 14 | + |
| 15 | +```bash |
| 16 | +bundle install |
| 17 | +``` |
| 18 | + |
| 19 | +## 初期化 |
| 20 | +アプリ起動時に SimpleMaster を初期化し、データセットを読み込ませます。 |
| 21 | + |
| 22 | +```ruby |
| 23 | +# config/initializers/simple_master.rb |
| 24 | +Rails.application.config.after_initialize do |
| 25 | + Rails.application.eager_load! |
| 26 | + |
| 27 | + SimpleMaster.init(for_test: Rails.env.test?) |
| 28 | + |
| 29 | + loader = SimpleMaster::Loader::QueryLoader.new |
| 30 | + $current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader) |
| 31 | + $current_dataset.load |
| 32 | +end |
| 33 | +``` |
| 34 | + |
| 35 | +※ JSON fixture を読み込む場合は後述の `JsonLoader` を使います。 |
| 36 | + |
| 37 | +## Master クラス定義 |
| 38 | +`ApplicationMaster` をベースに Master を作ります。 |
| 39 | + |
| 40 | +```ruby |
| 41 | +# app/models/application_master.rb |
| 42 | +class ApplicationMaster < SimpleMaster::Master |
| 43 | + self.abstract_class = true |
| 44 | +end |
| 45 | +``` |
| 46 | + |
| 47 | +```ruby |
| 48 | +# app/models/weapon.rb |
| 49 | +class Weapon < ApplicationMaster |
| 50 | + def_column :id |
| 51 | + def_column :type, sti: true |
| 52 | + def_column :name |
| 53 | + def_column :attack, type: :float |
| 54 | + def_column :rarity, type: :integer |
| 55 | + |
| 56 | + enum :rarity, { common: 0, rare: 1, epic: 2 } |
| 57 | + bitmask :flags, as: [:tradeable, :soulbound, :limited] |
| 58 | + |
| 59 | + validates :name, presence: true |
| 60 | + validates :attack, numericality: { greater_than_or_equal_to: 0 } |
| 61 | +end |
| 62 | +``` |
| 63 | + |
| 64 | +## データロード (DB / Fixture) |
| 65 | +### DB から読み込む |
| 66 | +標準の `QueryLoader` で DB のテーブルから読み込みます。 |
| 67 | + |
| 68 | +```ruby |
| 69 | +loader = SimpleMaster::Loader::QueryLoader.new |
| 70 | +$current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader) |
| 71 | +$current_dataset.load |
| 72 | +``` |
| 73 | + |
| 74 | +### Loader を自作する |
| 75 | +例:独自ローダを用意して JSON を読み込みます。 |
| 76 | + |
| 77 | +```ruby |
| 78 | +class JsonLoader < SimpleMaster::Loader |
| 79 | + FIXTURE_DIR = Rails.root.join("fixtures/masters") |
| 80 | + |
| 81 | + def read_raw(table) |
| 82 | + File.read(FIXTURE_DIR.join("#{table.klass.table_name}.json")) |
| 83 | + end |
| 84 | + |
| 85 | + def build_records(klass, raw) |
| 86 | + JSON.parse(raw).map { |attrs| klass.new(attrs) } |
| 87 | + end |
| 88 | +end |
| 89 | +``` |
| 90 | + |
| 91 | +※ STI を使う場合は `type` を見てクラス分岐する実装を追加してください(例: [dummy/lib/json_loader.rb](dummy/lib/json_loader.rb))。 |
| 92 | + |
| 93 | +```ruby |
| 94 | +loader = JsonLoader.new |
| 95 | +$current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader) |
| 96 | +$current_dataset.load |
| 97 | +``` |
| 98 | + |
| 99 | +## ActiveRecord 連携 |
| 100 | +ActiveRecord のモデルから Master を参照する場合は Extension を使います。 |
| 101 | + |
| 102 | +```ruby |
| 103 | +# app/models/application_record.rb |
| 104 | +class ApplicationRecord < ActiveRecord::Base |
| 105 | + include SimpleMaster::ActiveRecord::Extension |
| 106 | +end |
| 107 | +``` |
| 108 | + |
| 109 | +```ruby |
| 110 | +class Player < ApplicationRecord |
| 111 | + belongs_to :level, foreign_key: :lv, primary_key: :lv |
| 112 | + has_many :player_items |
| 113 | +end |
| 114 | +``` |
| 115 | + |
| 116 | +## テスト用設定 |
| 117 | +テストケースごとにリセットするため、Dataset を都度作るように設定します。 |
| 118 | +またテストでは通常と違い、データの一時保存や関連付け保存等が必要なため、`SimpleMaster::Master::Editable` と `TestTable` 利用するとよりスムーズとなります。 |
| 119 | +例えば、RSpec ではこのように設定します。 |
| 120 | + |
| 121 | +```ruby |
| 122 | +ApplicationMaster.prepend(SimpleMaster::Master::Editable) |
| 123 | + |
| 124 | +RSpec.configure do |config| |
| 125 | + config.around do |example| |
| 126 | + dataset = SimpleMaster::Storage::Dataset.new(table_class: SimpleMaster::Storage::TestTable) |
| 127 | + SimpleMaster.use_dataset(dataset) { example.run } |
| 128 | + end |
| 129 | +end |
| 130 | +``` |
| 131 | + |
| 132 | +## 便利メソッド |
| 133 | +- `SimpleMaster.use_dataset(dataset) { ... }` : 一時的に dataset を差し替える |
| 134 | +- `cache_method` / `cache_class_method` : 高速なキャッシュを定義 |
| 135 | +- `enum` / `bitmask` / `globalize` : カラム拡張 |
| 136 | + |
| 137 | +## 補足 |
| 138 | +- 本番では `SimpleMaster::Master::Editable` は使わず、テスト用途のみ推奨 |
| 139 | +- データソースに合わせて `Loader` を差し替える運用を想定 |
0 commit comments