2016-09-18 39 views
1

我學習框架鳳凰。 是將存儲在雲存儲中的圖像模型。在創建圖像時,我計算文件的哈希值,並將其作爲:名稱。我做了一個模型,控制器和視圖。但我不明白爲什麼我收到一個錯誤:phoenix undefined function changeset/3

== Compilation error on file web/models/image.ex == 
** (CompileError) web/models/image.ex:26: undefined function changeset/3 
    (stdlib) lists.erl:1338: :lists.foreach/2 
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6 
    (elixir) lib/kernel/parallel_compiler.ex:116: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1 

我查閱了所有的代碼,但是沒有找到,我打電話Image.changeset有三個參數的地方。 我image.ex:

defmodule Blog.Image do 
    use Blog.Web, :model 

    schema "images" do 
    field :name, :string 
    field :original_name, :string 
    field :filename, :string, virtual: true 

    timestamps 
    end 

    @required_fields ~w(
    name 
    original_name 
    filename 
) 
    @optional_fields ~w() 

    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, @required_fields, @optional_fields) 
    end 

    def create_changeset(struct, params \\ %{}) do 
    struct 
    |> changeset(struct, params) 
    |> generate_name_hash 
    end 

    defp generate_name_hash(changeset) do 
    put_change(changeset, :name, gen_hash_name(changeset[:filename])) 
    end 

    defp gen_hash_name(filename) do 
    hash_name = :crypto.hash(:sha256, File.read(filename)) 
    |> Base.encode16 
    "/"<>slice(hash_name, 0, 2)<>"/"<>slice(hash_name, 2, 2)<>"/"<>slice(hash_name, 4, 2) 
    end 

end 

我image_controller.ex:

defmodule Blog.ImageController do 
    use Blog.Web, :controller 
    plug Addict.Plugs.Authenticated when action in [:new, :create] 

    def new(conn, _params) do 
    changeset = Blog.Image.changeset(%Blog.Image{}) 
    render conn, "new.html", changeset: changeset 
    end 

    def create(conn, %{"image" => image_params}) do 
    full_image_params = %{filename: image_params["image"].path, original_name: image_params["image"].filename} 
    changeset = Blog.Image.create_changeset(%Blog.Image{}, full_image_params) 
    case Blog.Repo.insert(changeset) do 
     {:ok, image} -> 
     conn 
     |> put_flash(:info, "Image created successfully.") 
     |> redirect(to: image_path(conn, :show, image)) 
     {:error, changeset} -> 
     render(conn, "new.html", changeset: changeset) 
    end 
    end 
end 

我new.html.eex:

<%= form_for @changeset, image_path(@conn, :create), [role: "form", multipart: true], fn f -> %> 
    <div class="form-group"> 
    <%= label f, :image, class: "control-label" %> 
    <%= file_input f, :image, class: "form-control" %> 
    <%= error_tag f, :image %> 
    </div> 
    <div class="container"> 
    <div class="form-group"> 
     <%= submit "Submit", class: "btn btn-default" %> 
    </div> 
    </div> 
<% end %> 

回答

2

我相信這一點:

def create_changeset(struct, params \\ %{}) do 
    struct 
    |> changeset(struct, params) 
    |> generate_name_hash 
    end 

應該是

def create_changeset(struct, params \\ %{}) do 
    struct 
    |> changeset(params) 
    |> generate_name_hash 
    end 

因爲|>運算符會將其左側的所有內容作爲函數的第一個參數傳遞給右側。所以你基本上在做changeset(struct, struct, params)

0

堆棧跟蹤告訴你你的錯誤的確切位置: ** (CompileError) web/models/image.ex:26: undefined function changeset/3

我相信你正在嘗試使用cast函數,因爲changeset函數本身並不存在於Ecto changesets中。此外,cast有三個arity,所以你錯過了一個參數。

更改此線26:

def create_changeset(struct, params \\ %{}) do 
    struct 
    |> changeset(struct, params) 
    |> generate_name_hash 
end 

這樣:

def create_changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:name, :original_name, :filename]) #<---- 3rd arg. = 'allowed' 
    |> generate_name_hash 
end 

cast功能需要三個參數cast(data, params, allowed)。所有未明確允許的參數都將被忽略。

就像Mchl說的那樣,函數的結果被傳遞給管道操作中下一個函數的第一個參數(在這個特定的文章中,你不需要明確地通過struct)。

相關問題