[] Phoenix 1.3 |
Phoenix Framework . , 1.3 ( RC2).
. . LonestarElixir, . , Phoenix.
!
Phoenix . , , . , . , ?
Phoenix : lib/
web/
. :
lib/
.web/
.? ߠ .
-? Phoenix? ? lib/
Phoenix- ? Phoenix.
1.2 web/
. , - lib/
, - web/
?
: - ( ) web
- ? (, Django)?
.
, , Phoenix, . :
defmodule Example.UserController do
use Example.Web, :controller
# ...
def update(conn, %{"id" => id, "user" => user_params}) do
user = Repo.get!(User, id)
changeset = User.changeset(user, user_params)
case Repo.update(changeset) do
{:ok, user} ->
render(conn, Example.UserView, "show.json", user: user)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(Example.ChangesetView, "error.json", changeset: changeset)
end
end
end
, ? , . render/4
, ? . Phoenix : !
, . , . , , .
- Ecto
. 蠫? ࠗ . . , Django Rails. Elixir , Ecto
.
models/
. . ? ? .
, models/
-, . fat models. , , Phoenix .
Ѡ . .
Phoenix:
mix archive.install
https://github.com/phoenixframework/archives/raw/master/phx_new.ez
, . mix help
- :
mix phoenix.new # Creates a new Phoenix v1.1.4 application
mix phx.new # Creates a new Phoenix v1.3.0-rc.1 application using the experimental generators
: . phoenix
, 堗 phx
. . , , : , - .
, :
mix phx.new medium_phx_example --no-html --no-brunch
- , . --no-html
html
, phx.gen.html
. json
API, html
. --no-brunch
: brunch
- .
, : -? , . Ƞ . - lib/
. , , - . -. . lib/
. Ƞ , web-. :
lib
+-- medium_phx_example
+-- application.ex
+-- repo.ex
+-- web
+-- channels
| +-- user_socket.ex
+-- controllers
+-- endpoint.ex
+-- gettext.ex
+-- router.ex
+-- views
| +-- error_helpers.ex
| +-- error_view.ex
+-- web.ex
medium_phx_example
. . , .
web.ex
:
defmodule MediumPhxExample.Web do
def controller do
quote do
use Phoenix.Controller, namespace: MediumPhxExample.Web
import Plug.Conn
# Before 1.3 it was just:
# import MediumPhxExample.Router.Helpers
import MediumPhxExample.Web.Router.Helpers
import MediumPhxExample.Web.Gettext
end
end
# Some extra code:
# ...
end
Phoenix .Web
, .
. web/models/
, . . :
: Audio
. Audio
Album
Song
:
mix phx.gen.json Audio Album albums name:string release:utc_datetime
mix phx.gen.json Audio Song songs album_id:references:audio_albums name:string duration:integer
. , . audio_albums
, . Ƞ :
lib
+-- medium_phx_example
+-- application.ex
+-- audio
| +-- album.ex
| +-- audio.ex
| +-- song.ex
+-- repo.ex
+-- web
+-- channels
| +-- user_socket.ex
+-- controllers
| +-- album_controller.ex
| +-- fallback_controller.ex
| +-- song_controller.ex
+-- endpoint.ex
+-- gettext.ex
+-- router.ex
+-- views
| +-- album_view.ex
| +-- changeset_view.ex
| +-- error_helpers.ex
| +-- error_view.ex
| +-- song_view.ex
+-- web.ex
?
web/
, models/
. Ƞ . . :
defmodule MediumPhxExample.Audio.Album do
use Ecto.Schema
schema "audio_albums" do
field :name, :string
field :release, :utc_datetime
timestamps()
end
end
defmodule MediumPhxExample.Audio.Song do
use Ecto.Schema
schema "audio_songs" do
field :duration, :integer
field :name, :string
field :album_id, :id
timestamps()
end
end
. , changeset/2
- . belongs_to
. .
, : ࠗ -. , :
defmodule MediumPhxExample.Audio do
@moduledoc """
The boundary for the Audio system.
"""
import Ecto.{Query, Changeset}, warn: false
alias MediumPhxExample.Repo
alias MediumPhxExample.Audio.Album
def list_albums do
Repo.all(Album)
end
def get_album!(id), do: Repo.get!(Album, id)
def create_album(attrs \\ %{}) do
%Album{}
|> album_changeset(attrs)
|> Repo.insert()
end
# ...
defp album_changeset(%Album{} = album, attrs) do
album
|> cast(attrs, [:name, :release])
|> validate_required([:name, :release])
end
alias MediumPhxExample.Audio.Song
def list_songs do
Repo.all(Song)
end
def get_song!(id), do: Repo.get!(Song, id)
def create_song(attrs \\ %{}) do
%Song{}
|> song_changeset(attrs)
|> Repo.insert()
end
# ...
defp song_changeset(%Song{} = song, attrs) do
song
|> cast(attrs, [:name, :duration])
|> validate_required([:name, :duration])
end
end
: , ! , . .
- . . , :
defmodule MediumPhxExample.Web.AlbumController do
use MediumPhxExample.Web, :controller
alias MediumPhxExample.Audio
alias MediumPhxExample.Audio.Album
action_fallback MediumPhxExample.Web.FallbackController
# ...
def update(conn, %{"id" => id, "album" => album_params}) do
album = Audio.get_album!(id)
with {:ok, %Album{} = album} <- Audio.update_album(album, album_params) do
render(conn, "show.json", album: album)
end
end
# ...
end
update/2
.
, . . .
. fallback_controller
. . :
defmodule MediumPhxExample.Web.FallbackController do
@moduledoc """
Translates controller action results into valid `Plug.Conn` responses.
See `Phoenix.Controller.action_fallback/1` for more details.
"""
use MediumPhxExample.Web, :controller
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
conn
|> put_status(:unprocessable_entity)
|> render(MediumPhxExample.Web.ChangesetView, "error.json", changeset: changeset)
end
def call(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> render(MediumPhxExample.Web.ErrorView, :"404")
end
end
, Audio.update_album(album, album_params)
{:ok, %Album{} = album}
? , action_fallback
. Ƞ call/2
, . . .
. , , , . Ƞ Phoenix-Way
. , Phoenix Framework . GitHub.
. ElixirLangMoscow, , . 3 , . .