2016-09-05 5 views
0

Я начал изучать феникс, пытаясь сделать прикрепление изображений к сообщению и нагрузке на Amazon s3. Сделанная модель, используйте эту статью http://learningelixir.joekain.com/elixir-arc-with-a-single-module/, изготовленный контроллер. При отправке формы я получаю сообщение об ошибке:phoenix, upload image, controller

[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 

мой 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 

мой закачивающие/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

@ KeithA, конечно, обновленный пост –

+0

Хорошо, я считаю, что, возможно, нашел вашу проблему. В функции 'create' в' post_controller.ex' вы передаете структуру «Plug.Upload» во второй параметр в функцию «Blog.Image.changeset». В принципе, 'Blog.Image.changeset (% Blog.Image {}, post_params [" image "])' должен быть 'Blog.Image.changeset (% Blog.Image {}, a_map)' где 'a_map' должен быть картой вместо 'Plug.Upload' struct –

ответ

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

Надеется, что это помогает.