Phoenixで生成されるディレクトリの役割

こんにちは！

今回は現在勉強しているElixir/Phoenixについて、『Phoenix Web Development: Create rich web applications using functional programming techniques with Phoenix and Elixir (English Edition)』の情報を参考にPhoenixで生成される各ディレクトリの役割について備忘録的にまとめたいと思います。

洋書からの読み解きになるので、正確ではない部分があるかもしれませんが、何かお気付きの場合にはご指摘お願いします🙇‍♂️

また合わせて、上記書籍はPhoenix1.4対応ではないので、その分一部情報が古い可能性もありますが、今後気付き次第修正していきます🙇‍♂️

##Phoenixでプロジェクト生成時に作成されるディレクトリ&ファイル
```
|--README.md
|--assets
|  |--brunch-config.js
|  |--css
|  |--js
|  |--package.json
|  |--static
|  |--vendor
|--config
|  |--config.exs
|  |--dev.exs
|  |--prod.exs
|  |--prod.secret.exs
|  |--test.exs
|--lib
|  |--testapp
|  |--testapp.ex
|  |--testapp_web
|  |--testapp_web.ex
|--mix.exs
|--priv
|  |--gettext
|  |--repo
|--test
|  |--support
|  |--test_helper.exs
|  |--testapp_web
```

##config directory--アプリケーション及びWebサービスの設定ファイル
Phoenixアプリケーションのデフォルトで生成されるconfig.exs, dev.exs, test.exs, prod.secret.exs, prod.exsがここに配置されています。

・config.exsはMix.Configモジュールを使用してアプリケーション及び依存関係に関する設定を
記述してあり、test, development, productionの全ての環境の中で共通する設定が記述されたています。

・dev.exs, test.exs, prod.exsはそれぞれ開発環境、テスト環境、実行環境ごとに使用する設定ファイルになっています。

・prod.secret.exsはリポジトリなどでは共有されないデータを格納しておくファイルで、GithubやBitbucketにプッシュしても反映されません。
ここにはAPI keysやsecret keys, database passwordなどの共有/公開してはいけない情報を保存させます。

```prod.secret.exs
例)
use Mix.Config

config :appname, AppnameWeb.Endpoint,
  secret_key_base: "****************"

# Configure your database
config :app_name, App_name.Repo,
  username: "postgres",
  password: "postgres",
  database: "appname_prod",
  pool_size: 15

```

##assets directory--フロントエンドに関するファイルを格納
このディレクトリにはフロントエンドに関する全てのファイルが格納されており、images, CSS, JavaScriptはもちろんNPMやWebpackに関するファイルもここにあります。


フロントエンドに関するコードとファイルを他のPhoenixに関するコード・ファイルから完全に切り離すことで、Phoenix開発者がPhoenixをGreatなものにすることに集中できるようになっています。

このようにPhoenixとフロントエンドに関するコード・ファイルを切り離すことで、assetのコンパイルツールはフレームワークの選択とは切り離して選ぶことができるようになっています。


※Phoenix１.3まではコンパイルツールにはBrunchがデフォルトで採用されていましたが、Phoenix1.4からはWebpackに変更されているようです。

##priv directory
・ヘルパーやアプリケーションのセットアップコードが記述されているディレクトリ
・Repoのシードファイルやマイグレーションファイルもここに格納されているほか、`gettext`やPhoenix serverを立ち上げたときに利用されるassetsもここのサブディレクトリである`static`に格納されています。


##test directory--アプリケーションに関する全てのテストを記述する
・アプリケーション生成時に、`(app)_web`ディレクトリと`support`ディレクトリ、`test_helper.exs`ファイルの3つが自動生成されます。

`(app)_web`にはcontroller, contexts, views, templatesなどをカバーするテストが格納され、Phoenixアプリケーションのテストは全てここに記述するようになります。

`support`はその名の通りtestを補助する役割のあるファイルを格納するディレクトリになっていますが、ほとんどの場合でここの設定を変更することはないようです。

そのため、このtestディレクトリ内で行う作業は、そのほとんどが`(app)_web`とそのサブディレクトリでテストに関するコードを記述する時のみのようです。

##other directories--触ることもなく、リモートリポジトリにも反映されない
そのほかに`_build`や`deps`といったディレクトリも自動生成されますが、そのどちらも変更したりするものではなく、Elixirとの依存関係に関わるコードが格納されています。
このディレクトリも`prod.secret.exs`と同じくリモートリポジトリなどでは共有されません。

##lib directory--Phoenixにおける最重要ディレクトリ
・`lib`ディレクトリはアプリケーションそのものが格納されるディレクトリ
・アプリケーション生成時に`lib/sample`と`lib/sample_web`という2つのサブディレクトリが生成される

###lib/sampleディレクトリ
controllersやtemplates、JSON,またはそれに類するようなものは含まれておらず、contextsやschemaを通じたデータベース特有のEctoロジックを記述します。

contextsについては以下参照しました。
[Elixir1.5とPhoenix1.3の変更内容](https://dev.classmethod.jp/server-side/elixir1-5-and-phoenix1-3-changes/)

*スキーマはデータベーステーブルのマッピングで、データの形状を記述するために使用される
*以下参考のため書籍中のコードより引用

```lib/vocial/votes/option.ex

defmodule Vocial.Votes.Option do
  use Ecto.Schema
  import Ecto.Changeset
  alias Vocial.Votes.Option
  alias Vocial.Votes.Poll

  schema "options" do
    field :title, :string
    field :votes, :integer, default: 0

    belongs_to :poll, Poll

    timestamps()
  end

  def changeset(%Option{} = option, attrs) do
    option
    |> cast(attrs, [:title, :votes, :poll_id])
    |> validate_required([:title, :votes, :poll_id])
  end
end
```

###lib/sample_web
・Phoenixにかかるコードの主な部分が格納されているディレクトリで、この中でcontrollersやviews、templatesなどを記述する

・Phoenixがリクエストをどのように解析し、どのように情報をPhoenix routerに伝えるかを決めるendpoint.exもここに格納されている

・Railsではroutes.rbはconfigディレクトリに格納されていたが、Phoenixの場合にはこのディレクトリに格納されている


##終わり
エンジニアを目指して当初はRuby/Rails中心に勉強していたのですが、コミュニティの熱量や「なんとなく面白そう」というところからElixir/Phoenixの勉強も始めました。

Elixir自体の理解もまだまだ薄く、そのためPhoenixの理解もなかなか進みませんが、頭の中の整理も兼ねて、今後も出来るだけ積極的に学んだことを発信していきたいと思います🙇‍♂️