Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Phoenix Framework - How to update a record in a database and use the PATCH method?

I'm building an app using the Phoenix Framework and I've done all the CRUD action but the Update/Edit one. I've read and the done the Programming Phoenix book but I still can't do the update action. I think the problem is that I need to override the POST method somehow.

This is my changeset for updating:

        def changeset_update(model, params \\ :empty) do
        model
        |> cast(params, [], [])
        |> validate_length(:username, min: 1, max: 20)
        end

My action in the controller:

    def update(conn, %{"user" => user_params, "id" => id}) do
    user      = Repo.get!(User, id) 
    changeset = User.changeset_update(%User{}, user_params)
    IO.puts changeset.valid?

    case Repo.update(changeset) do 
        {:ok, user} ->
            conn
            |> put_flash(:info, "#{user.name} updated successfully!")
            |> redirect(to: user_path(conn, :show, id: id))
        {:error, changeset} ->
            render conn, "edit.html", changeset: changeset, user: user
    end
    end

and my page:

<h1>Edit User</h1>

<%= form_for @changeset, admin_path(@conn, :update, @user), fn f -> %>
	<%= if @changeset.action do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below:</p>
      <ul>
        <%= for {attr, message} <- f.errors do %>
          <li><%= humanize(attr) %> <%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

	<div class="form-group">
		<input type="hidden" name="_method" value="patch">
			<%= text_input f, :name, placeholder: @user.name, 
				class: "form-control" %>

			<%= text_input f, :username, placeholder: @user.username, 
				class: "form-control" %>

			<%= email_input f, :email, placeholder: @user.email, 
				class: "form-control" %>

			<%= text_input f, :client, placeholder: @user.client, 
				class: "form-control" %>

			<%= number_input f, :role, placeholder: @user.role, 
				class: "form-control" %>

			<button type="submit" class="btn btn-primary">Save</button>
	</div>
<% end %>	

<%= link "Update", to: admin_path(@conn, :update, @user.id),
	method: :update, data: [confirm: "Update this user's record?"], 
			class: "btn btn-default btn-xs" %>

(I actually have two buttons because I was trying both ways)

With the first button I get:

    Protocol.UndefinedError at PATCH /admin/users/13

    protocol Phoenix.Param not implemented for [id: "13"]

But I do have the route /admin/users/:id for the :update action in my routes.ex

With the second button I get:

    Phoenix.Router.NoRouteError at POST /admin/users/13

    no route found for POST /admin/users/13 (MyApp.Router)

Which is normal I guess, since I don't have that route for POST.

Can anyone help me solve this please?

like image 691
Sasha Fonseca Avatar asked Nov 25 '15 18:11

Sasha Fonseca


People also ask

Is Phoenix framework fast?

Extreme performanceIn one benchmark test, Elixir with Phoenix framework performed up to 13 times better than Ruby on Rails, and upwards of 50% more performance compared to Node. js and Express. The default performance of Phoenix/Elixir is quite impressive.

Is Phoenix a good framework?

Unlike other frameworks, Phoenix doesn't have a performance productivity tradeoff making it very useful for modern web technologies. It's very efficient for building real-time apps as it contains built-in components like channels that can manage multiple real-time client experiences.

What are plugs in Phoenix?

They are small reusable prices and can be used to transform the connection. Every Phoenix request starts with a connection and then goes deep down by slightly changing it on its way. So Plug is some piece of code which receives a connection, changes it slightly and returns back.


1 Answers

Your PATCH version actually works and gets routed to the update action. The problem is in the line

|> redirect(to: user_path(conn, :show, id: id))

Change that to

|> redirect(to: user_path(conn, :show, id)

and you should be good :-)

like image 161
manukall Avatar answered Oct 14 '22 13:10

manukall