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
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
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.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









