Error during passing more arguments to function delete in controller

Hello,

I have a function in my rack_detail_controller:

  def delete(conn, %{"id" => id, "rack_id" => rack_id}) do   
    rack_detail = Repo.get!(Rack_detail, id)
    Repo.delete!(rack_detail)
    conn
      |> redirect to: "/rack_details/#{rack_id}"
  end

In my show.html.eex there’s:

link "", to: rack_detail_path(@conn, :delete, rack_detail.rack_details_id, rack_detail.rack_id), method: :delete, data: [confirm: "Are you sure?"], class: "icon-trash-empty delete-button"

The show.html.eex doesn’t even want to load itself and the error displays:

[error] #PID<0.404.0> running MdbmsWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: GET /rack_details/1
** (exit) an exception was raised:
    ** (Protocol.UndefinedError) protocol Enumerable not implemented for 1. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Scrivener.Page, Stream

Is it possible to pass 2 values (rack_detail.rack_details_id and rack_detail.rack_id) to function delete in controller?

Please share your router. The rate_detail_path will only work as you called it if you nested the rack resource within it, but we need to see your router to say for sure.

1 Like

Here’s my router

  scope "/", MdbmsWeb do
    pipe_through [:browser, :browser_auth]
    resources "/connections", PageController
    resources "/rack_details", RackDetailController, only: [:show, :delete]
    get "/connections", PageController, :index
  end

Is RackDetail a resource? If so, it seems like you want something like:

resources "/rack_details", RackDetailController do
  resources "/racks", RackController, only: [:show, :delete]
end

If “rack detail” and “rack” are one in in the same resource, then it seems you want to call:

rack_detail_path(@conn, :delete, rack_id)

I didn’t mention that the whole show.html.eex looks like this:

<%= for rack_detail <- @rack_details do %>
<%= link "", to: rack_detail_path(@conn, :delete, rack_detail.rack_details_id, rack_detail.rack_id), method: :delete, data: [confirm: "Are you sure?"], class: "icon-trash-empty delete-button" %>
<% end %>

That’s why I write rack_detail.rack_details_id etc. When I remove this second value (rack_detail.rack_id) and remove it also from controller everything works fine. The problem appears only when I add the second value to the link.

Right, but we need to know what your resources represent. In my previous example, you either need one of those two options, but it will depend on what a @rack_detail or a @rack is. If they are different entities with a has_many relationship, you need the nested route in order to use the rack_detail_path that you provided. If they are the same entity, which is implied by your routes, then you can only pass one resource. Your _id's imply they are different resources, but your routes don’t show that. Can you clarify? Thanks!

1 Like

Yes, you’re right. I apologize for the lack of details.
rack.ex

  schema "racks" do
    field :avbl_u, :string
    field :details, :string
    field :max_u, :string
    field :name, :string
    has_many :rack_detail, Mdbms.Rack_detail
    timestamps()
  end

rack_detail.ex

  schema "rack_details" do
    field :order, :string
    belongs_to :rack, Mdbms.Rack, foreign_key: :rack_id
    timestamps()
  end

I hope it’ll help you.

We still don’t have enough info, but from what I can tell, it sounds like you simply want rack_detail_path(@conn, :delete, rack_detail.rack_details_id)

1 Like

When I put to my code:

rack_detail_path(@conn, :delete, rack_detail.rack_details_id)

everything works fine.

But I also want to pass rack_detail.rack_id to use it in my controller function to redirect, because the URL consists of "/rack_details/ + rack_id and thanks to that rack_id there are displayed devices in the show.html.eex which rack_id == this rack_id.

There’s my def show from rack_detail_controller.ex:

  def show(conn, %{"id" => id}) do
    rack_details = Rack
    |> Rack.rackDetailsQuery(id)
    |> Repo.all

    render(conn, "show.html", rack_details: rack_details)
  end

The function rackDetailsQuery (query) selects all the needed information basing on rack_id forwarded in URL.

To sum up, I need both rack_id and rack_details_id. The first one to redirect after deleting and the second one to just delete the rack_detail which id == rack_details_id

I hope this information will help you understand my issue.