週刊Elixirライブラリ2015-9
Elixirのライブラリの解説を週ごとにお届けする記事です。
解説が間違っていた場合には、コメントか@hayabusa333にご連絡くださると嬉しいです。
今回はEctoについて
# Ecto is 何?
EctoはElixirにてデータベースとアクセスし、データを保存するためのライブラリです。
Ectoにてデータベースにアクセスするためにはアダプタが必要で、複数のアダプタに対応しております。対応アダプタは下記となります。
Database Ecto Adapter Dependency
PostgreSQL Ecto.Adapters.Postgres postgrex
MySQL Ecto.Adapters.MySQL mariaex
MSSQL Tds.Ecto tds_ecto
SQLite3 Sqlite.Ecto sqlite_ecto
今回は、postgrexにてPostgreSQLにアクセスしようと思います。
# 実行環境
OS:OS X Yosemite
Erlang:Eshell V6.5, OTP-Version 18
Elixir:v1.0.4
PostgreSQL:v9.4.4
# Ectoの実行を行うための新規プロジェクトの作成
mix new 実行時に --sup をつけて実行した場合に mix.exs の内容が微妙に変わります。mix.exs の内容に注意してください。
$ mix new my_ecto --sup $ cd my_ecto
# HexにてEctoをインストールするために設定ファイルの記載を行う
$ vim mix.exs
mix.exsの内容は下記となります。
defmodule MyEcto.Mixfile do use Mix.Project def project do [app: :my_ecto, version: "0.0.1", elixir: "~> 1.0", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end # Configuration for the OTP application # # Type `mix help compile.app` for more information def application do [applications: [:logger, :postgrex, :ecto], mod: {MyEcto.App, []}] # mix new my_ecto --sup に --sup をつけると :mod の記載が追加される # 内容としては、起動時に実行するモジュールを指定しております。 # 上記の記載がないとEctoがうまく起動しません end # Dependencies can be Hex packages: # # {:mydep, "~> 0.3.0"} # # Or git/path repositories: # # {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"} # # Type `mix help deps` for more examples and options defp deps do [ {:postgrex, ">= 0.0.0"}, {:ecto, "~> 0.14.3"} ] end end
# EctoにてDBにアクセスするための設定を記載する
$ vim config/config.exs
config/config.exs の一番下に下記を追加してください
config :my_ecto, MyEcto.Repo, #アプリケーション名と、Repo名を記載 adapter: Ecto.Adapters.Postgres, #使用するアダプタを指定 database: "ecto_simple", #データベース名を設定 username: "postgres", #ユーザー名を設定 password: "password", #ユーザーがアクセスする際のパスワードを指定 hostname: "localhost" #データベースサーバのIPアドレスを指定
# Ectoにてサーバにアクセスするための記述と実地するクエリをコードとして記載する
$ vim lib/my_ecto.ex
lib/my_ecto.ex の内容は以下となります。
# 起動時に読み込むモジュール # 下記のstartメソッドがないとEctoが動いてくれないため注意が必要 defmodule MyEcto.App do use Application def start(_type, _args) do import Supervisor.Spec, warn: false tree = [worker(MyEcto.Repo, [])] opts = [strategy: :one_for_one, name: MyEcto.Supervisor] Supervisor.start_link(tree, opts) end end defmodule MyEcto.Repo do use Ecto.Repo, otp_app: :my_ecto end defmodule MyEcto.Weather do use Ecto.Model schema "weather" do field :city_id, :integer # Defaults to type :string field :temp_lo, :integer field :temp_hi, :integer field :prcp, :float, default: 0.0 end end # iex にて実際に実施するクエリの内容を記載 defmodule MyEcto do import Ecto.Query alias MyEcto.Weather alias MyEcto.Repo def sample_query do query = from w in Weather, where: w.prcp > 0 or is_nil(w.prcp), select: w Repo.all(query) end end
# 依存関係の解決を行います。
$ mix deps.get $ mix deps.compile
# マイグレーションファイルを作成する
マイグレーションファイルである create_tables を作成し、作成されたファイルがあることを確認します。
$ mix ecto.gen.migration create_tables Compiled lib/my_ecto.ex Generated my_ecto app * creating priv/repo/migrations * creating priv/repo/migrations/20150811103823_create_tables.exs $ ls priv/repo/migrations/
ファイルがあるだけではマイグレーションは実行できないため
マイグレーションする内容を記載します。
今回の記載内容はEctoのサンプルと同じものとなります。
$ vim priv/repo/migrations/YYYYXXXXXXXXXX_create_tables.exs
YYYYXXXXXXXXXX_create_tables.exsを下記へと書き換えます。
defmodule Repo.CreateTables do use Ecto.Migration def up do create table(:weather) do add :city_id, :integer add :temp_lo, :integer add :temp_hi, :integer add :prcp, :float timestamps end create index(:weather, [:city_id]) create table(:cities) do add :name, :string, size: 40, null: false add :country_id, :integer end create index(:cities, [:country_id]) create table(:countries) do add :name, :string, size: 40, null: false end end def down do drop index(:weather, [:city_id]) drop index(:cities, [:country_id]) drop table(:weather) drop table(:cities) drop table(:countries) end end
# Ectoを実際に使ってみてる
Ectoを実際に使ってみましょう。
まずはマイグレッションを実行します。
$ mix ecto.create The database for MyEcto.Repo has been created. $ mix ecto.migrate 19:52:04.911 [info] == Running MyEcto.Repo.Migrations.CreateTables.up/0 forward 19:52:04.912 [info] create table weather 19:52:04.952 [info] create index weather_city_id_index 19:52:04.956 [info] create table cities 19:52:04.969 [info] create index cities_country_id_index 19:52:04.973 [info] create table countries 19:52:04.991 [info] == Migrated in 0.7s
lib/my_ecto.exに記載したsample_queryを実施する
$ iex -S mix iex(1)> MyEcto.sample_query 19:53:44.440 [debug] SELECT w0."id", w0."city_id", w0."temp_lo", w0."temp_hi", w0."prcp" FROM "weather" AS w0 WHERE ((w0."prcp" > 0.0::float) OR w0."prcp" IS NULL) [] OK query=417.9ms queue=20.0ms [] iex(2)>
iex -S mix にて MyEcto.sample_query を実施し、Selectをpostgresqlに投げることができました。
特に今回はテーブル上に何も入れていないため結果は返ってきておりません。
# まとめ
今回はElixirにてデータベースとアクセスし、データを保存するためのライブラリであるEctoを紹介させていただきました。
Ecto単体では使いどころが難しいかもしれませんが、Elixirで一番有名である?WebフレームワークのPhoenixでも使用されており、データベースにアクセスするライブラリとしては将来性も高いため内側まで知っていても損はないと思います。
それでは皆さま、良いElixirライフを