Garey

Coursework

Apr 8th, 2022 (edited)
938
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 31.57 KB | None | 0 0
  1.  
  2. #
  3. # Дефинираме си модул, за да има име структурата, която ще използваме за потребители
  4. #
  5. defmodule User do
  6.   #
  7.   # Дефинираме си структурата и задаваме стойности по подразбиране.
  8.   #
  9.   defstruct username: '', password: '', email: '', sex: '', is_logged_in: false
  10.  
  11.   #
  12.   # Презаписваме to_string метода, за да не изписваме всеки път обекта по възможно най-глупавият начин.
  13.   # Спестява време
  14.   #
  15.   defimpl String.Chars, for: User do
  16.     def to_string(user) do
  17.       #
  18.       # Връщаме многоредов string с информацията от структурата.
  19.       #
  20.       """
  21.      Username: #{user.username}
  22.      Password: #{user.password}
  23.      Email: #{user.email}
  24.      Sex: #{user.sex}
  25.      Is Logged In: #{user.is_logged_in}
  26.      """
  27.     end
  28.   end
  29. end
  30.  
  31. #
  32. # Дефинираме си модул, който ще използва структура, която ще служи за следене на състоянието на приложението ни
  33. #
  34. defmodule AppState do
  35.   #
  36.   # В структурата имаме текущият потребител, който е влязъл и списък от потребители. Задаваме им стойности
  37.   # по подразбиране.
  38.   #
  39.   defstruct currentUser: %User{}, users: []
  40.  
  41.   #
  42.   # Презаписваме to_string метода, за да не изписваме всеки път обекта по възможно най-глупавият начин.
  43.   # Спестява време
  44.   #
  45.   defimpl String.Chars, for: AppState  do
  46.     def to_string(state) do
  47.       """
  48.      Current User:
  49.        Username: #{state.currentUser.username}
  50.        Password: #{state.currentUser.password}
  51.        Email: #{state.currentUser.email}
  52.        Sex: #{state.currentUser.sex}
  53.        Is Logged In: #{state.currentUser.is_logged_in}
  54.  
  55.      Total #{Enum.count(state.users)} users registered
  56.      """
  57.     end
  58.   end
  59. end
  60.  
  61. #
  62. # Дефинираме си модула за приложението ни, което ще използва GenServer, за да обработва заявки с име Database
  63. #
  64. defmodule Database do
  65.  
  66.   #
  67.   # Казваме, че искаме да използваме GenServer имплементацията в нашият модул
  68.   #
  69.   use GenServer
  70.  
  71.   #
  72.   # Създаваме си метод, чрез който да стартираме нашият сървър, като приема за текущо състояние
  73.   # нашата структура за състояние, която си направихме - AppState
  74.   #
  75.   def start_link(), do: GenServer.start_link(__MODULE__, %AppState{})
  76.  
  77.   #
  78.   # Създаваме си метод, чрез който да спираме нашият сървър с параметри на process id(pid), причина за спиране
  79.   # на сървъра(:normal) и време за което да се спре (:infinity).
  80.   #
  81.   def stop(pid), do: GenServer.stop(pid, :normal, :infinity)
  82.  
  83.   #
  84.   # Implementations
  85.   #
  86.  
  87.   #
  88.   # Създаваме си два метода за инициализация и за терминиране.
  89.   # Извикват се, когато се стартира сървъра успешно и когато е извикан метода stop.
  90.   #
  91.   @impl true
  92.   def init(users) do
  93.     {:ok, users}
  94.   end
  95.  
  96.   @impl true
  97.   def terminate(_reason, _state) do
  98.     :ok
  99.   end
  100.  
  101.   #
  102.   # Тук си създаваме методи, които клиента може да използва, за да управлява състоянието на приложението си.
  103.   # Примерно: потребителят иска да си създаде акаунт - ще извика Database.create() и ще си въведе информацията.
  104.   #
  105.   #
  106.   # Client Calls
  107.   #
  108.  
  109.   #
  110.   # Дефинираме си метод create, който ще използва handle_call, който се извиква чрез GenServer.call
  111.   # Първият параметър на GenServer.call e process id(pid) на сървъра, който е стартиран.
  112.   # Вторият параметър служи за подаване на специално име, което се използва да различава
  113.   # заявките от различните GenServer.call-ове. Пример: За да разпознае сървъра ни, че искаме
  114.   # да създадем нов потребител, то ние ще му кажем, че името, което ще използваме е :create и
  115.   # ще използваме параметър с име user от неизвестен тип.
  116.   #
  117.   # Следователно в метода долу в handle_call трябва да му кажем, че този метод, който разписваме
  118.   # като код ще използва това име и приема тези параметри, за да можем да обработим заявката,
  119.   # която ще дойде.
  120.   #
  121.   # В следващите методи логиката е същата:
  122.   # GenServer.call(номер на процеса, <уникално име на точката за достъп> или {<уникално име на точката за достъп>, <неограничен брой параметри>})
  123.   #
  124.   # Ако въведем само име на точката за достъп, както е в последният метод show, по този начин казваме, че
  125.   # не искаме да имаме параметри.
  126.   #
  127.   def create(pid, user), do: GenServer.call(pid, {:create, user})
  128.   def login(pid, username, password), do: GenServer.call(pid, {:login, username, password})
  129.   def logout(pid, username), do: GenServer.call(pid, {:logout, username})
  130.   def change_password(pid, username, current_password, new_password), do: GenServer.call(pid, {:change_password, username, current_password, new_password})
  131.   def delete(pid, username), do: GenServer.call(pid, {:delete, username})
  132.   def show(pid), do: GenServer.call(pid, :show)
  133.  
  134.   #
  135.   # Callbacks
  136.   #
  137.  
  138.   #
  139.   # Тук е обработката на командата create от по-горе.
  140.   # @impl true се използва, за да се каже, че ще използваме метода от GenServer-а.
  141.   # Представи си го като наследяване. Няма как да не наследиш методи от интерфейс или абстрактен клас.
  142.   # Може да се напише само на първият метод, който се разписва и нататък не е нужно да се пише.
  143.   #
  144.   # Обратно на метода. Приема три параметъра. Както казахме по-горе, имаме уникално име и подадени от
  145.   # потребителя параметри. На всеки handle_call има още два параметъра.
  146.   #
  147.   # Първият параметър задължително е точката на обработване - <уникално име> или {<уникално име>, <n на брой параметри>}
  148.   # Вторият параметър се използва от GenServer-а и чрез него ние можем да проследим кой е извикал този метод, ако имаме
  149.   # няколко сървъра, които са разделени в клъстер.
  150.   # Третият параметър е текущото състояние на приложението ни или AppState. Състоянието се подава, за да може да се
  151.   # проследи какво се случва с обектите в приложението. Ако веднъж извикаме този метод и създадем потребител успешно,
  152.   # то състоянието на приложението ни ще се обнови и ако извикаме който и да е следващ метод, то в състоянието на
  153.   # приложението ни ще имаме в users масива един потребител, докато приложението ни не се затвори, ако не ги съхраняваме
  154.   # във външен източник - база данни, текстов файл, json файл и други начини.
  155.   #
  156.   @impl true
  157.   def handle_call({:create, user}, _from, state) do
  158.  
  159.     #
  160.     # Проверяваме дали текущият ни потребител е влязъл в
  161.     # акаунта си. По подразбиране горе в структурата is_logged_in
  162.     # е false.
  163.     #
  164.     if not state.currentUser.is_logged_in do
  165.  
  166.       #
  167.       # Ако е влязъл, искаме да проверим дали потребител с
  168.       # подаденото потребителско име или имейл вече съществува
  169.       # в списъка ни с потребители чрез помощта на груповият
  170.       # метод Enum.any и ламбда функцията.
  171.       #
  172.       isUserExisting = Enum.any?(
  173.         state.users,
  174.         #
  175.         # Създаваме си ламбда функцията, която се чете така:
  176.         # За всеки потребител, изпълни тази функция, ако текущият
  177.         # обект е с име на променливата localUser.
  178.         #
  179.         fn localUser ->
  180.           localUser.username === user.username or
  181.           localUser.email === user.email
  182.         end
  183.       )
  184.  
  185.       #
  186.       # Ако съществува потребителят в списъка, извеждаме грешка
  187.       # и подаваме текущото състояние напред за следващите
  188.       # методи.
  189.       #
  190.       if isUserExisting do
  191.         #
  192.         # Връщаме отговор (това означава :reply, следователно
  193.         # има и :noreply, ако искаме да не връщаме отговор),
  194.         # в който казваме, че потребителят вече съществува.
  195.         #
  196.         {:reply, 'The user already exists', state}
  197.       else
  198.         #
  199.         # В случай, че не съществува потребителя, добавяме го
  200.         # към списъка с потребители и новият списък ще се върне като
  201.         # резултат в updatedUsers променливата
  202.         #
  203.         # Създаваме си ново състояние на приложението, в което казваме
  204.         # че искаме да подновим списъка с потребители с новият ни
  205.         # потребител вътре в него, затова подаваме обновеният списък
  206.         # на новото състояние като users параметър и използваме
  207.         # старото състояние на текущият потребител, понеже не искаме
  208.         # автоматично да си влиза в акаунта. Може да иска да прави още
  209.         # потребители.
  210.         #
  211.         updatedUsers = [user|state.users]
  212.         updatedState = %AppState{currentUser: state.currentUser, users: updatedUsers}
  213.  
  214.         #
  215.         # Връщаме отговор с новото състояние на приложението ни
  216.         #
  217.         {:reply, updatedState, updatedState}
  218.       end
  219.     else
  220.       #
  221.       # Ако случайно се опитаме да направим потребител, докато сме
  222.       # в някой друг потребител, ще ни върне този резултат.
  223.       #
  224.       {:reply, 'You are already logged in', state}
  225.     end
  226.   end
  227.  
  228.   #
  229.   # Принципът на всички handle_call е същият както по-горе описаният.
  230.   #
  231.   def handle_call({:login, username, password}, _from, state) do
  232.  
  233.     #
  234.     # Ако потребителят не е влязъл в профила си
  235.     #
  236.     if not state.currentUser.is_logged_in do
  237.  
  238.       #
  239.       # Проверяваме дали потребителското име и паролата
  240.       # съвпадат с някои от тези в списъка ни с потребители.
  241.       #
  242.       canUserLogIn = Enum.any?(
  243.         state.users,
  244.         fn user ->
  245.           user.username === username or user.email === username
  246.           and
  247.           user.password === password
  248.         end
  249.       )
  250.  
  251.       #
  252.       # Ако успешно намери потребител с такива данни
  253.       #
  254.       if canUserLogIn do
  255.         #
  256.         # Създаваме си една анонимна функция, която ще се
  257.         # преизползва няколко пъти с цел по-изчистен код.
  258.         #
  259.         predicate = fn user -> user.username === username end
  260.  
  261.         #
  262.         # Създаваме си map или tuple, който ще се използва за
  263.         # съхранение на данни в две променливи
  264.         #
  265.         # Първата - user - ще се използва, за да се намери потребителя
  266.         # по потребителско име и ще изпълни  Enum.find(state.users, false, predicate).
  267.         #
  268.         # Втората - userIndex - ще се използва, за да се намери индекса на
  269.         # потребителя в масива, за да можем да го заменим по-късно с обновената му
  270.         # информация.
  271.         #
  272.  
  273.         {user, userIndex} = {
  274.           Enum.find(state.users, false, predicate),
  275.           Enum.find_index(state.users, predicate)
  276.         }
  277.  
  278.         #
  279.         # Ако успешно е намерен потребителят
  280.         #
  281.         if user do
  282.           #
  283.           # Ще използваме информацията от старият потребител, но ще сменим статуса му
  284.           # на is_logged_in от false на true, защото вече ще е влязъл в акаунта си.
  285.           #
  286.           updatedUser = %User{
  287.             username: user.username,
  288.             password: user.password,
  289.             email: user.email,
  290.             sex: user.sex,
  291.             is_logged_in: true,
  292.           }
  293.  
  294.           #
  295.           # Обновяваме списъка ни с потребители с новият статус на нашият потребител
  296.           #
  297.           updatedList = List.replace_at(state.users, userIndex, updatedUser)
  298.  
  299.           #
  300.           # Обновяваме и състоянието на приложението с намереният и обновеният
  301.           # потребител и обновеният списък с потребители.
  302.           #
  303.           updatedState = %AppState{currentUser: updatedUser, users: updatedList}
  304.  
  305.  
  306.           #
  307.           # Връщаме отговор с обновеното състояние на приложението
  308.           #
  309.           {:reply, updatedState, updatedState}
  310.         end
  311.       else
  312.         #
  313.         # Ако случайно нещо се обърка и потребителят не е нацелил паролата
  314.         # или потребителското си име, връщаме отговор със старото състояние
  315.         # на приложението.
  316.         #
  317.         {:reply, 'Incorrect username/password', state}
  318.       end
  319.     else
  320.       #
  321.       # Ако случайно се опитаме да влезем в друг акаунт, но вече сме влезли,
  322.       # връщаме тази грешка.
  323.       #
  324.       {:reply, 'You are already logged in', state}
  325.     end
  326.   end
  327.  
  328.   #
  329.   # Принципът на всички handle_call е същият както по-горе описаният.
  330.   #
  331.   def handle_call({:logout, username}, _from, state) do
  332.     #
  333.     # Ако потребителят е влязъл в профила си и ако името му отговаря на
  334.     # името на текущият потребител.
  335.     #
  336.     if state.currentUser.is_logged_in and username === state.currentUser.username do
  337.       #
  338.       # Създаваме си една анонимна функция, която ще се
  339.       # преизползва няколко пъти с цел по-изчистен код.
  340.       #
  341.       predicate = fn user -> user.username === username end
  342.  
  343.       #
  344.       # Създаваме си map или tuple, който ще се използва за
  345.       # съхранение на данни в две променливи
  346.       #
  347.       # Първата - user - ще се използва, за да се намери потребителя
  348.       # по потребителско име и ще изпълни  Enum.find(state.users, false, predicate).
  349.       #
  350.       # Втората - userIndex - ще се използва, за да се намери индекса на
  351.       # потребителя в масива, за да можем да го заменим по-късно с обновената му
  352.       # информация.
  353.       #
  354.       {user, userIndex} = {
  355.         Enum.find(state.users, false, predicate),
  356.         Enum.find_index(state.users, predicate)
  357.       }
  358.  
  359.       #
  360.       # Ако успешно е намерен потребителят
  361.       #
  362.       if user do
  363.         #
  364.         # Ще използваме информацията от старият потребител, но ще сменим статуса му
  365.         # на is_logged_in от true на false, защото вече ще е излязъл от акаунта си.
  366.         #
  367.         updatedUser = %User {
  368.           username: user.username,
  369.           password: user.password,
  370.           email: user.email,
  371.           sex: user.sex,
  372.           is_logged_in: false,
  373.         }
  374.  
  375.         #
  376.         # Обновяваме списъка ни с потребители с новият статус на нашият потребител
  377.         #
  378.         updatedUsers = List.replace_at(state.users, userIndex, updatedUser)
  379.  
  380.         #
  381.         # Обновяваме и състоянието на приложението с намереният и обновеният
  382.         # потребител и обновеният списък с потребители.
  383.         #
  384.         updatedState = %AppState{currentUser: %User{}, users: updatedUsers}
  385.  
  386.         #
  387.         # Връщаме отговор с обновеното състояние на приложението
  388.         #
  389.         {:reply, updatedState, updatedState}
  390.       end
  391.     else
  392.       #
  393.       # Ако случайно се опитаме да излезем от акаунта си, но още не сме влезли,
  394.       # връщаме тази грешка.
  395.       #
  396.       {:reply, 'You are not logged in', state}
  397.     end
  398.   end
  399.  
  400.   #
  401.   # Принципът на всички handle_call е същият както по-горе описаният.
  402.   #
  403.   def handle_call({:change_password, username, current_password, new_password}, _from, state) do
  404.  
  405.     #
  406.     # Ако потребителят е влязъл в профила си и ако името му отговаря на
  407.     # името на текущият потребител.
  408.     #
  409.     if state.currentUser.is_logged_in and username === state.currentUser.username do
  410.       #
  411.       # Създаваме си една анонимна функция, която ще се
  412.       # преизползва няколко пъти с цел по-изчистен код.
  413.       #
  414.       predicate = fn user -> user.username === username end
  415.  
  416.       #
  417.       # Създаваме си map или tuple, който ще се използва за
  418.       # съхранение на данни в две променливи
  419.       #
  420.       # Първата - user - ще се използва, за да се намери потребителя
  421.       # по потребителско име и ще изпълни  Enum.find(state.users, false, predicate).
  422.       #
  423.       # Втората - userIndex - ще се използва, за да се намери индекса на
  424.       # потребителя в масива, за да можем да го заменим по-късно с обновената му
  425.       # информация.
  426.       #
  427.       {user, userIndex} = {
  428.         Enum.find(state.users, false, predicate),
  429.         Enum.find_index(state.users, predicate)
  430.       }
  431.  
  432.       #
  433.       # Ако успешно е намерен потребителят
  434.       #
  435.       if user do
  436.         #
  437.         # Правим си една променлива с проверка дали текущата парола отговаря на
  438.         # потребителската и дали новата парола не е различна от текущата парола.
  439.         #
  440.         canChangePassword = user.password === current_password and new_password != current_password
  441.  
  442.         #
  443.         # Ако проверката мине успешно и потребителя може да си смени паролата
  444.         #
  445.         if canChangePassword do
  446.           #
  447.           # Ще използваме информацията от старият потребител, но ще сменим паролата му
  448.           # на новата парола.
  449.           #
  450.           updatedUser = %User{
  451.             username: user.username,
  452.             password: new_password, # Ето този ред
  453.             email: user.email,
  454.             sex: user.sex,
  455.             is_logged_in: user.is_logged_in,
  456.           }
  457.  
  458.           #
  459.           # Обновяваме списъка ни с потребители с новата парола на нашият потребител
  460.           #
  461.           updatedUsers = List.replace_at(state.users, userIndex, updatedUser)
  462.  
  463.           #
  464.           # Обновяваме и състоянието на приложението с намереният и обновеният
  465.           # потребител и обновеният списък с потребители.
  466.           #
  467.           updatedState = %AppState{currentUser: updatedUser, users: updatedUsers}
  468.  
  469.           #
  470.           # Връщаме отговор с обновеното състояние на приложението
  471.           #
  472.           {:reply, updatedState, updatedState}
  473.         else
  474.           #
  475.           # Ако някой от критериите не отговаря на изискванията за смяна на
  476.           # парола - новата парола е като старата или текущата парола не
  477.           # отговаря на въведената, връщаме тази грешка.
  478.           #
  479.           {:reply, 'There was a problem trying to change your password', state}
  480.         end
  481.       end
  482.     else
  483.       #
  484.       # Ако случайно се опитаме да си сменим паролата на акаунта, но още не сме влезли,
  485.       # връщаме тази грешка.
  486.       #
  487.       {:reply, 'You are not logged in', state}
  488.     end
  489.   end
  490.  
  491.   #
  492.   # Принципът на всички handle_call е същият както по-горе описаният.
  493.   #
  494.   def handle_call({:delete, username}, _from, state) do
  495.     #
  496.     # Ако потребителят е влязъл в профила си и ако името му отговаря на
  497.     # името на текущият потребител.
  498.     #
  499.     if state.currentUser.is_logged_in and state.currentUser.username === username do
  500.       #
  501.       # Създаваме си една анонимна функция, която ще се
  502.       # преизползва няколко пъти с цел по-изчистен код.
  503.       #
  504.       predicate = fn user -> user.username === username end
  505.  
  506.       #
  507.       # Намираме потребителя от списъка с потребители
  508.       # Ако не го намери, по подразбиране връща стойността
  509.       # на вторият параметър - в случая false.
  510.       #
  511.       user = Enum.find(state.users, false, predicate)
  512.  
  513.       #
  514.       # Ако потребителят е намерем и потребителското име отговаря на това на
  515.       # текущият потребител
  516.       #
  517.       if user != false and user.username === state.currentUser.username do
  518.         #
  519.         # Изтриваме потребителят от списъка ни с потребители.
  520.         # Методът връща новият списък без потребителя, който изтрихме.
  521.         #
  522.         updatedUsers = List.delete(state.users, user)
  523.  
  524.         #
  525.         # Обновяваме и състоянието на приложението с празен потребител
  526.         # (понеже си изтрихме акаунта и вече нямаме такъв, автоматично ни
  527.         # изхвърля от акаунта) и обновеният списък с потребители.
  528.         #
  529.         updatedState = %AppState{currentUser: %User{}, users: updatedUsers}
  530.  
  531.         #
  532.         # Връщаме отговор с обновеното състояние на приложението
  533.         #
  534.         {:reply, updatedState, updatedState}
  535.       else
  536.         #
  537.         # Ако потребителското име не отговря, това не е нашият акаунт, следователно
  538.         # връщаме тази грешка.
  539.         #
  540.         {:reply, 'Log into your own account', state}
  541.       end
  542.     else
  543.       #
  544.       # Ако случайно се опитаме да си изтрием акаунта, но още не сме влезли
  545.       # или ако се опитваме да изтрием акаунта на друг потребител,
  546.       # връщаме тази грешка.
  547.       #
  548.       {:reply, 'You are not logged in or trying to delete other user', state}
  549.     end
  550.   end
  551.  
  552.   #
  553.   # Принципът на всички handle_call е същият както по-горе описаният.
  554.   # На този handle_call нямаме параметри, а само уникално име. Параметри
  555.   # не ни трябват, понеже ще визуализираме потребителите от състоянието на
  556.   # приложението ни (state).
  557.   #
  558.   def handle_call(:show, _from, state) do
  559.  
  560.     #
  561.     # Връщаме отговор с текущото състояние на приложението ни
  562.     # Вътре в състоянието има текущ потребител и списък от потребители
  563.     #
  564.     {:reply, state, state}
  565.   end
  566. end
  567.  
  568. #
  569. # Дефинираме основният модул на приложението ни
  570. #
  571. defmodule Main do
  572.   #
  573.   # Дефинираме си и основната функция, която ще се изпълни при стартиране на
  574.   # приложението ни.
  575.   #
  576.   def main do
  577.     #
  578.     # Използваме метода от GenServer за стартиране на сървъра.
  579.     # При успешно стартиране, той ни връща статус :OK, че всичко е наред
  580.     # и идентификатор на процеса(process id или pid), който да използваме
  581.     # за нашите методи.
  582.     #
  583.     {:ok, pid} = Database.start_link()
  584.  
  585.     #
  586.     # Създаваме си два потребителя за пробата с фективна информация
  587.     #
  588.     user =  %User{
  589.       username: 'Kolev',
  590.       password: 'sample',
  591.       email: 'kolev@mypos.com',
  592.       sex: 'Male',
  593.     }
  594.  
  595.     user2 =  %User{
  596.       username: 'Kolev2',
  597.       password: 'sample',
  598.       email: 'kolev2@mypos.com',
  599.       sex: 'Male',
  600.     }
  601.  
  602.     #
  603.     # Използваме нашите методи, които си направихме, за да създадем
  604.     # двата потребителя в нашето приложение и да ги попълним в състоянието
  605.     # на приложението ни.
  606.     #
  607.     Database.create(pid, user)
  608.     Database.create(pid, user2)
  609.  
  610.     #
  611.     # Пробваме да влезем в един от потребителите
  612.     # Може да се види дали е успешно или има грешка ако преди
  613.     # метода се напише IO.puts, както е при logout-а отдолу.
  614.     #
  615.     Database.login(pid, 'Kolev', 'sample')
  616.  
  617.     #
  618.     # Пробваме да излезем от акаунта ни.
  619.     #
  620.     IO.puts  Database.logout(pid, 'Kolev')
  621.  
  622.     #
  623.     # За онагледяване на промяната, използваме няколко реда print за преди и след промяна.
  624.     #
  625.     IO.puts ''
  626.     IO.puts 'Before change'
  627.     IO.puts ''
  628.     #
  629.     # Пробваме да влезем в един от потребителите
  630.     #
  631.     IO.puts Database.login(pid, 'Kolev2', 'sample')
  632.  
  633.     #
  634.     # За онагледяване на промяната, използваме няколко реда print за преди и след промяна.
  635.     #
  636.     IO.puts ''
  637.     IO.puts 'After change'
  638.     IO.puts ''
  639.  
  640.     #
  641.     # Пробваме да сменим паролата на един от потребителите и извеждаме резултата
  642.     #
  643.     IO.puts Database.change_password(pid, 'Kolev2', 'sample', 'sample2')
  644.  
  645.     #
  646.     # За онагледяване на промяната, използваме няколко реда print за преди и след промяна.
  647.     #
  648.     IO.puts ''
  649.     IO.puts 'All Users'
  650.     IO.puts ''
  651.  
  652.     #
  653.     # Използваме метода show, за да вземем всички потребители от списъка
  654.     #
  655.     Enum.map(Database.show(pid).users, fn user -> IO.puts user end)
  656.  
  657.     #
  658.     # За онагледяване на промяната, използваме няколко реда print за преди и след промяна.
  659.     #
  660.     IO.puts ''
  661.     IO.puts 'All Users after delete'
  662.     IO.puts ''
  663.  
  664.     #
  665.     # Изтриваме един потребител от списъка ни
  666.     #
  667.     Database.delete(pid, 'Kolev2')
  668.  
  669.     #
  670.     # Използваме метода show, за да вземем всички потребители от списъка
  671.     #
  672.     Enum.map(Database.show(pid).users, fn user -> IO.puts user end)
  673.  
  674.     #
  675.     # Спираме GenServer-а ни.
  676.     #
  677.     Database.stop(pid)
  678.   end
  679. end
  680.  
  681. #
  682. # Извикваме main метода от модула Main, за да можем да стартираме
  683. # приложението успешно
  684. #
  685. Main.main()
  686.  
Add Comment
Please, Sign In to add comment