Hello, I have a question on proper working with forms and associations.
I have a form to build a search query. Among the fields there are two belongs_to
associations - client and city, which are selected from a select. They can freely be updated later. The only validation is that client must be associated with the current user.
I have a simple select in the form for client_id
and city_id
:
<div>
<%= label f, :client_id, "Client" %>
<%= select f, :client_id, @client_options %>
<%= error_tag f, :client_id %>
</div>
Then in form I have to take the client based on client_id
from params and put it into params like this
defp add_client_param(query_params, socket) do
case query_params["client_id"] do
nil -> query_params
client_id ->
Map.put(
query_params,
"client",
Enum.find(socket.assigns.clients, & &1.id == client_id)
)
end
end
It goes to a simple update function in a context:
def update_query(%Query{} = query, attrs) do
query
|> Query.changeset(attrs)
|> Repo.update()
end
That sends it into changeset
in the model:
def changeset(query, attrs) do
changeset =
query
|> cast(attrs, [])
case attrs[:client] do
nil -> changeset
client ->
changeset
|> put_assoc(:client, attrs[:client])
|> validate_client()
end
end
Since I can’t just pass client
to cast
- I pass it to put_assoc
. But if I do update_query
generic - caller may not want to update client
or other references, so I have to do a case
for each reference that caller may omit instead of doing something like cast([:client])
.
Is it the proper way to do it? Because I strongly feel that I’m missing something.
Are there any good examples doing simple things like this in a “recommended” way?