Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@
- **馴染みの関連 API で高速参照**: `belongs_to` / `has_many` 風のインターフェースを DB ではなくオンメモリ上で処理し、N+1 を気にしなくてよい速度で動作。
- **COW フレンドリーで多プロセス共有**: レコードは freeze され、Copy-on-Write を活かしてフォークプロセス間でメモリを効率共有できる。

## ドキュメント
- 導入ガイド: [English](docs/simple_master_guide_en.md) / [日本語](docs/simple_master_guide_ja.md)
- カラム仕様: [English](docs/simple_master_columns_en.md) / [日本語](docs/simple_master_columns_ja.md)
- Dataset / Table: [English](docs/simple_master_dataset_en.md) / [日本語](docs/simple_master_dataset_ja.md)
- Association: [English](docs/simple_master_associations_en.md) / [日本語](docs/simple_master_associations_ja.md)

## ライセンス
MIT ライセンスです。詳細は [LICENSE](LICENSE) を参照してください。
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,11 @@ In game development and other domains, configuration/definition datasets are oft
- **Familiar associations, very fast**: `belongs_to` / `has_many`-style API resolved in memory, fast enough that N+1 is rarely a concern.
- **COW-friendly for multi-process**: records are frozen, making Copy-on-Write efficient when sharing memory across forked processes.

## Documentation
- Getting Started Guide: [English](docs/simple_master_guide_en.md) / [日本語](docs/simple_master_guide_ja.md)
- Columns: [English](docs/simple_master_columns_en.md) / [日本語](docs/simple_master_columns_ja.md)
- Dataset / Table: [English](docs/simple_master_dataset_en.md) / [日本語](docs/simple_master_dataset_ja.md)
- Associations: [English](docs/simple_master_associations_en.md) / [日本語](docs/simple_master_associations_ja.md)

## License
MIT License. See [LICENSE](LICENSE) for details.
51 changes: 51 additions & 0 deletions docs/simple_master_associations_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# SimpleMaster Associations (English)

> 日本語版: [simple_master_associations_ja.md](simple_master_associations_ja.md)

## Overview
SimpleMaster provides `belongs_to`, `has_one`, `has_many`, and `has_many :through`.

## Definitions
```ruby
class Player < ApplicationRecord
belongs_to :level, foreign_key: :lv, primary_key: :lv
has_many :player_items
end
```

```ruby
class Reward < ApplicationMaster
belongs_to :enemy
belongs_to :reward, polymorphic: true
end
```

The lookup path depends on whether the target is `SimpleMaster::Master`
or `ActiveRecord::Base`.

- Master to Master: use `all_by` / `find_by`
- These are fast, so values are fetched on each call. Cache in a variable if used often.
- ActiveRecord: use `simple_master_connection`
- `belongs_to_store` / `has_many_store` (RequestStore) caches per request.

## Common options
### `class_name:`
- Example: `belongs_to :reward, class_name: "Weapon"`
- Explicitly sets the target class.

### `foreign_key:`
- Example: `has_many :players, foreign_key: :lv`
- Sets the foreign key column.

### `primary_key:`
- Example: `belongs_to :level, primary_key: :lv`
- Sets the target primary key (default is `:id`).

## Association types
- `belongs_to` : `belongs_to :enemy`
- `belongs_to (polymorphic)` : `belongs_to :reward, polymorphic: true`
- Requires `def_column :reward_type, polymorphic_type: true`
- `has_one` : `has_one :profile`
- `has_many` : `has_many :players, foreign_key: :lv`
- `has_many :through` : `has_many :items, through: :player_items`
- `source:` can rename the target association
50 changes: 50 additions & 0 deletions docs/simple_master_associations_ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# SimpleMaster Association 仕様 (日本語)

> English version: [simple_master_associations_en.md](simple_master_associations_en.md)

## 全体説明
SimpleMaster の Association は `belongs_to` / `has_one` / `has_many` / `has_many :through` を提供します。

## 定義方法
```ruby
class Player < ApplicationRecord
belongs_to :level, foreign_key: :lv, primary_key: :lv
has_many :player_items
end
```

```ruby
class Reward < ApplicationMaster
belongs_to :enemy
belongs_to :reward, polymorphic: true
end
```

対象が `SimpleMaster::Master` か `ActiveRecord::Base` かで参照方法が変わります。

- Master 同士: `all_by` / `find_by` を使った参照
- 取得が高速なため、都度引き直しとなります。利用時に呼ぶ回数多いなら、変数に格納してください。
- ActiveRecord: `simple_master_connection` で DB 参照
- `belongs_to_store` / `has_many_store` (RequestStore) に保持されるため、リクエストごとにキャッシュが効きます。

## 共通オプション
### `class_name:`
- 例: `belongs_to :reward, class_name: "Weapon"`
- 明示的に参照先クラスを指定します。

### `foreign_key:`
- 例: `has_many :players, foreign_key: :lv`
- 外部キー名を指定します。

### `primary_key:`
- 例: `belongs_to :level, primary_key: :lv`
- 参照先のキーを指定します(デフォルトは `:id`)。

## Association 種別
- `belongs_to` : `belongs_to :enemy`
- `belongs_to (polymorphic)` : `belongs_to :reward, polymorphic: true`
- 前提: `def_column :reward_type, polymorphic_type: true`
- `has_one` : `has_one :profile`
- `has_many` : `has_many :players, foreign_key: :lv`
- `has_many :through` : `has_many :items, through: :player_items`
- `source:` を指定すると参照先の名前を変更できます。
199 changes: 199 additions & 0 deletions docs/simple_master_columns_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# SimpleMaster Columns (English)

> 日本語版: [simple_master_columns_ja.md](simple_master_columns_ja.md)

## Overview
SimpleMaster columns are defined with `def_column`. At load time, type conversion,
cache helpers, and accessor methods are generated.
The behavior depends on `type` and DSL options.

```ruby
class Weapon < ApplicationMaster
def_column :id
def_column :name, type: :string
def_column :attack, type: :float
def_column :rarity

enum :rarity, { common: 0, rare: 1, epic: 2 }
end
```

## Common options
### `type:`
- Example: `def_column :attack, type: :float`
- See the column type list below.

### `group_key:`
- Example: `def_column :lv, type: :integer, group_key: true`
- You can also use `group_key :lv`.

### `db_column_name:`
- Use when the DB column name differs.
- Example: `def_column :start_at, type: :time, db_column_name: :start_time`

### `globalize:`
- Adds locale-aware values using `I18n.locale`.
- Example: `def_column :name, globalize: true`
- You can also use `globalize :name`.
- Translation values live in `@_globalized_name` like `{ en: "Storm Edge", ja: "..." }`.
- Not supported on `id` / `enum` / `bitmask` / `sti` / `polymorphic_type`.
- Cannot be used with `group_key`.

## Column types

### id (IdColumn)
**Usage**
```ruby
def_column :id
```
**Behavior**
- Converts to `to_i` on assignment.
- In tests, updates `id_hash` when changed.

### integer
**Usage**
```ruby
def_column :lv, type: :integer
```
**Behavior**
- Converts to `to_i` on assignment (empty string becomes `nil`).

### float
**Usage**
```ruby
def_column :attack, type: :float
```
**Behavior**
- Converts to `to_f` on assignment (empty string becomes `nil`).

### string
**Usage**
```ruby
def_column :name, type: :string
```
**Behavior**
- Converts to `to_s` on assignment.
- Values are cached to reuse identical objects (`object_cache`).

### symbol
**Usage**
```ruby
def_column :kind, type: :symbol
```
**Behavior**
- Converts to `to_s` + `to_sym` on assignment.
- SQL/CSV output uses a string.

### boolean
**Usage**
```ruby
def_column :is_boss, type: :boolean
```
**Behavior**
- Integers use 0/1, strings accept "true" or "1".
- Adds a `name?` predicate.
- SQL/CSV output is 0/1.

### json
**Usage**
```ruby
def_column :info, type: :json
```
**Options**
- `symbolize_names: true` converts JSON keys to symbols.

**Behavior**
- Parses string values with `JSON.parse`.
- SQL/CSV output uses `JSON.generate`.
- Non-string assignments are not transformed by `symbolize_names`.

### time
**Usage**
```ruby
def_column :start_at, type: :time
```
**Options**
- `db_type: :time` outputs `HH:MM:SS` only.

**Behavior**
- Parses strings with `Date._parse` into `Time`.
- Sub-seconds are truncated.

### enum
**Usage**
```ruby
def_column :rarity, enum: { common: 0, rare: 1, epic: 2 }
# or
def_column :rarity
enum :rarity, { common: 0, rare: 1, epic: 2 }
```
**Options**
- `prefix`, `suffix` add a prefix/suffix to predicates.
- `prefix: true` => `rarity_common?`
- `suffix: :rarity` => `common_rarity?`

**Behavior**
- Values are stored as symbols.
- Adds `rarities` and `rarity_before_type_cast`.
- Predicate methods (e.g. `common?`) are generated.

### bitmask
**Usage**
```ruby
def_column :flags, type: :integer
bitmask :flags, as: [:tradeable, :soulbound, :limited]
```
**Behavior**
- Accepts array/symbol/integer and converts to bit integer.
- `flags` returns an array of symbols.
- Adds `flags_value` / `flags_value=` for raw integer bits.

### sti (STI type column)
**Usage**
```ruby
def_column :type, sti: true
```
**Behavior**
- Converts `type` to a string.
- Defines `sti_base_class` and `sti_column`.
- Loader should resolve classes by `type`.

### polymorphic_type
**Usage**
```ruby
def_column :reward_type, polymorphic_type: true
```
**Behavior**
- Used for `belongs_to polymorphic` type columns.
- Stores a class name string and sets `reward_type_class`.
- Empty strings become `nil`.

## Custom column types
Define custom columns by subclassing `SimpleMaster::Master::Column`.
If the class name ends with `Column`, the `type` is auto-registered.

```ruby
class MoneyColumn < SimpleMaster::Master::Column
private

def code_for_conversion
<<-RUBY
value = value&.to_i
RUBY
end

def code_for_sql_value
<<-RUBY
#{name}
RUBY
end
end

class Product < ApplicationMaster
def_column :price, type: :money
end
```

- Ensure the file is loaded before use.
- Override `init` if you need custom methods.
- See [lib/simple_master/master/column.rb](lib/simple_master/master/column.rb).
Loading