目的
Ectoで1対多の関係性を検証する。
実行環境
OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4
始める前に
先日の記事を元に実施しますので、
プロジェクトの作成とマイグレーションは終わらせておいて下さい。
プロジェクトの作成とマイグレーションは終わらせておいて下さい。
よければ参考に・・・
[Elixir+Phoenix]EctoModelsの機能を使う
[Elixir+Phoenix]EctoModelsの機能を使う
準備良し。
以降、この記事でのプロジェクトと言えば、
“ecto_models_sample”を指し示す。
以降、この記事でのプロジェクトと言えば、
“ecto_models_sample”を指し示す。
目次
- 1対多の関係?
- has_manyを検証!
1. 1対多の関係?
1対多の関係と言うと何が思いつくでしょうか?
男一人に対して女複数人のハーレム。(またはその逆)
若しくは、複数人に対しての浮気。
碌なのが思いつかないですね。(冗談)
若しくは、複数人に対しての浮気。
碌なのが思いつかないですね。(冗談)
閑話休題。
簡単なWebサイトを例にしましょう。
登録しているユーザが記事を投稿できるWebサイトがあります。
登録しているユーザが記事を投稿できるWebサイトがあります。
その場合、ユーザ一人に対して複数の記事が紐づけられますね。
そういった場合に今回実施する1対多の関係性を設定しておくと楽になるわけです。
(一々、SQL文で探して結合してなんてやりたくないです・・・)
そういった場合に今回実施する1対多の関係性を設定しておくと楽になるわけです。
(一々、SQL文で探して結合してなんてやりたくないです・・・)
Ectoには以下のような機能があります。
- Schema.has_many/3
- Schema.belongs_to/3
- Schema.has_one/3
大体どれを使うか想像ができたのではないでしょうか?
2. has_manyを検証!
では、実際に検証していきましょう。
まず、Userモデル以外に新しいモデルを作成します。
記事モデルでいいか・・・
記事モデルでいいか・・・
データモデルは以下になります。
microposts: id:integer, content:string, user_id:integer, timestamp
※idとtimestampは自動で作成されるので、それ以外の項目を指定する
microposts: id:integer, content:string, user_id:integer, timestamp
※idとtimestampは自動で作成されるので、それ以外の項目を指定する
>mix phoenix.gen.html Micropost microposts content:string user_id:integer
DBでSQLを使ってデータを入れるのが面倒くさいので、
画面上からmicropostsテーブルへデータを入力するために”gen.html”を使用している。
画面上からmicropostsテーブルへデータを入力するために”gen.html”を使用している。
>mix ecto.migrate
[info] == Running EctoModelsSample.Repo.Migrations.CreateMicropost.change/0 forward
[info] create table microposts
[info] == Migrated in 0.2s
それでは、二つのモデルを編集します。
web/models/user.exを開き、
スキーマを以下のように編集して下さい。
スキーマを以下のように編集して下さい。
schema "users" do
field :name, :string
field :email, :string
has_many :microposts, EctoModelsSample.Micropost
timestamps
end
web/models/micropost.exを開き、
スキーマを以下のように編集して下さい。
スキーマを以下のように編集して下さい。
schema "microposts" do
field :content, :string
belongs_to :user, EctoModelsSample.User, foreign_key: :user_id
timestamps
end
@required_fields ~w(content user_id)
@optional_fields ~w()
Tips:
foreign_keyを指定しない場合、
“:user+_id = user_id”と言った形で補完するようです。
foreign_keyを指定しない場合、
“:user+_id = user_id”と言った形で補完するようです。
次にUserコントローラを修正します。
web/controllers/user_contoroller.exを開き、
以下のように関数を編集して下さい。
以下のように関数を編集して下さい。
def index(conn, _params) do
users = EctoModelsSample.User |> Repo.all() |> Repo.preload [:microposts]
render(conn, "index.html", users: users)
end
def show(conn, %{"id" => id}) do
user = EctoModelsSample.User |> Repo.get(id) |> Repo.preload [:microposts]
render(conn, "show.html", user: user)
end
Micropostを画面上に表示させたいですね!
テンプレートに以下のようなコードを記述すれば表示できます。
テンプレートに以下のようなコードを記述すれば表示できます。
<%= for user <- @users do %>
<%= user.name %>
<%= user.email %>
<%= for post <- user.microposts do %>
<%= post.content %>
<% end %>
<% end %>
管理人の独り言~
Phoenixのガイドだとuser_idを生成していないのだが・・・
どうやってあれで動いているのだろうか・・・
どうやってあれで動いているのだろうか・・・
検証として、user_idを生成しないパターンも行ったのですが、
そうすると実行時に「user_idなんてキーねぇよ」って怒られるのです。
そうすると実行時に「user_idなんてキーねぇよ」って怒られるのです。
まだ不明な所は残っているが、
1対多の関係性を検証できたからとりあえず良しとしよう。
1対多の関係性を検証できたからとりあえず良しとしよう。
また後でhexdocs - Ecto.Schemaを参考にしてやってみよう。