trivialcase
Assign isn't assigning?
I have a piece of code that gets executed on successful user signin, and everything seems to work fine, except that one of my assigned variables isn’t getting assigned by the code, but it works fine when I do it while debugging with pry…
Here is my code:
case TokenAuthentication.verify_token_value(token) do
{:ok, user} ->
conn
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
|> put_flash(:info, "Congratulations, #{user.first_name}, you were signed in successfully.")
|> assign(:current_user, user)
IEx.pry
|> redirect(to: page_path(conn, :index))
and when I pry I have
assigns: %{current_user: nil}
but then I do assign(conn, :current_user, user) at the prompt and I get
assigns: %{current_user: %Myapp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
auth_tokens: #Ecto.Association.NotLoaded<association :auth_tokens is not loaded>,
email: "test@test.com", first_name: "Test", id: 20,
inserted_at: ~N[2017-05-09 13:06:32.374191], last_name: "McTest",
password: nil, password_confirmation: nil,
password_hash: "$2b$12$v8zTVSz0TGJ6COKlGb0TY.pbg3lnpJMZprmjDz3OS6s5aZWIDgsaC",
updated_at: ~N[2017-05-09 13:06:32.374206]}}
as expected. I know that Elixir shouldn’t have side effects, so how is my running it at the prompt different?
Marked As Solved
benwilson512
Your code isn’t quite doing what you think it is. Here it is formatted better:
conn
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
|> put_flash(:info, "Congratulations, #{user.first_name}, you were signed in successfully.")
|> assign(:current_user, user)
# everything prior to this line has now been thrown away, you didn't bind it to anything
IEx.pry
|> redirect(to: page_path(conn, :index))
If I had to guess IEx.pry will return whatever it is you’ve last written in it. So if you assign a conn, that assigned conn will get passed through to the redirect function.
Also Liked
Aetherus
Remember that all data structures in Elixir are immutable, so is a %Plug.Conn{}.
Plug.Conn.assign/3 always returns a new %Plug.Conn{}. So your code should be
conn = conn
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
|> put_flash(:info, "Congratulations, #{user.first_name}, you were signed in successfully.")
|> assign(:current_user, user)
IEx.pry
redirect(conn, to: page_path(conn, :index))
Note that the local variable conn is reassigned.
Aetherus
I’m not familiar with Guardian so excuse me if I’m wrong.
Since you’re using token authentication, the token should be maintained by the client side code (e.g. javascript on the browser side). The client should carry the token on every request whenever the token is available.
However, redirect is a two-step action:
- the browser receives a response with status code
302and aLocationheader, which contains a URL. - the browser sends another
GETrequest immediately to the URL inLocationheader.
Unfortunately, you can’t control the second step. You can’t add headers to it, you can’t specify the HTTP method, you can’t add cookie to it, and you can’t attach token to it. I think this is the reason why you lose the current_user after redirect.
If you are building a single-page application, try not to use redirect. Let Javascript handle page switching.
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
- #javascript
- #code-sync
- #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
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








