script

script

How to increment database table column

I know in elixir data types are immutable. I have a column name failed_login_tries. which is integer and i want to increment it every time user put incorrect password. this is the code

 defp check_chromatic_password(plaintext, %User{} = user) do
   if Bcrypt.checkpw(plaintext, user.local_password_hash) do
      {:ok, user}
   else
     {:error, :invalid_password}
   end
 end

failed_login_tries is inside the %User struct

Marked As Solved

minhajuddin

minhajuddin

You can change the user struct by using user = %{ user | failed_login_tries: user.failed_login_tries + 1} and to persist this in the database use Repo.update by passing it an updated ecto changeset. Immutability refers to the fact that the previous struct remains the same. e.g.

defmodule User do
  defstruct [:email]
end

u1 = %User{email: "mujju"}
u2 = u1
u2 = %{u2 | email: "danny"}

IO.inspect(u1)
# => %User{email: "mujju"}
IO.inspect(u2)
# => %User{email: "danny"}

Also Liked

LostKobrakai

LostKobrakai

There’s an even simpler option to write that query:

from(u in User, update: [inc: [failed_login_tries: 1]], where: u.id == user.id) )
25
Post #3
aseigo

aseigo

Just be aware that there is an inherent race condition with that approach: if the user fails auth in quick succession twice both may have the user record with the current count prior to either auth attempt, and so both will increment the old value by one and update the db with that, causing the N attempts to be counted as just 1!

The correct way to do this is in the database itself using a fragment as in:

from(u in User, 
     update: [set: [failed_login_tries: fragment("failed_login_tries + 1")]],
     where: u.id == user.id) )
|> MyRepo.update_all([])

This way the db sorts out the concurrent updates and you will always end up with the correct count.

11
Post #2
aseigo

aseigo

I always forget about inc (and friends) .. thanks for the reminder!

Last Post!

snofang

snofang

You can use Optimistic Lock feature; This keeps you away from races invalid results and also let you have timestamps functionality in place.

Where Next?

Popular in Questions Top

New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
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
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
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
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
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