获取错误Ecto.Changeset.fetch / 2是未定义的或私有的

时间:2016-07-12 17:55:15

标签: elixir phoenix-framework

我正试图在页面上做一个简单的登录。每当我尝试将我的页面路由到用户注册时,我收到以下错误。

UndefinedFunctionError at GET /users/new
function Ecto.Changeset.fetch/2 is undefined or private. Did you mean one of:

      * fetch_change/2
      * fetch_field/2

这个错误似乎来自Changeset,因为每当我注释掉我的Changeset并只渲染一个空的html页面时它就可以运行。任何帮助将不胜感激。

网/控制器/ user_controller.ex

defmodule Test.UserController do
  use Test.Web, :controller
  alias Test.User

  def new(conn, params) do
    changeset = User.changeset(%User{})
    render conn, "new.html", changeset   
  end

  def show(conn, %{"user_id_hash" => user_id_hash}) do
    render conn, "user_index.html", %{layout: {Test.LayoutView, "react.html"}}
  end

  def create(conn, %{"user" => user_params}) do
    changeset = User.changeset(%User{}, user_params)
    case Repo.insert(changeset) do 
      {:ok, user} ->
        conn
        |> put_flash(:info, "#{user.username} thank you for signing up please check your email to confirm your account.")
        |> redirect(to: page_path(conn, :index))
      {:error, changeset}->
        render(conn, "new.html", changeset: changeset)
    end
  end

end

然后是我在web / models / user.ex中的模型

defmodule Test.User do
  use Test.Web, :model

  #Allows us to query the Database as Repo.
  alias Test.Repo
  #Allows us to use our User model as User.(function)
  alias Test.User

  #These are
  @fields ~w(username email password encrypted_password user_id_hash password_confirmation)a

  #These are the required fields as atoms for the validate_required method.
  @required_fields_atoms ~w(username email password password_confirmation)a

  schema "users" do
    field :username, :string
    field :email, :string
    field :encrypted_password, :string
    field :user_id_hash, :string
    field :account_confirmed, :boolean
    field :confirmation_hash, :string
    field :password, :string, virtual: true
    field :password_confirmation, :string, virtual: true
    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, @fields)
    |> validate_required(@required_fields)
    |> validate_length(:username, min: 6, max: 32)
    |> validate_length(:password, min: 8, max: 100)
    |> validate_confirmation(:password, message: "does not match password")
    |> put_pass_hash()
  end


  def generate_confirmation_token() do
    rand_string = random_string(26)
  end

  defp put_pass_hash(changeset) do
    case changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
        put_change(changeset, :encrypted_password, Comeonin.Bcrypt.hashpwsalt(pass))
      _ -> changeset
    end
  end


  defp random_string(length) do
    :crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
  end

end

运行程序时,错误说它来自

Test.UserController.action/2 (test)
web/controllers/user_controller.ex (line 1)

如果有人可以提供帮助,我永远不会打电话给fetch功能。

编辑添加了堆栈跟踪

[error] #PID<0.365.0> running Test.Endpoint terminated
Server: my-name.c9users.io:8081 (http)
Request: GET /users/new
** (exit) an exception was raised:
    ** (UndefinedFunctionError) function Ecto.Changeset.fetch/2 is undefined or private. Did you mean one of:

      * fetch_change/2
      * fetch_field/2

        (ecto) Ecto.Changeset.fetch(#Ecto.Changeset<action: nil, changes: %{}, errors: [username: {"can't be blank", []}], data: #Test.User<>, valid?: false>, :conn)
        (phoenix_html) lib/phoenix_html/engine.ex:98: Phoenix.HTML.Engine.fetch_assign/2
        (test) web/templates/layout/app.html.eex:11: Test.LayoutView."app.html"/1
        (phoenix) lib/phoenix/view.ex:335: Phoenix.View.render_to_iodata/3
        (phoenix) lib/phoenix/controller.ex:641: Phoenix.Controller.do_render/4
        (test) web/controllers/user_controller.ex:1: Test.UserController.action/2
        (test) web/controllers/user_controller.ex:1: Test.UserController.phoenix_controller_pipeline/2
        (test) lib/test/endpoint.ex:1: Test.Endpoint.instrument/4
        (test) lib/phoenix/router.ex:261: Test.Router.dispatch/2
        (test) web/router.ex:1: Test.Router.do_call/2
        (test) lib/test/endpoint.ex:1: Test.Endpoint.phoenix_pipeline/1
        (test) lib/plug/debugger.ex:93: Test.Endpoint."call (overridable 3)"/2
        (test) lib/test/endpoint.ex:1: Test.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
^C

1 个答案:

答案 0 :(得分:7)

Test.UserController中,这个:

render conn, "new.html", changeset

应该是

render conn, "new.html", changeset: changeset

您获得的奇怪错误是因为Phoenix templates fetch @ variables using Dict.fetch。在这种情况下,您最有可能在模板中的某个位置使用@conn,并且它正在尝试运行Dict.fetch(changeset, :conn)changeset.__struct__.fetch(changeset, :conn)委托给changeset Ecto.Changeset.fetch(changeset, :conn)是一个结构,最后调用TestID StudentID ComponentID Score ------------------------------------- 14919 3445 1 20 14919 3445 4 17 14919 3445 8 20 14919 3445 11 19 14919 3445 13 19 11339 3448 1 15 11339 3448 4 23 11339 3448 8 23 **11339 3448 11 22** 11339 3448 13 20 **14773 3448 1 20** 14773 3448 4 21 **14773 3448 8 23** 14773 3448 11 21 **14773 3448 13 21**