我开始研究凤凰,试图将图像附加到亚马逊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
my image.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
my uploaders / 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
问题:如何修复此错误?即使我应该尝试创建一个图像?
答案 0 :(得分:0)
在Blog.Image
:
schema
定义应包含upload
类型的字段Blog.Uploaders.PostImage.Type
:
schema "images" do
field :upload, Blog.Uploaders.PostImage.Type
...
end
cast_attachments
:upload
def changeset(model, params \\ %{}) do
model
# NOTE: don't include upload here, or it will be processed twice
|> cast(params, ~w(name), [])
|> put_name
|> cast_attachments(params, [:upload])
end
希望这有帮助。