'Elixir, database, restore data every single month do default
I do have a database structure denoted like that:
schema "users" do
field :april, :integer
field :august, :integer
field :december, :integer
field :february, :integer
field :january, :integer
field :july, :integer
field :june, :integer
field :march, :integer
field :may, :integer
field :name, :string
field :november, :integer
field :october, :integer
field :points, :integer
field :role, :string
field :september, :integer
field :surname, :string
end
And I would like to clear one column every single month, for each user. This column is :points. By clear I mean set up value 0. By default the :points value is set up to 0. I would like also to update each month every column in range :January - :December to value 50, which is set up also by default.
I know how to get a month from the date, but how could I by every single month restore to default values those columns? here is my migration file:
create table(:users) do
add :name, :string
add :surname, :string
add :role, :string
add :points, :integer, default: 0
add :january, :integer, default: 50
add :february, :integer, default: 50
add :march, :integer, default: 50
add :april, :integer, default: 50
add :may, :integer, default: 50
add :june, :integer, default: 50
add :july, :integer, default: 50
add :august, :integer, default: 50
add :september, :integer, default: 50
add :october, :integer, default: 50
add :november, :integer, default: 50
add :december, :integer, default: 50
end
Solution 1:[1]
You can do some limited introspection on the Ecto schemas to see what they have defined as the default value for a field by calling the __struct__/0 function. It will yield some information about the struct's default values:
MyEctoSchema.__struct__()
|> Map.from_struct()
However, whatever values the Ecto struct has are NOT guaranteed to be what is defined inside the database. Remember, there is no requirement for a database to have migrations at all, and the Ecto schemas have no inherent knowledge of how the database may be defined. In other words, it's entirely possible for the migrations to say one thing, the database to say another, and the Ecto schema struct to be defined with yet something different: although they might be strongly aligned, they're all operating independently and they are not sharing any information.
I wrote a package that helps inspect schemas that may be useful: https://hexdocs.pm/inspecto/
Once you have a value, then you can update your records using a standard Ecto update operation.
Unrelated: is there a better name for this table? It seems like it's storing summaries of monthly points, not really anything about "users" at all.
Solution 2:[2]
It sounds like you want a function to execute and detect the start of a month and update the database. That's my interpretation. Adjust the code below if that's not quite right:
defmodule Mateusz do
@months ~w(january february march april may june july august september october november december)a
@start_month_value 50
def start_month(users) do
if NaiveDateTime.utc_now().day == 1 do
users.points == 0
for month <- @months, do: users[month] == @start_month_value
users
end
Presumably you'll want to put the value users back in the database. I'll let you decide if that should be done in the function or by the caller.
As data structures go it might be cleaner for you if you created a months structure and declare an instance of the structure in the users structure. This would allow you to have default values for just the months fields and on the first just reset users.months to new(Months).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Everett |
| Solution 2 | Sinc |
