Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/holidayDB Added work with database #3

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions holiday/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
26 changes: 26 additions & 0 deletions holiday/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
holiday-*.tar

# Temporary files, for example, from tests.
/tmp/
24 changes: 24 additions & 0 deletions holiday/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Holiday

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `holiday` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:holiday, "~> 0.1.0"}
]
end
```

## Coomands
`rm _build/ -r && mix compile`

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/holiday>.

8 changes: 8 additions & 0 deletions holiday/config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Config
config :holiday, ecto_repos: [Holiday.Repo]

config :holiday, Holiday.Repo,
database: "holiday_repo",
username: "postgres",
password: "",
hostname: "localhost"
170 changes: 170 additions & 0 deletions holiday/lib/holiday.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
defmodule Holiday do
import Ecto.Query
alias Holiday.{Repo, Event}

@moduledoc """
Documentation for `Holiday`.
"""

@doc """
Initializing the local database.

"""
@spec init_db() :: []
def init_db() do
path = Path.expand("lib/us-california-nonworkingdays.ics")

{:ok, binary} = File.read(path)

Enum.each(binary |> ICalendar.from_ics(), fn event ->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если нужно создать несколько сущностей сразу, у нас есть выбор из трех решений:

  1. Сделать как у тебя, но тогда нету гарантии, что все сущности будут созданы (напимер, если changeset будет невалидный), так лучше не делать)
  2. Сделать как у тебя, но возвращать массив созданных сущностей и зафейленных %{success_entities: [], failed_entities: []}, тогда мы сможемпонять, что что-то пошло не так
  3. Использовать транзакию вместе с Multi. В таком случае, если какая-то из сущностей не будет создана/обновлена, все изменения будут отменены

P.S исправлять ничего не нужно, твоё решение норм для учебного задания

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В твоём решении блок

      case result do
        {:ok, struct} ->
          {:ok, struct}

        {:error, changeset} ->
          {:error, changeset}
      end

ничего не делает, потому что результатом Enum.each всегда является :ok 😄


result =
case Repo.get_by(Event, uid: event.uid) do
nil -> %Event{uid: event.uid}
myEvent -> myEvent
end
|> Ecto.Changeset.change(%{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше написать отдельный changeset для модели Event
https://hexdocs.pm/ecto/Ecto.Changeset.html

uid: event.uid,
title: event.summary,
dStart: %{DateTime.to_date(event.dtstart) | year: 1970},
dEnd: %{DateTime.to_date(event.dtend) | year: 1970},
rules: event.rrule,
isConfirmed: event.status == "confirmed"
})
|> Holiday.Repo.insert_or_update()

case result do
{:ok, struct} ->
{:ok, struct}

{:error, changeset} ->
{:error, changeset}
end
end)

true
end

@doc """
Returns true if today is a holiday, and false it it's not..

## Parameters

- day: Date that represents the default is today's date or a user-specified date.

## Examples

iex> Holiday.is_holiday(~D[2000-01-01])
true

"""
@spec is_holiday(day :: %Date{}) :: boolean()
def is_holiday(day \\ Date.utc_today()) do
Repo.exists?(from(e in Event, where: e.dStart == ^make_start_date(day)))
end

defp getOneEvent(day, recursion \\ true) do
result =
Repo.one(
from(
e in Event,
where: e.dStart > ^day,
order_by: [asc: e.dStart],
limit: 1
)
)

unless result do
if recursion && getOneEvent(make_start_date(day, 1969), false), do: true, else: false
end

result
end

@doc """
Return a float representing a number of `units till closest holiday in the future.

## Parameters

- unit: Atom. Can be one of :day | :hour | :minute | :second
- now: Date that represents the default is today's date or a user-specified date.

## Examples

iex> Holiday.time_until_holiday(:day, ~U[2022-01-12 00:01:00.00Z])
19.999305555555555

iex> Holiday.time_until_holiday(:hour, ~U[2022-01-12 00:01:00.00Z])
479.98333333333335

"""
@spec time_until_holiday(
unit :: :day | :hour | :minute | :second,
now :: %DateTime{}
) :: float()
def time_until_holiday(unit, now \\ DateTime.utc_now())

def time_until_holiday(:day, now) do
find_nearest(now) / 60 / 60 / 24
end

def time_until_holiday(:hour, now) do
find_nearest(now) / 60 / 60
end

def time_until_holiday(:minute, now) do
find_nearest(now) / 60
end

def time_until_holiday(:second, now) do
find_nearest(now)
end

@doc """
Displays all holidays in the database in the format: Holiday Name: Start Date - End Date.


## Examples

iex> Holiday.show_all_events()
true

"""
@spec show_all_events() :: []
def show_all_events() do
query = from(e in Event)

db = Repo.all(query)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
db = Repo.all(query)
db = Repo.all(Event)

135-ую строку можно удалить


for event <- db do
IO.puts("#{event.title}: #{event.dStart} - #{event.dEnd}")
event
end

true
end

defp make_start_date(date, year \\ 1970) do
Date.new(year, date.month, date.day) |> elem(1)
end

defp make_fake_date_time(%Date{} = date) do
time = Time.new(0, 0, 0, 0) |> elem(1)

DateTime.new(date, time)
|> elem(1)
end

defp make_fake_date_time(%DateTime{} = date) do
%{date | year: 1970}
end

defp find_nearest(date) do
new_date = date |> make_fake_date_time

getOneEvent(DateTime.to_date(new_date) |> make_start_date()).dStart
|> make_start_date
|> make_fake_date_time
|> DateTime.diff(new_date)
end
end
25 changes: 25 additions & 0 deletions holiday/lib/holiday/application.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Holiday.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application

@impl true
def start(_type, _args) do
children = [
Holiday.Repo
# Starts a worker by calling: Friends.Worker.start_link(arg)
# {Friends.Worker, arg}
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: Holiday.Supervisor]
Supervisor.start_link(children, opts)
end

def init(_type, config) do
IO.puts("STARTING REPO")
{:ok, config}
end
end
12 changes: 12 additions & 0 deletions holiday/lib/holiday/holiday.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule Holiday.Event do
use Ecto.Schema

schema "holiday" do
field(:title, :string)
field(:dStart, :date)
field(:dEnd, :date)
field(:uid, :binary_id)
field(:rules, :map)
field(:isConfirmed, :boolean)
end
end
5 changes: 5 additions & 0 deletions holiday/lib/holiday/repo.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule Holiday.Repo do
use Ecto.Repo,
otp_app: :holiday,
adapter: Ecto.Adapters.Postgres
end
13 changes: 13 additions & 0 deletions holiday/lib/mix/tasks/init_db.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Mix.Tasks.InitDb do
use Mix.Task

@shortdoc "Seed database."
def run(_) do
{:ok, _} = Application.ensure_all_started(:holiday)

case Holiday.init_db() do
true -> IO.puts("Completed")
_ -> IO.puts("Error")
end
end
end
13 changes: 13 additions & 0 deletions holiday/lib/mix/tasks/is_holiday.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Mix.Tasks.IsHoliday do
use Mix.Task

@shortdoc "Returns Yes if today is a holiday, and No it it's not."
def run(_) do
{:ok, _} = Application.ensure_all_started(:holiday)

case Holiday.is_holiday() do
true -> IO.puts("Yes")
_ -> IO.puts("No")
end
end
end
Loading