Phoenix 1.3.0 released

@tompave: You can always build archive yourself like:

git clone git@github.com:phoenixframework/phoenix.git
cd phoenix
git checkout v1.3.0
mix deps.get
mix archive.build
mix archive.install

@chrismccord: After uninstall old phoenix and install new archive (also when build archive from source) I have still two phoenix.* tasks:

> mix archive
* hex-0.16.1
* phoenix-1.3.0
Archives installed at: /home/eiji/.asdf/installs/elixir/1.5.0-otp-20/.mix/archives

> mix help
mix                   # Runs the default task (current: "mix run")
mix app.start         # Starts all registered apps
mix app.tree          # Prints the application tree
mix archive           # Lists installed archives
mix archive.build     # Archives this project into a .ez file
mix archive.install   # Installs an archive locally
mix archive.uninstall # Uninstalls archives
mix clean             # Deletes generated application files
mix cmd               # Executes the given command
mix compile           # Compiles source files
mix deps              # Lists dependencies and their status
mix deps.clean        # Deletes the given dependencies' files
mix deps.compile      # Compiles dependencies
mix deps.get          # Gets all out of date dependencies
mix deps.tree         # Prints the dependency tree
mix deps.unlock       # Unlocks the given dependencies
mix deps.update       # Updates the given dependencies
mix do                # Executes the tasks separated by comma
mix escript           # Lists installed escripts
mix escript.build     # Builds an escript for the project
mix escript.install   # Installs an escript locally
mix escript.uninstall # Uninstalls escripts
mix help              # Prints help information for tasks
mix hex               # Prints Hex help information
mix hex.audit         # Shows retired Hex dependencies
mix hex.build         # Builds a new package version locally
mix hex.config        # Reads, updates or deletes Hex config
mix hex.docs          # Fetches or opens documentation of a package
mix hex.info          # Prints Hex information
mix hex.outdated      # Shows outdated Hex deps for the current project
mix hex.owner         # Manages Hex package ownership
mix hex.publish       # Publishes a new package version
mix hex.repo          # Manages Hex repositories
mix hex.retire        # Retires a package version
mix hex.search        # Searches for package names
mix hex.user          # Manages your Hex user account
mix loadconfig        # Loads and persists the given configuration
mix local             # Lists local tasks
mix local.hex         # Installs Hex locally
mix local.public_keys # Manages public keys
mix local.rebar       # Installs Rebar locally
mix new               # Creates a new Elixir project
mix phoenix.gen.html  # Generates controller, model and views for an HTML based resource
mix phoenix.server    # Starts applications and their servers
mix phx.digest        # Digests and compresses static files
mix phx.digest.clean  # Removes old versions of static assets.
mix phx.gen.channel   # Generates a Phoenix channel
mix phx.gen.context   # Generates a context with functions around an Ecto schema
mix phx.gen.embedded  # Generates an embedded Ecto schema file
mix phx.gen.html      # Generates controller, views, and context for an HTML resource
mix phx.gen.json      # Generates controller, views, and context for a JSON resource
mix phx.gen.presence  # Generates a Presence tracker
mix phx.gen.schema    # Generates an Ecto schema and migration file
mix phx.gen.secret    # Generates a secret
mix phx.routes        # Prints all routes
mix phx.server        # Starts applications and their servers
mix profile.cprof     # Profiles the given file or expression with cprof
mix profile.fprof     # Profiles the given file or expression with fprof
mix run               # Runs the given file or expression
mix test              # Runs a project's tests
mix xref              # Performs cross reference checks
iex -S mix            # Starts IEx and runs the default task
2 Likes

phoenix tasks are deprecated and will be removed with 1.4.0 according to release notes.

1 Like

Fixed. Thanks!

1 Like

Confirmed. Thank you for the hard work on this!

Nice. Anything to do to upgrade from rc3 to final, other than bumping versions?

Please be more constructive in your posts/feedback.

I’ve removed the fork resulting from your post.

Hello all,
I tried to follow Writing Web-facing tutorial but when I added the email as credential I got this:

Did you forget to alias the Credential module?

1 Like

All seems correct. I checked migration credential too, but same error.

What @chrismccord wanted to know is, if you have a line like this in your module:

alias FooBar.Credentials

If it is there, please show more of your code.

1 Like

As @chrismccord and @NobbZ wrote, there is no such module as Credentials in your code, so you have to use alias for proper module, namely Ins.Accounts.Credentials as we can see in the screenshot.

1 Like

here are my files:
Credential.ex

defmodule Ins.Accounts.Credential do
  use Ecto.Schema
  import Ecto.Changeset
  alias Ins.Accounts.{Credential, User}


  schema "credentials" do
    field :email, :string
    belongs_to :user, User

    timestamps()
  end

  @doc false
  def changeset(%Credential{} = credential, attrs) do
    credential
    |> cast(attrs, [:email])
    |> validate_required([:email])
    |> unique_constraint(:email)
  end
end

User.ex

defmodule Ins.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias Ins.Accounts.{User, Credential}


  schema "users" do
    field :name, :string
    field :username, :string
    has_one :credential, Credential

    timestamps()
  end

  @doc false
  def changeset(%User{} = user, attrs) do
    user
    |> cast(attrs, [:name, :username])
    |> validate_required([:name, :username])
    |> unique_constraint(:username)
  end
end

Account.ex

defmodule Ins.Accounts do
  @moduledoc """
  The Accounts context.
  """

  import Ecto.Query, warn: false
  alias Ins.Repo

  alias Ins.Accounts.User

  @doc """
  Returns the list of users.

  ## Examples

      iex> list_users()
      [%User{}, ...]

  """
  def list_users do
    User
    |> Repo.all()
    |> Repo.preload(:credential)
  end
  ...
end

So in your InsWeb.Controllers.UserController (I’m guessing it is) at the top of your module definition you need to add something like alias Ins.Accounts.Credentials to bring Credentials into active scope. :slight_smile:

I tried it …before I posted this troubleshoot…I doesn’t work.

We still have not seen your InsWeb.Controllers.UserController code, because it absolutely should work. ^.^

my generated user_controller.ex looks like that:

defmodule InsWeb.UserController do
  use InsWeb, :controller

  alias Ins.Accounts
  alias Ins.Accounts.User
  ## alias Ins.Accounts.Credential

  def index(conn, _params) do
    users = Accounts.list_users()
    render(conn, "index.html", users: users)
  end

  def new(conn, _params) do
    changeset = Accounts.change_user(%User{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"user" => user_params}) do
    case Accounts.create_user(user_params) do
      {:ok, user} ->
        conn
        |> put_flash(:info, "User created successfully.")
        |> redirect(to: user_path(conn, :show, user))
      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

  def show(conn, %{"id" => id}) do
    user = Accounts.get_user!(id)
    render(conn, "show.html", user: user)
  end

  def edit(conn, %{"id" => id}) do
    user = Accounts.get_user!(id)
    changeset = Accounts.change_user(user)
    render(conn, "edit.html", user: user, changeset: changeset)
  end

  def update(conn, %{"id" => id, "user" => user_params}) do
    user = Accounts.get_user!(id)

    case Accounts.update_user(user, user_params) do
      {:ok, user} ->
        conn
        |> put_flash(:info, "User updated successfully.")
        |> redirect(to: user_path(conn, :show, user))
      {:error, %Ecto.Changeset{} = changeset} ->
        render(conn, "edit.html", user: user, changeset: changeset)
    end
  end

  def delete(conn, %{"id" => id}) do
    user = Accounts.get_user!(id)
    {:ok, _user} = Accounts.delete_user(user)

    conn
    |> put_flash(:info, "User deleted successfully.")
    |> redirect(to: user_path(conn, :index))
  end
end

You have commented the alias line. Remove the # in front of it.

That actually will not work in this case. :slight_smile:

Seeing this file is definitely what I needed. I’m guessing, based on counting, that this line is line 45:

    case Accounts.update_user(user, user_params) do

And if so it is failing inside that, so next we need to see your INS.Account module, I bet it is that module that needs the alias (wherever the Credentials.changeset call actually exists is the same module where the alias needs to exist). :slight_smile:

@OvermindDL1 my account module is up. I thought also that I’d add this alias in my Account module but it shown the same result.

Here is the whole content:

defmodule Ins.Accounts do
  @moduledoc """
  The Accounts context.
  """

  import Ecto.Query, warn: false
  alias Ins.Repo

  alias Ins.Accounts.User
#   alias Ins.Accounts.Credential

  @doc """
  Returns the list of users.

  ## Examples

      iex> list_users()
      [%User{}, ...]

  """
  def list_users do
    User
    |> Repo.all()
    |> Repo.preload(:credential)
  end

  @doc """
  Gets a single user.

  Raises `Ecto.NoResultsError` if the User does not exist.

  ## Examples

      iex> get_user!(123)
      %User{}

      iex> get_user!(456)
      ** (Ecto.NoResultsError)

  """
#   def get_user!(id), do: Repo.get!(User, id)
  def get_user!(id) do
    User
    |> Repo.get!(id)
    |> Repo.preload(:credential)
  end

  @doc """
  Creates a user.

  ## Examples

      iex> create_user(%{field: value})
      {:ok, %User{}}

      iex> create_user(%{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def create_user(attrs \\ %{}) do
    %User{}
    |> User.changeset(attrs)
    |> Ecto.Changeset.cast_assoc(:credential, with: &Credential.changeset/2)
    |> Repo.insert()
  end

  @doc """
  Updates a user.

  ## Examples

      iex> update_user(user, %{field: new_value})
      {:ok, %User{}}

      iex> update_user(user, %{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def update_user(%User{} = user, attrs) do
    user
    |> User.changeset(attrs)
    |> Ecto.Changeset.cast_assoc(:credential, with: &Credential.changeset/2)
    |> Repo.update()
  end

  @doc """
  Deletes a User.

  ## Examples

      iex> delete_user(user)
      {:ok, %User{}}

      iex> delete_user(user)
      {:error, %Ecto.Changeset{}}

  """
  def delete_user(%User{} = user) do
    Repo.delete(user)
  end

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking user changes.

  ## Examples

      iex> change_user(user)
      %Ecto.Changeset{source: %User{}}

  """
  def change_user(%User{} = user) do
    User.changeset(user, %{})
  end

  alias Ins.Accounts.Credential

  @doc """
  Returns the list of credentials.

  ## Examples

      iex> list_credentials()
      [%Credential{}, ...]

  """
  def list_credentials do
    Repo.all(Credential)
  end

  @doc """
  Gets a single credential.

  Raises `Ecto.NoResultsError` if the Credential does not exist.

  ## Examples

      iex> get_credential!(123)
      %Credential{}

      iex> get_credential!(456)
      ** (Ecto.NoResultsError)

  """
  def get_credential!(id), do: Repo.get!(Credential, id)

  @doc """
  Creates a credential.

  ## Examples

      iex> create_credential(%{field: value})
      {:ok, %Credential{}}

      iex> create_credential(%{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def create_credential(attrs \\ %{}) do
    %Credential{}
    |> Credential.changeset(attrs)
    |> Repo.insert()
  end

  @doc """
  Updates a credential.

  ## Examples

      iex> update_credential(credential, %{field: new_value})
      {:ok, %Credential{}}

      iex> update_credential(credential, %{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def update_credential(%Credential{} = credential, attrs) do
    credential
    |> Credential.changeset(attrs)
    |> Repo.update()
  end

  @doc """
  Deletes a Credential.

  ## Examples

      iex> delete_credential(credential)
      {:ok, %Credential{}}

      iex> delete_credential(credential)
      {:error, %Ecto.Changeset{}}

  """
  def delete_credential(%Credential{} = credential) do
    Repo.delete(credential)
  end

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking credential changes.

  ## Examples

      iex> change_credential(credential)
      %Ecto.Changeset{source: %Credential{}}

  """
  def change_credential(%Credential{} = credential) do
    Credential.changeset(credential, %{})
  end
end

Awesome, that is what I needed, your earlier post cut it off before it showed the error line. ^.^;

So the error line is:

    |> Ecto.Changeset.cast_assoc(:credential, with: &Credential.changeset/2)

So yeah, the alias line you have commented out really should be all that is required. Actually I’m not sure how that module is even compiling without it since you struct-create the Credential in that file too. o.O?