MatijaL

MatijaL

Need help with changeset errors, I have no idea how to approach this problem

Hi,

I have this project that I’m building as I’m learning Phoenix and I got stuck yesterday and have no idea how to fix or even approach this problem.

So, I have services and those services have orders. After the order is completed, both the seller and buyer can leave reviews. Reviews are in the same db row.

First, there is a template which contains a form

<.form :let={f} for={@review_changeset} action={ ~p"/orders/#{@order.slug}" } as="order" method="PATCH">
 <%= label f, :review %>
 <%= textarea f, :review %>
 <%= error_tag f, :review %

  <%= submit "Submit" %>
</.form>

on submit, update function is run which takes the review and then, if the user submitting the review is buyer, it updates attrs with review_buyer, and it does the same for the seller. The reason for that is that the review schema contains review_buyer and review_seller fields

def update_order(%User{} = user, %Order{} = order, %{"order" => %{"review" => review}} = attrs) do
    attrs =
      cond do
        user.id == order.buyer_id ->
          Map.put(attrs, "review", %{"review_buyer" => review})
        user.id == order.seller_id ->
          Map.put(attrs, "review", %{"review_seller" => review})
        true ->
          attrs
        end

    order
    |> Order.review_changeset(attrs)
    |> Repo.update()

Changeset

def changeset(%Review{} = review, attrs) do
    review
    |> cast(attrs, [:review_buyer, :review_seller])
    |> validate_review()
  end

  defp validate_review(changeset) do
    cond do
      get_change(changeset, :review_buyer) ->
        changeset
        |> validate_length(:review_buyer, min: 10, max: 250)

      get_change(changeset, :review_seller) ->
        changeset
        |> validate_length(:review_seller, min: 10, max: 250)

      true ->
        changeset
      end
  end

Now, this all works, but the problem is showing errors. If there is a changeset error, error is set to review_buyer or review_seller field which does not exist in the form. Form has only review field. How do I transform errors to show for review field? Or should I take a completely different approach here?

Marked As Solved

codeanpeace

codeanpeace

I think your gut is onto something here.

Since you already know whether the logged in user is a buyer or seller, it makes sense to just directly render the appropriately specified textarea input.

# assuming a `review_type` assign is set on LiveView/Component `mount` to either `:review_buyer` or `:review_seller`

<.form :let={f} for={@review_changeset} action={ ~p"/orders/#{@order.slug}" } as="order" method="PATCH">
 <%= label f, @review_type %>
 <%= textarea f, @review_type %>
 <%= error_tag f, @review_type %

  <%= submit "Submit" %>
</.form>

Also Liked

thomas.fortes

thomas.fortes

In this case the solution presented is simple enough, but in more complex forms (or forms where you have to massage the data a lot before saving) you can use a changeset for the form where you can handle the errors and another changeset for the persistence layer.

  def form_changeset(%Review{} = review, attrs) do
    review
    |> cast(attrs, [:review])
    |> validate_length(:review, min: 10, max: 250)
  end

<.form :let={f} for={@review_changeset} action={ ~p"/orders/#{@order.slug}" } as="order" method="PATCH">
 <%= label f, :review %>
 <%= textarea f, :review %>
 <%= error_tag f, :review %

  <%= submit "Submit" %>
</.form>

Should show the errors in the form when validating, then, before you save you should get if the user is seller or buyer and update the map received from the form accordingly to pass to the changeset that will validate it before saving.

Where Next?

Popular in Questions Top

Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement