【发布时间】:2017-03-09 23:25:18
【问题描述】:
我开始研究凤凰,尝试将图片附加到帖子和Amazon s3上的负载。制作模型,使用这篇文章http://learningelixir.joekain.com/elixir-arc-with-a-single-module/,制作控制器。提交表单时收到错误消息:
[info] POST /posts
[debug] Processing by Blog.PostController.create/2
Parameters: %{"_csrf_token" => "DkM9WAdYfxQ/dS0qQjU/FBILIic+NgAAaqE2D6FDOMICwTlVGaxnUQ==", "_utf8" => "✓", "post" => %{"body" => "789", "image" => %Plug.Upload{content_type: "image/jpeg", filename: "basilico.jpg", path: "/tmp/plug-1473/multipart-108288-12435-6"}, "title" => "6363"}}
Pipelines: [:browser]
[debug] QUERY OK db=0.0ms
begin []
[debug] QUERY OK db=0.3ms
INSERT INTO "posts" ("body","title","user_id","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" ["789", "6363", 5, {{2016, 9, 5}, {20, 44, 48, 0}}, {{2016, 9, 5}, {20, 44, 48, 0}}]
[debug] QUERY OK db=123.3ms
commit []
[info] Sent 400 in 130ms
[debug] ** (Ecto.CastError) expected params to be a map, got: `%Plug.Upload{content_type: "image/jpeg", filename: "basilico.jpg", path: "/tmp/plug-1473/multipart-108288-12435-6"}`
(ecto) lib/ecto/changeset.ex:343: Ecto.Changeset.do_cast/4
(blog) web/models/image.ex:19: Blog.Image.changeset/2
(blog) web/controllers/post_controller.ex:28: Blog.PostController.create/2
(blog) web/controllers/post_controller.ex:1: Blog.PostController.action/2
(blog) web/controllers/post_controller.ex:1: Blog.PostController.phoenix_controller_pipeline/2
(blog) lib/blog/endpoint.ex:1: Blog.Endpoint.instrument/4
(blog) lib/phoenix/router.ex:261: Blog.Router.dispatch/2
(blog) web/router.ex:1: Blog.Router.do_call/2
(blog) lib/blog/endpoint.ex:1: Blog.Endpoint.phoenix_pipeline/1
(blog) lib/plug/debugger.ex:122: Blog.Endpoint."call (overridable 3)"/2
(blog) lib/blog/endpoint.ex:1: Blog.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
我的post.ex
defmodule Blog.Post do
use Blog.Web, :model
schema "posts" do
field :title, :string
field :body, :string
has_one :image, Blog.Image
belongs_to :user, Blog.User
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:title, :body, :user_id])
|> validate_required([:title, :body, :user_id])
end
end
我的图片.ex:
defmodule Blog.Image do
use Blog.Web, :model
alias Blog.Uploaders
schema "images" do
field :name, :string
field :upload, :any, virtual: true
belongs_to :post, Blog.Post
timestamps
end
@required_fields ~w(name)
@optional_fields ~w()
def changeset(model, params \\ %{}) do
model
|> cast(params, ~w(upload), [])
|> put_name
|> cast(params, @required_fields, @optional_fields)
end
def put_name(changeset) do
case changeset do
%Ecto.Changeset{
valid?: true,
changes: %{upload: %Plug.Upload{content_type: "image/" <> _, filename: name}}
} ->
put_change(changeset, :name, name)
_ ->
changeset
end
end
def store(%Plug.Upload{} = upload, image) do
Uploaders.PostImage.store({upload, image})
end
def url(image, version) do
Uploaders.PostImage.url({image.name, image}, version)
end
end
我的上传者/post_image.ex:
defmodule Blog.Uploaders.PostImage do
use Arc.Definition
@acl :public_read
@versions [:original, :show, :thumb]
@heights %{
show: 315,
thumb: 30
}
def validate({file, _}) do
~w(.jpg .jpeg .gif .png) |> Enum.member?(Path.extname(file.file_name))
end
def transform(:thumb, _file) do
{:convert, "-thumbnail x#{@heights[:thumb]} -gravity center -format jpg"}
end
def transform(:show, _file) do
{:convert, "-strip -resize x#{@heights[:show]} -gravity center -format png"}
end
def storage_dir(version, {_, image}) do
"uploads/posts/#{image.post_id}/images/#{image.id}/#{version}"
end
def filename(_version, {file, _}) do
Path.rootname(file.file_name)
end
end
还有我的 post_controller.ex:
def create(conn, %{"post" => post_params}) do
user = Addict.Helper.current_user(conn)
# user = Blog.Repo.get(Blog.User, user.id)
changeset = Blog.Post.changeset(%Blog.Post{}, Map.put(post_params, "user_id", user.id))
case Blog.Repo.insert(changeset) do
{:ok, post} ->
image_params = Blog.Image.changeset(%Blog.Image{}, post_params["image"])
image = Ecto.Model.build_assoc(post, :image, image_params)
Blog.Repo.insert!(image)
conn
|> put_flash(:info, "Post created successfully.")
|> redirect(to: post_path(conn, :show, post))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
问题:如何解决这个错误?即使我应该尝试创建一个图像?
【问题讨论】:
-
您介意发布整个堆栈跟踪吗?
-
@KeithA 当然,更新帖子
-
好的,我相信我可能已经找到了您的问题。在
post_controller.ex的create函数中,您将Plug.Upload结构传递给Blog.Image.changeset函数的第二个参数。基本上,Blog.Image.changeset(%Blog.Image{}, post_params["image"])应该是Blog.Image.changeset(%Blog.Image{}, a_map)其中a_map应该是一个映射而不是Plug.Upload结构 -
谢谢@KeithA!我在
upload_params = %{content_type: post_params["image"].content_type, filename: post_params["image"].filename, path: post_params["image"].path}; image_params = Blog.Image.changeset(%Blog.Image{}, upload_params); image = Ecto.Model.build_assoc(post, :image, image_params)上替换了操作代码 create(我希望我已经正确理解了你),但现在我得到一个不同的错误:` ** (UndefinedFunctionError) function Ecto.Model.build_assoc/3 is undefined or private。您的意思是以下之一:* build/2 * build/3 ` -
对不起,我发现了一个错误
image = Ecto.build_assoc(post, :image, image_params),但是最后插入的记录没有名字:INSERT INTO "images" ("post_id","inserted_at","updated_at") VALUES ($1,$2,$3) RETURNING "id" [18, {{2016, 9, 5}, {21, 42, 46, 0}}, {{2016, 9, 5}, {21, 42, 46, 0}}]