6
votes

I'm moving from Rails to Phoenix and running in to an issue that I can't find the answer for.

I've got user authentication set up (by checking for @current_user in a private authenticate function).

I also have a Post model/controller/view (scaffold for those familiar w Rails).

I'd like to automatically fill a Post field with the @current_user ID when the form is submitted (each post will belong to a user) without a form field that the user has to fill in.

In Rails this is pretty straightforward... something like this added to the create action of the post controller works:

@post.user = current_user.id

How do I do this with the Phoenix Framework/Elixir?

Here's the create action in my PostController

  def create(conn, %{"post" => post_params}) do
    changeset = Post.changeset(%Post{}, post_params)

    case Repo.insert(changeset) do
      {:ok, _project} ->
        conn
        |> put_flash(:info, "Please check your email inbox.")
        |> redirect(to: page_path(conn, :thanks))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

Should this type of logic be performed in the controller or the model? or is there a good way to do this in the view (without using a hidden field which isn't secure).

Solution (thanks to Gazler):

  def create(conn, %{"post" => post_params}) do
    current_user = conn.assigns.current_user
    changeset = Post.changeset(%Post{user_id = current_user.id}, post_params)
    case Repo.insert(changeset) do
      {:ok, _project} ->
        conn
        |> put_flash(:info, "Please check your email inbox.")
        |> redirect(to: page_path(conn, :thanks))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end
1

1 Answers

11
votes

You can use the following:

current_user = conn.assigns.current_user
changeset = Post.changeset(%Post{user_id: current_user.id}, post_params)

Or use Ecto.build_assoc/3:

current_user = conn.assigns.current_user
changeset = Ecto.build_assoc(current_user, :posts, post_params)

This assumes you have current_user in your conn.assigns.