对于一个基本的博客应用程序(Post
has_many
comments
),我想在post#show
的末尾显示一个新的注释表单。但我一直被构建它和在web/templates/user/show.html.eex
中渲染web/templates/comment/form.html.eex
的机制所困扰。应用程序:
mix phoenix.new my_app
cd my_app
mix ecto.create
mix phoenix.gen.html Post posts content:string
mix phoenix.gen.html Comment comments content:string
post_id:references:posts
mix ecto.migrate
web/models/post.ex
defmodule MyApp.Post do
use MyApp.Web, :model
schema "posts" do
field :content, :string
has_many :comments, MyApp.Comment
timestamps
end
@required_fields ~w(content)
@optional_fields ~w()
def changeset(model, params \ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
web/models/comment.ex
defmodule MyApp.Comment do
use MyApp.Web, :model
schema "comments" do
field :content, :string
belongs_to :post, MyApp.Post
timestamps
end
@required_fields ~w(content post_id)
@optional_fields ~w()
def changeset(model, params \ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
在Post
控制器中,我遇到了第一个问题。此代码不起作用(key :post not found in: %{}
错误):
web/controller/post_controller.ex
[...]
def show(conn, %{"id" => id}) do
post = Repo.get!(Post, id)
changeset =
conn.assigns.post
|> build_assoc(:comments)
|> Comment.changeset()
render(conn, "show.html", post: post, changeset: changeset)
end
[...]
下一个问题是我不知道如何呈现表单
web/templates/post/show.html.eex
<h2>Show post</h2>
<ul>
<li>
<strong>Content:</strong>
<%= @post.content %>
</li>
</ul>
<%= render "comment/form.html", changeset: @changeset,
action: comment_path(@conn, :create) %>
我该怎么解决这个问题?
-
在
web/controllers/post_controller.ex
中,将conn.assigns.post
仅替换为post
,因为这是变量的实际名称。 -
要从另一个视图渲染模板(要从
web/templates/post/show.html.eex
渲染web/templates/comment/form.html.eex
),需要传递目标模板的视图作为第一个参数:render MyApp.CommentView, "form.html", ...
这是因为控制器中的
render
是Phoenix.Controller.render/4
,而视图和模板中可用的是Phoenix.View.render/3
,并且它们期望不同的参数。