$ mix phx.new blogfour
$ cd blogfour
$ mix ecto.create
$ mix phx.server# mix.exs
defp deps do
# ...
{:phx_gen_auth, "~> 0.4.0", only: [:dev], runtime: false},
$ mix deps.get
$ mix phx.gen.auth Accounts User users
$ mix deps.get
$ mix ecto.migrate<!-- app.html.eex -->
<%= if @current_user do %>
Hello, you are logged in.
<% end %>generate
$ mix phx.gen.html Content Post posts title:string body:text user_id:references:usersadjust the resulting schema, replacing explicit mention of fk with belongs_to relationship
# post.ex
#field :user_id, :id
belongs_to :user, Blogfour.Accounts.Useradd has_many side of relationship to user schema? TODO
# user.ex
has_many :posts, Blogfour.Content.Post# router.ex
resources "/posts", PostController$ mix ecto.migrate# post_controller.ex
import BlogfourWeb.UserAuth, only: [require_authenticated_user: 2]
plug :require_authenticated_user when action not in [:index, :show]# post_controller.ex
def action(conn, _) do
args = [conn, conn.params, conn.assigns.current_user]
apply(__MODULE__, action_name(conn), args)
end
def index(conn, _params, current_user) do
#...
end
# and so on with show, new, ...etc# post_controller.ex
def create(conn, %{"post" => post_params}, current_user) do
case Content.create_post(current_user, post_params) do
{:ok, post} ->
conn
|> put_flash(:info, "Post created successfully.")
|> redirect(to: Routes.post_path(conn, :show, post))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end# content.ex
alias Blogfour.Accounts
def list_posts do
Repo.all(Post)
Repo.all(Post) |> Repo.preload(:user)
end
def get_post!(id), do: Repo.get!(Post, id) |> Repo.preload(:user)def create_post(%Accounts.User{} = user, attrs \\ %{}) do
%Post{}
|> Post.changeset(attrs)
|> Ecto.Changeset.put_assoc(:user, user)
|> Repo.insert()
end<!-- index -->
<%= post.user.email %>
<!-- show -->
<%= @post.user.email %>$ phx.gen.html Discussion Comment comments content:text post_id:references:posts user_id:references:users# router.ex
resources "/comments", CommentController# router.ex
resources "/posts", PostController do
post "/comment", PostController, :add_local_comment
end
resources "/comments", CommentController# post.ex
has_many :comments, Blogfour.Discussion.Comment# user.ex
has_many :comments, Blogfour.Discussion.Comment# comment.ex
alias Accounts.User
# field :post_id, :id
# field :user_id, :id
belongs_to :user, Blogfour.Accounts.User
belongs_to :post, Blogfour.Content.Post$ touch lib/blogfour_web/templates/post/post_comment_area.html.eex<!-- ... post/show.html.eex -->
<%= render "post_comment_area.html",
post: @post,
changeset: @changeset,
action: Routes.post_post_path(@conn, :add_local_comment, @post) %><!-- post_comment_area.html.eex -->
<div class="comments">
<h3>Comment Form</h3>
<%= form_for @changeset, @action, fn f -> %>
<div class="form-group">
<label>Content</label>
<%= textarea f, :content, class: "form-control" %>
</div>
<div class="form-group">
<%= submit "Add comment", class: "btn btn-primary" %>
</div>
<% end %>
<h3>Comments Shall Be Listed Below</h3>
<%= for comment <- @post.comments do %>
<li><%= comment.content %></li>
<% end %>
</div># post_controller.ex
alias Blogfour.Repo
def show(conn, %{"id" => id}, current_user) do
post = Content.get_post!(id) |> Repo.preload(:comments)
changeset = Comment.changeset(%Comment{}, %{})
render(conn, "show.html", post: post, changeset: changeset)
end# discussion.ex
alias Blogfour.Accounts
def create_related_comment(attrs \\ %{}, %Accounts.User{} = user, post) do
%Comment{}
|> Comment.changeset(attrs)
|> Ecto.Changeset.put_assoc(:post, post)
|> Ecto.Changeset.put_assoc(:user, user)
|> Repo.insert() # |> IO.inspect
end# post_controller.ex
alias Blogfour.Discussion
alias Blogfour.Discussion.Comment
def add_local_comment(conn, %{"comment" => comment_params, "post_id" => post_id}, current_user) do
post = post_id |> Content.get_post!() |> Repo.preload([:comments])
case Discussion.create_related_comment(comment_params, current_user, post) do
{:ok, _comment} ->
conn
|> put_flash(:info, "all good!")
|> redirect(to: Routes.post_path(conn, :show, post))
{:error, _error} ->
conn
|> put_flash(:error, "badness!")
|> redirect(to: Routes.post_path(conn, :show, post))
end
end# discussion.ex
def list_comments do
Repo.all(Comment)
|> Repo.preload(:user)
|> Repo.preload(:post)
end
# ...
def get_comment!(id) do
Repo.get!(Comment, id)
|> Repo.preload(:user)
|> Repo.preload(:post)
end
still gotta make update functions work...