I have a column in my Postgres Database named “adjust_expense_from_income” data_type Decimal, I have retrieved the card details by triggering the function
cards = GameOfFortune.Repo.all(query)
which provides me all the cards as I need. In the template view, I have to check the “adjust_expense_from_income” if it is zero then show different edit links else show another edit link. But it is always going to If condition and not in the else condition. Out of 10 rows in my cards 7 rows contain value as zero for the column name " adjust_expense_from_income" and rest 3 have “adjust_expense_from_income” > zero but it not working as I expect why?
Below is the code of my view
<%= if card.adjust_expense_from_income >0 do %>
<%= link "Edit", to: Routes.admin_path(@conn, :edit_debt_card_adjust_income,card.id), class: "" %>
<% else %>
<%= link "Edit", to: Routes.admin_path(@conn, :edit_debt_card_single,card.id), class: "" %>
<% end %>
The reason we can compare different data types is pragmatism. Sorting algorithms don’t need to worry about different data types in order to sort. The overall sorting order is defined below:
number < atom < reference < function < port < pid < tuple < map < list < bitstring
Ultimately Decimal is a struct, which at the core is a map which will always be greater than a number which is what 0 is.
<%= if Decimal.gt?(card.adjust_expense_from_income, 0) do %>
<%= link "Edit", to: Routes.admin_path(@conn, :edit_debt_card_adjust_income,card.id), class: "" %>
<% else %>
<%= link "Edit", to: Routes.admin_path(@conn, :edit_debt_card_single,card.id), class: "" %>
<% end %>
Note: The Decimal module functions tend to accept the decimal() sum (union) type which is defined as: decimal() :: t() | integer() | String.t() i.e.:
How can I use my own function created in the card module so that I just call the function instead of applying if… else condition in template view. Let’s say if I create a function in the card module as shown below:
def get_debt_card_type(card) do
case do
card.option_two_description && card.option_one_description ->
:double_option
Decimal.gt?(card.adjust_expense_from_income, 0) ->
:adjust_income
_ ->
:single_option
end
end
When I created this function it giving me an error shown below: " the function “case” cannot handle clauses with the -> operator because it is not a macro "
How can I make it correct and second how can I call it in my view where I am using if … else clause.
# hello/lib/hello/domain/card.ex
defmodule Hello.Domain.Card do
alias __MODULE__
defstruct(
option_one_description: nil,
option_two_description: nil,
adjust_expense_from_income: Decimal.new(0)
)
def new() do
%Card{}
end
def new(one, two, value) do
%Card{
option_one_description: one,
option_two_description: two,
adjust_expense_from_income: value
}
end
def get_debt_card_type(%Card{
option_one_description: one,
option_two_description: two,
adjust_expense_from_income: value
}) do
cond do
two && one ->
:double_option
Decimal.gt?(value, 0) ->
:adjust_income
true ->
:single_option
end
end
end
# hello/lib/hello_web/controllers/page_controller.ex
defmodule HelloWeb.PageController do
use HelloWeb, :controller
def index(conn, _params) do
list = [
Hello.Domain.Card.new("", "", Decimal.new(0)),
Hello.Domain.Card.new(nil, nil, Decimal.new("0.25")),
Hello.Domain.Card.new()
]
render(conn, "index.html", cards: list)
end
end
# hello/lib/hello_web/views/page_view.ex
defmodule HelloWeb.PageView do
use HelloWeb, :view
# added
alias Hello.Domain.Card
def debt_card_link(conn, card) do
case Card.get_debt_card_type(card) do
:double_option ->
link("Double", to: Routes.page_path(conn, :index))
:adjust_income ->
link("Adjust", to: Routes.page_path(conn, :index))
_ ->
link("Single", to: Routes.page_path(conn, :index))
end
end
end
<!-- hello/lib/hello_web/templates/page/index.html.eex -->
<section>
<%= for card <- @cards do %>
<p><%= debt_card_link(@conn, card) %></p>
<% end %>
</section>