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?
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.
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.
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.
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 :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With