How to get Plug.Conn in model or changeset?

lets say i have some user info stored in conn, with that i need to do some validations in changeset, so how can i get conn info in model or changeset?

def changeset(model, params \\%{}) do
 model
   |> cast(params, [ :name, :phone ])
   |> my_custom_validator
   |> validate_required()
 end

In custom validator i need conn struct

   defp my_custom_validator(changeset) do
      conn_info = Guardian.Plug.current_resource(conn)
   end

where conn in Guardian.Plug.current_resource(conn) is like conn struct we pass it in controller, but i am getting error like web/models/user.ex:84: undefined function conn/0 so how can i get conn info in changeset?

In general --> YouAppName.Endpoint

You already a value in changeset, do you really need conn?

You don’t! Its considered very bad practice to expose conn in your model. If you need information from the conn, pull it out in the controller and add it to params before you call the changeset. Another approach is to create a changeset with an extra parameter and pass what ever data you need in the extra parameter.

TL;DR Don’t expose conn to your model/schema.

3 Likes

for examle lets say i have a changeset which have current password, new passwords,. conn have current logged in user password so to verify old password in changeset and password in conn are valid, i need conn

thanks man for the valuable node

If you’re implementing a form for changing password, then you should be sending the new, confirmed, and current passwords in the params. So, they will arrive in your changeset and you can verify the in the changeset. No need to touch the conn.

There are a few obvious reasons not to expose conn in the changeset.

  1. Now your schema tests need a conn. Yuck
  2. Lets say you decide later to implement password change in a channel, instead of a web request. You don’t have access to the conn in a channel.

Its really about separation of concerns. Controllers deal with the web request and use the model to persist the data. You don’t want to cross that nice separation of concerns by passing a conn to the model.

1 Like

create a changeset in your controller where you have access to “conn” and put a logic for verifying that they – the passwords – are equal in your model. or even create a new function “changeset_password” and use it instead of “changeset”

1 Like

Here is how I do current password validation in Coherence

1 Like

very clear, thanks a lot