Skip to content

Commit

Permalink
Adds bang versions for each function
Browse files Browse the repository at this point in the history
  • Loading branch information
sobolevn committed Jun 18, 2017
1 parent c0bf80f commit ea886fd
Show file tree
Hide file tree
Showing 22 changed files with 163 additions and 99 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ You need to understand how [grammatical cases](https://en.wikipedia.org/wiki/Gra
### API

```elixir
alias PetrovichElixir.Petrovich

Petrovich.firstname("Александр", :accusative, :male)
# => Александра

Expand Down
3 changes: 2 additions & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ use Mix.Config
# Configure Petrovich to use `rules` submodule:
config :petrovich_elixir,
rules_path: "rules/rules.json",
gender_path: "rules/gender.json"
gender_path: "rules/gender.json",
wrong_path: "rules/missing.json"
16 changes: 13 additions & 3 deletions lib/petrovich_elixir/petrovich.ex → lib/petrovich.ex
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
defmodule PetrovichElixir.Petrovich do
defmodule Petrovich do
@moduledoc """
Public interface to all the functions.
Documentation for Petrovich.
Public interface to all the functions.
It can inflect first, middle, and last names.
It also can detect gender by name.
"""

alias PetrovichElixir.Parser
alias Petrovich.Parser

@default_gender :androgynous

def firstname(name, case_, gender \\ @default_gender) do
Parser.parse(name, :firstname, case_, gender)
end
def firstname!(name, case_, gender \\ @default_gender) do
Parser.parse!(name, :firstname, case_, gender)
end

def middlename(name, case_, gender \\ @default_gender) do
Parser.parse(name, :middlename, case_, gender)
end
def middlename!(name, case_, gender \\ @default_gender) do
Parser.parse!(name, :middlename, case_, gender)
end

def lastname(name, case_, gender \\ @default_gender) do
Parser.parse(name, :lastname, case_, gender)
end
def lastname!(name, case_, gender \\ @default_gender) do
Parser.parse!(name, :lastname, case_, gender)
end
end
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule PetrovichElixir.Applier do
defmodule Petrovich.Applier do
@moduledoc """
Applies rules on value.
Expand Down
2 changes: 1 addition & 1 deletion lib/petrovich_elixir/config.ex → lib/petrovich/config.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule PetrovichElixir.Config do
defmodule Petrovich.Config do
@moduledoc """
Provides application/system environment variable lookup at runtime
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule PetrovichElixir.Detector do
defmodule Petrovich.Detector do
@moduledoc """
Guesses the gender by person's name.
"""
Expand Down
7 changes: 7 additions & 0 deletions lib/petrovich/exceptions.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule Petrovich.Exceptions.ParseException do
defexception message: "Name is not parsed"
end

defmodule Petrovich.Exceptions.RulesFileException do
defexception message: "Rules file is missing"
end
36 changes: 30 additions & 6 deletions lib/petrovich_elixir/parser.ex → lib/petrovich/parser.ex
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
defmodule PetrovichElixir.Parser do
defmodule Petrovich.Parser do
@moduledoc """
Parser receives the name and case to infect it to.
Then it parses the rules to find the appropriate modifications.
It then calls `Applier` to modify the value.
"""

alias PetrovichElixir.{NameStore, Applier}
alias Petrovich.{NameStore, Applier}
alias Petrovich.Exceptions.ParseException

def parse(data, _, :nomenative, _), do: data
def parse(data, _, :nomenative, _), do: {:ok, data}
def parse(data, type, case_, gender) do
apply_rule(data, to_string(type), case_, to_string(gender))
end

def parse!(data, type, case_, gender) do
{status, data} = parse(data, type, case_, gender)

if status == :ok do
data
else
raise ParseException
end
end

defp apply_rule(values, type, case_, gender) do
NameStore.start_link()

values
|> String.split("-")
|> Enum.map(fn(item) -> prepare_value(item, type, case_, gender) end)
|> Enum.join("-")
|> join_result
end

defp prepare_value(value, type, case_, gender) do
Expand All @@ -31,8 +42,21 @@ defmodule PetrovichElixir.Parser do
|> maybe_exception(gender, exceptions)
|> maybe_rule(gender, suffixes)
|> case do
{:error, _} -> value
{:ok, res} -> Applier.apply(value, case_, res)
{:error, _} -> {:error, value}
{:ok, res} -> {:ok, Applier.apply(value, case_, res)}
end
end

defp join_result(results) do
success = Enum.all?(results, fn({status, _}) -> status == :ok end)
joined = results
|> Enum.map(fn({_, item}) -> item end)
|> Enum.join("-")

if success do
{:ok, joined}
else
{:error, joined}
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule PetrovichElixir.Store do
defmodule Petrovich.Store do
@moduledoc """
This module implements basic functionality for different agents.
Expand All @@ -7,7 +7,8 @@ defmodule PetrovichElixir.Store do
caller module.
"""

alias PetrovichElixir.Config
alias Petrovich.Config
alias Petrovich.Exceptions.RulesFileException

defmacro __using__(options) do
caller = __CALLER__.module
Expand Down Expand Up @@ -37,10 +38,15 @@ defmodule PetrovichElixir.Store do
end

defp load_values do
:petrovich_elixir
|> Config.get_env(@setting)
|> File.read!
|> Poison.decode!
try do
:petrovich_elixir
|> Config.get_env(@setting)
|> File.read!
|> Poison.decode!
rescue
e in File.Error ->
raise RulesFileException, message: Exception.message(e)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
defmodule PetrovichElixir.GenderStore do
defmodule Petrovich.GenderStore do
@moduledoc """
This module stores different genders.
It is then used to guess the gender by name,
last name or middle name.
"""

use PetrovichElixir.Store, setting: :gender_path
use Petrovich.Store, setting: :gender_path

@name __MODULE__

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
defmodule PetrovichElixir.NameStore do
defmodule Petrovich.NameStore do
@moduledoc """
This module stores different rules on how to inflect values.
It stores rules for first, middle and last names.
"""

use PetrovichElixir.Store, setting: :rules_path
use Petrovich.Store, setting: :rules_path
end
7 changes: 0 additions & 7 deletions lib/petrovich_elixir.ex

This file was deleted.

2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule PetrovichElixir.Mixfile do
defmodule Petrovich.Mixfile do
use Mix.Project

@version "0.0.1"
Expand Down
20 changes: 0 additions & 20 deletions test/petrovich_elixir_test/public_api_test.exs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule PetrovichElixirTest.ConfigTest do
defmodule PetrovichTest.ConfigTest do
use ExUnit.Case

alias PetrovichElixir.Config
alias Petrovich.Config

test "config can read regular config values" do
Application.put_env(:petrovich_elixir, :test_var, "test")
Expand Down
12 changes: 12 additions & 0 deletions test/petrovich_test/exceptions_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule PetrovichTest.Exceptions.ParseExceptionTest do
use ExUnit.Case

alias Petrovich.Parser
alias Petrovich.Exceptions.ParseException

test "raise ParseException" do
assert_raise ParseException, fn ->
Parser.parse!("bad value", :firstname, :prepositional, :male)
end
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule PetrovichElixirTest.ParserTest.FirstName.Normal do
defmodule PetrovichTest.ParserTest.FirstName.Normal do
use ExUnit.Case

alias PetrovichElixir.Parser
alias Petrovich.Parser

setup do
values = %{
Expand Down Expand Up @@ -40,46 +40,46 @@ defmodule PetrovichElixirTest.ParserTest.FirstName.Normal do

test "parses nomenative name", %{values: values} do
for {gender, name, result} <- values.nomenative do
assert Parser.parse(name, :firstname, :nomenative, gender) == result
assert Parser.parse!(name, :firstname, :nomenative, gender) == result
end
end

test "parses genitive name", %{values: values} do
for {gender, name, result} <- values.genitive do
assert Parser.parse(name, :firstname, :genitive, gender) == result
assert Parser.parse!(name, :firstname, :genitive, gender) == result
end
end

test "parses dative name", %{values: values} do
for {gender, name, result} <- values.dative do
assert Parser.parse(name, :firstname, :dative, gender) == result
assert Parser.parse!(name, :firstname, :dative, gender) == result
end
end

test "parses accusative name", %{values: values} do
for {gender, name, result} <- values.accusative do
assert Parser.parse(name, :firstname, :accusative, gender) == result
assert Parser.parse!(name, :firstname, :accusative, gender) == result
end
end

test "parses instrumental name", %{values: values} do
for {gender, name, result} <- values.instrumental do
assert Parser.parse(name, :firstname, :instrumental, gender) == result
assert Parser.parse!(name, :firstname, :instrumental, gender) == result
end
end

test "parses prepositional name", %{values: values} do
for {gender, name, result} <- values.prepositional do
assert Parser.parse(name, :firstname, :prepositional, gender) == result
assert Parser.parse!(name, :firstname, :prepositional, gender) == result
end
end
end


defmodule PetrovichElixir.ParserTest.FirstName.Exception do
defmodule Petrovich.ParserTest.FirstName.Exception do
use ExUnit.Case

alias PetrovichElixir.Parser
alias Petrovich.Parser

setup do
values = %{
Expand Down Expand Up @@ -118,37 +118,37 @@ defmodule PetrovichElixir.ParserTest.FirstName.Exception do

test "parses nomenative name", %{values: values} do
for {gender, name, result} <- values.nomenative do
assert Parser.parse(name, :firstname, :nomenative, gender) == result
assert Parser.parse!(name, :firstname, :nomenative, gender) == result
end
end

test "parses genitive name", %{values: values} do
for {gender, name, result} <- values.genitive do
assert Parser.parse(name, :firstname, :genitive, gender) == result
assert Parser.parse!(name, :firstname, :genitive, gender) == result
end
end

test "parses dative name", %{values: values} do
for {gender, name, result} <- values.dative do
assert Parser.parse(name, :firstname, :dative, gender) == result
assert Parser.parse!(name, :firstname, :dative, gender) == result
end
end

test "parses accusative name", %{values: values} do
for {gender, name, result} <- values.accusative do
assert Parser.parse(name, :firstname, :accusative, gender) == result
assert Parser.parse!(name, :firstname, :accusative, gender) == result
end
end

test "parses instrumental name", %{values: values} do
for {gender, name, result} <- values.instrumental do
assert Parser.parse(name, :firstname, :instrumental, gender) == result
assert Parser.parse!(name, :firstname, :instrumental, gender) == result
end
end

test "parses prepositional name", %{values: values} do
for {gender, name, result} <- values.prepositional do
assert Parser.parse(name, :firstname, :prepositional, gender) == result
assert Parser.parse!(name, :firstname, :prepositional, gender) == result
end
end
end
Loading

0 comments on commit ea886fd

Please sign in to comment.