Skip to content

Instantly share code, notes, and snippets.

@IzumiSy
Created December 14, 2017 14:06
Show Gist options
  • Save IzumiSy/9325576ad7b569ad47e18e62bd902f2c to your computer and use it in GitHub Desktop.
Save IzumiSy/9325576ad7b569ad47e18e62bd902f2c to your computer and use it in GitHub Desktop.
ROM.rb relation example
require "rom"
require "rom/sql"
#
# ## Relation
#
# RelationはROM.rbにおいてアダプタ固有の操作をラップする永続化レイヤの責務を扱う
# SQLiteやMySQL固有の操作はAdapterに実装されており、それらに対するインターフェースを提供する
# (余談ではあるが、rom-sqlは中のSQLビルダにSequelを使っている)
module Relations
class Users < ROM::Relation[:sql]
# schemaをROM::Relationの継承クラスの中で使うことでデータベースのスキーマを定義できる
# MySQLなどのデータベースを使っていれば、`schema(infer: true)`の一文でスキーマ推論を有効化できる
# ここではインメモリなので明示的にスキーマの定義をしている。
schema(:users) do
attribute :id, Types::Int
attribute :name, Types::String
attribute :age, Types::Int
attribute :has_car, Types::Bool
end
# インスタンスメソッドを定義することで、Relationが持つメソッドを追加できる
# ここでは、Relationが対象としているアダプタ(例えばこのコードの場合はSQLite)
# に定義された固有の操作が行える。whereはSQLiteアダプタの中で定義されている。
def all
where()
end
def has_car
where(has_car: true)
end
# デフォルトではすべてのカラムが返り値のレコードに含まれて返されるが
# それを変更したければdatasetを定義することができる。
# この例の場合はhas_carを意図的にレコードに含めないようにしている。
dataset do
select(:id, :name, :age)
end
end
end
# ROMを初期化して定義したRelationを登録する。
# auto_registrationというディレクトリをまるごと登録対象にできるメソッドがあるので
# ちゃんとしたプロジェクトであればそちらをつかうのがよい。
config = ROM::Configuration.new(:sql, "sqlite::memory")
config.register_relation(Relations::Users)
rom = ROM.container(config)
# データベースのテーブルがないのでマイグレーションをする
# こちらもちゃんとしたRakeタスクをROMが用意してくれているので
# まともなプロジェクトではこのようにマイグレーションを書くことはない。
migration = ROM::SQL.migration(rom) do
change do
create_table(:users) do
primary_key :id
string :name
integer :age
boolean :has_car, default: false
end
end
end
gateway = rom.gateways[:default]
migration.apply(gateway.connection, :up)
# ROMに登録されたRelationを操作してみる。
# Relationを経由すればinsertなどのSQLite固有のメソッドも使えるが、できればRelationのメソッド
# としてラップしたほうがよい。固有のメソッド以外にもoneやallなどのビルトインメソッドもある。
users = rom.relations[:users]
users.insert(name: "Bob", age: 22, has_car: true)
users.insert(name: "Alice", age: 23)
p users.all.to_a # [{:id=>1, :name=>"Bob", :age=>22}, {:id=>2, :name=>"Alice", :age=>23}]
p users.has_car.to_a # [{:id=>1, :name=>"Bob", :age=>22}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment