著者:清水赳(香川大学SLP)
こんにちは。香川大学工学部 学部3 年の清水です。今回は、前回に引き続き、Elixir 製のWebアプリケーションフレームワーク Phoenix を紹介します。Elixir はRuby によく似た文法を持っています。更にPhoenix は、MVC
フレームワークを採用するなど、Ruby on Rails に大きく影響を受けています。その他にも影響を受けた点は多く、非常に近い感覚でコーディングが行えます。
前回はPhoenix の紹介として、モデルが1 つだけの簡単な掲示板アプリケーションを作成しました。今回はもう一歩踏み込んでみます。自分の蔵書を管理できるアプリケーションを作りながら、2 つ以上のモデルを関連付ける方法を紹介します。
記事本文掲載のシェルスクリプトマガジンvol.50は以下リンク先でご購入できます。

| 1 2 3 4 5 6 | schema "genres" do  has_many :books, Bookcollection.Book, on_delete: :delete_all # この行を追加  field :name, :string  timestamps() end | 
| 1 2 3 4 5 6 7 8 | schema "books" do  field :title, :string  field :isbn, :string  field :store_loc, :string  field :genre_id, :integer # この行を削除  belongs_to :genre, Bookcollection.Genre, foreign_key: :genre_id # この行を追加  timestamps() end | 
| 1 2 3 4 5 6 | scope "/", Bookcollection do  pipe_through :browser # Use the default browser stack  get "/", PageController, :index # この行を削除する  resources "/books", BookController # この行を追加する  resources "/genres", GenreController # この行を追加する end | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | defmodule Bookcollection.GenreController do  use Bookcollection.Web, :controller  def index(conn, _params) do    genres = Repo.all(Bookcollection.Genre)    render conn, "index.html", genres: genres  end  def new(conn, _params) do    genre = Bookcollection.Genre.changeset(%Bookcollection.Genre{}, %{})    render conn, "new.html", genre: genre  end  def create(conn, _params) do    genre = Bookcollection.Genre.changeset(%Bookcollection.Genre{}, _params["genre"])    case Repo.insert(genre) do      {:ok, genre} ->        redirect conn, to: "/genres"      {:error, genre} ->        render(conn, "new.html", genre: genre)    end  end  def delete(conn, _params) do    genre = Repo.get(Bookcollection.Genre, _params["id"])    Repo.delete_all(from(b in Bookcollection.Book, where:b.genre_id == ^genre.id))    Repo.delete(genre)    redirect conn, to: "/genres"  end end | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | defmodule Bookcollection.BookController do  use Bookcollection.Web, :controller  def index(conn, _params) do    books = Repo.all(Bookcollection.Book)    render conn, "index.html", books: books  end  def new(conn, _params) do    book = Bookcollection.Book.changeset(%Bookcollection.Book{}, %{})    genre = Enum.map(Repo.all(Bookcollection.Genre), &{&1.name, &1.id})    render conn, "new.html", book: book, genre: genre  end  def create(conn, _params) do    book = Bookcollection.Book.changeset(%Bookcollection.Book{}, _params["book"])    case Repo.insert(book) do      {:ok, book} ->        redirect conn, to: "/books"      {:error, book} ->        genre = Enum.map(Repo.all(Bookcollection.Genre),&{&1.name, &1.id})        render(conn, "new.html", book: book, genre: genre )    end  end  def delete(conn, _params) do    book = Repo.get(Bookcollection.Book, _params["id"])    Repo.delete(book)    redirect conn, to: "/books"  end end | 
| 1 2 3 | defmodule Bookcollection.BookView do  use Bookcollection.Web, :view end | 
| 1 2 3 | defmodule Bookcollection.GenreView do use Bookcollection.Web, :view end | 
<%= for book <- @books do %> <% end %>
| <%= book.title %> | <%= link ” 削除”, to: book_path(@conn, :delete,book.id), method: :delete %> | 
<%= form_for @book, book_path(@conn, :create), fn f ->%>
タイトル <%= text_input f, :title, placeholder: ” タイトル”,class: “form-control” %>
ISBN <%= text_input f, :isbn, placeholder: “ISBN”, class:”form-control” %>
蔵書の場所 <%= text_input f, :store_loc, placeholder: ” 蔵書の場所”, class: “form-control” %>
<%= select f, :genre_id, @genre %>
<%= submit ” 登録” %>
<% end %>
<%= for genre <- @genres do %> <% end %>
| <%= genre.name %> | <%= link ” 削除”, to: genre_path(@conn, :delete, genre.id), method: :delete %> | 
<%= form_for @genre, genre_path(@conn, :create), fn f-> %>
<%= text_input f, :name, placeholder: ” ジャンル名”,class: “form-control” %>
<%= submit ” 作成” %>
<% end %>