- Handle master data fast without relying on Rails/ActiveRecord
- Reference records as Ruby objects and define associations and caches
- Use without a DB and switch datasets by use case
Add to Gemfile and bundle.
gem "simple_master"bundle installInitialize SimpleMaster at boot and load a dataset.
# config/initializers/simple_master.rb
Rails.application.config.after_initialize do
Rails.application.eager_load!
SimpleMaster.init(for_test: Rails.env.test?)
loader = SimpleMaster::Loader::QueryLoader.new
$current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader)
$current_dataset.load
endIf you load JSON fixtures, use the JsonLoader described below.
Create masters based on ApplicationMaster.
# app/models/application_master.rb
class ApplicationMaster < SimpleMaster::Master
self.abstract_class = true
end# app/models/weapon.rb
class Weapon < ApplicationMaster
def_column :id
def_column :type, sti: true
def_column :name
def_column :attack, type: :float
def_column :rarity, type: :integer
enum :rarity, { common: 0, rare: 1, epic: 2 }
bitmask :flags, as: [:tradeable, :soulbound, :limited]
validates :name, presence: true
validates :attack, numericality: { greater_than_or_equal_to: 0 }
endUse the default QueryLoader to load from DB tables.
loader = SimpleMaster::Loader::QueryLoader.new
$current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader)
$current_dataset.loadExample: implement a loader to read JSON.
class JsonLoader < SimpleMaster::Loader
FIXTURE_DIR = Rails.root.join("fixtures/masters")
def read_raw(table)
File.read(FIXTURE_DIR.join("#{table.klass.table_name}.json"))
end
def build_records(klass, raw)
JSON.parse(raw).map { |attrs| klass.new(attrs) }
end
endIf you use STI, add a branch that resolves the class from type
(see dummy/lib/json_loader.rb).
loader = JsonLoader.new
$current_dataset = SimpleMaster::Storage::Dataset.new(loader: loader)
$current_dataset.loadUse the Extension to reference masters from ActiveRecord models.
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include SimpleMaster::ActiveRecord::Extension
endclass Player < ApplicationRecord
belongs_to :level, foreign_key: :lv, primary_key: :lv
has_many :player_items
endCreate a dataset per example to reset state.
In tests, SimpleMaster::Master::Editable and TestTable are useful.
Example with RSpec:
ApplicationMaster.prepend(SimpleMaster::Master::Editable)
RSpec.configure do |config|
config.around do |example|
dataset = SimpleMaster::Storage::Dataset.new(table_class: SimpleMaster::Storage::TestTable)
SimpleMaster.use_dataset(dataset) { example.run }
end
endSimpleMaster.use_dataset(dataset) { ... }: temporarily switch datasetcache_method/cache_class_method: define fast cachesenum/bitmask/globalize: column extensions
- Do not use
SimpleMaster::Master::Editablein production; it is for tests - Swap the
Loaderbased on your data source