Skip to content

Latest commit

 

History

History
384 lines (287 loc) · 13.6 KB

ELIXIR.md

File metadata and controls

384 lines (287 loc) · 13.6 KB

Elixir

Phoenix  —  Productive. Reliable. Fast. A productive web framework that does not compromise speed and maintainability.

phoenix


phoenix-trello. Trello tribute done with Elixir, Phoenix Framework, Webpack, React and Redux.

phoenix-trello


credo  —  a static code analysis tool for the Elixir language with a focus on teaching and code consistency.

credo


guardian  —  an authentication framework for use with Elixir applications. Guardian is based on similar ideas to Warden but is re-imagined for modern systems where Elixir manages the authentication requirements.

Guardian remains a functional system. It integrates with Plug, but can be used outside of it. If you’re implementing a TCP/UDP protocol directly, or want to utilize your authentication via channels, Guardian is your friend. The core currency of authentication in Guardian is JSON Web Tokens (JWT). You can use the JWT to authenticate web endpoints, channels, and TCP sockets and it can contain any authenticated assertions that the issuer wants to include.


Beaker is a tool that can be used to keep track of metrics for your Elixir project. It aims to provide an easy way to register statistics as well as an easy way to visualize them.


httpoison —  yet another HTTP client for Elixir powered by hackney.

httpoison


maru  — an  Elixir RESTful Framework

Example:

defmodule Router.User do
  use Maru.Router

  namespace :user do
    route_param :id do
      get do
        json(conn, %{ user: params[:id] })
      end

      desc "description"
      params do
        requires :age,    type: Integer, values: 18..65
        requires :gender, type: Atom, values: [:male, :female], default: :female
        group    :name,   type: Map do
          requires :first_name
          requires :last_name
        end
        optional :intro,  type: String, regexp: ~r/^[a-z]+$/
        optional :avatar, type: File
        optional :avatar_url, type: String
        exactly_one_of [:avatar, :avatar_url]
      end
      post do
        ...
      end
    end
  end
end

defmodule Router.Homepage do
  use Maru.Router

  resources do
    get do
      json(conn, %{ hello: :world })
    end

    mount Router.User
  end
end


defmodule MyAPP.API do
  use Maru.Router

  before do
    plug Plug.Logger
    plug Plug.Static, at: "/static", from: "/my/static/path/"
  end

  plug Plug.Parsers,
    pass: ["*/*"],
    json_decoder: Poison,
    parsers: [:urlencoded, :json, :multipart]

  mount Router.Homepage

  rescue_from Unauthorized, as: e do
    IO.inspect e

    conn
    |> put_status(401)
    |> text("Unauthorized")
  end

  rescue_from [MatchError, RuntimeError], with: :custom_error

  rescue_from :all do
    conn
    |> put_status(500)
    |> text("Server Error")
  end

  defp custom_error(conn, exception) do
    conn
    |> put_status(500)
    |> text(exception.message)
  end
end


The unittest unit testing library was originally inspired by Python standard testing framework. It supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections.

Example:

defmodule UnittestTest do
  use ExUnit.Case
  import Unittest

  test "is" do
    assert is(:atom, :atom)
    assert is(666, :int)
    assert is("String", :str)
    assert is(3.14159265359, :float)
    assert is(<<60, 33, 68, 79, 67>>, :bin)
    assert is(<<1 :: size(1)>>, :bitstring)
    assert is(%{"one" => :one, 2 => :two}, :map)
    assert is(nil, :nil)
    assert is(344, :number)
    assert is(3.44, :number)
    assert is({:ok, "OK"}, :tuple)
    assert is(true, :bool)
    assert is([:one, :two], :list)

    pid = spawn(fn -> :ok end)
    assert is(pid, :pid)

    function = fn() -> :something end
    assert is(function, :function)

    # Returns true if term is a function that can be applied
    # with arity number of arguments; otherwise returns false.
    function = fn(_, _) -> :something end
    assert is(function, 2, :function)
  end
end

hound  — an  Elixir library for writing integration tests and browser automation.

ExUnit example:

defmodule HoundTest do
  use ExUnit.Case
  use Hound.Helpers

  hound_session

  test "the truth", meta do
    navigate_to("http://example.com/guestbook.html")

    element = find_element(:name, "message")
    fill_field(element, "Happy Birthday ~!")
    submit_element(element)

    assert page_title() == "Thank you"
  end

end

distillery  —  a pure Elixir implementation of release packaging functionality for the Erlang VM (BEAM). Every alchemist requires good tools, and one of the greatest tools in the alchemist’s disposal is the distillery. The purpose of the distillery is to take something and break it down to it’s component parts, reassembling it into something better, more powerful. That is exactly what this project does — it takes your Mix project and produces an Erlang/OTP release, a distilled form of your raw application’s components; a single package which can be deployed anywhere, independently of an Erlang/Elixir installation. No dependencies, no hassle.

This is a pure-Elixir, dependency-free implementation of release generation for Elixir projects. It is currently a standalone package, but may be integrated into Mix at some point in the future.


timex —  a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you! It is very easy to use Timex types in place of default Erlang types, as well as Ecto types via the timex_ecto package.

Here’s a few simple examples:

> use Timex
> Timex.today
~D[2016-02-29]

> datetime = Timex.now
#<DateTime(2016-02-29T12:30:30.120+00:00Z Etc/UTC)

> Timex.now("America/Chicago")
#<DateTime(2016-02-29T06:30:30.120-06:00 America/Chicago)

> Duration.now
#<Duration(P46Y6M24DT21H57M33.977711S)>

> {:ok, default_str} = Timex.format(datetime, "{ISO:Extended}")
{:ok, "2016-02-29T12:30:30.120+00:00"}

> {:ok, relative_str} = Timex.shift(datetime, minutes: -3) |> Timex.format("{relative}", :relative)
{:ok, "3 minutes ago"}

> strftime_str = Timex.format!(datetime, "%FT%T%:z", :strftime)
"2016-02-29T12:30:30+00:00"

> Timex.parse(default_str, "{ISO:Extended}")
{:ok, #<DateTime(2016-02-29T12:30:30.120+00:00 Etc/Utc)}

> Timex.parse!(strftime_str, "%FT%T%:z", :strftime)
#<DateTime(2016-02-29T12:30:30.120+00:00 Etc/Utc)

> Duration.diff(Duration.now, Duration.zero, :days)
16850

> Timex.shift(date, days: 3)
~D[2016-03-03]

> Timex.shift(datetime, hours: 2, minutes: 13)
#<DateTime(2016-02-29T14:43:30.120Z Etc/UTC)>

> timezone = Timezone.get("America/Chicago", Timex.now)
#<TimezoneInfo(America/Chicago - CDT (-06:00:00))>

> Timezone.convert(datetime, timezone)
#<DateTime(2016-02-29T06:30:30.120-06:00 America/Chicago)>

> Timex.before?(Timex.today, Timex.shift(Timex.today, days: 1))
true

> Timex.before?(Timex.shift(Timex.today, days: 1), Timex.today)
false

ex_admin —  an add on for an application using the Phoenix Framework to create an CRUD administration tool with little or no code. By running a few mix tasks to define which Ecto Models you want to administer, you will have something that works with no additional code.

ex_admin


kitto —  a framework to help you create dashboards, written in Elixir/React.

kitto


Faker is a pure Elixir library for generating fake data.


Floki is a simple HTML parser that enables search for nodes using CSS selectors.

Take this HTML as an example:

<!doctype html>
<html>
<body>
  <section id="content">
    <p class="headline">Floki</p>
    <span class="headline">Enables search using CSS selectors</span>
    <a href="http://github.com/philss/floki">Github page</a>
    <span data-model="user">philss</span>
  </section>
  <a href="https://hex.pm/packages/floki">Hex package</a>
</body>
</html>

Here are some queries that you can perform (with return examples):

Floki.find(html, "#content")
# => [{"section", [{"id", "content"}],
# =>  [{"p", [{"class", "headline"}], ["Floki"]},
# =>   {"a", [{"href", "http://github.com/philss/floki"}], ["Github page"]}]}]


Floki.find(html, "p.headline")
# => [{"p", [{"class", "headline"}], ["Floki"]}]

Floki.find(html, "p.headline")
|> Floki.raw_html
# => <p class="headline">Floki</p>


Floki.find(html, "a")
# => [{"a", [{"href", "http://github.com/philss/floki"}], ["Github page"]},
# =>  {"a", [{"href", "https://hex.pm/packages/floki"}], ["Hex package"]}]


Floki.find(html, "a[href^=https]")
# => [{"a", [{"href", "http://github.com/philss/floki"}], ["Github page"]},
# =>  {"a", [{"href", "https://hex.pm/packages/floki"}], ["Hex package"]}]


Floki.find(html, "#content a")
# => [{"a", [{"href", "http://github.com/philss/floki"}], ["Github page"]}]


Floki.find(html, "[data-model=user]")
# => [{"span", [{"data-model", "user"}], ["philss"]}]


Floki.find(html, ".headline, a")
# => [{"p", [{"class", "headline"}], ["Floki"]},
# =>  {"a", [{"href", "http://github.com/philss/floki"}], ["Github page"]},
# =>  {"a", [{"href", "https://hex.pm/packages/floki"}], ["Hex package"]}]

Maxwell is an HTTP client that provides a common interface over :httpc, :ibrowse, :hackney.

Usage:

Use Maxwell.Builder module to create the API wrappers.

defmodule GitHubClient do
  #generate 4 function get/1, get!/1 patch/1 patch!/1 function
  use Maxwell.Builder, ~w(get patch)a

  middleware Maxwell.Middleware.BaseUrl, "https://api.github.com"
  middleware Maxwell.Middleware.Headers, %{'Content-Type': "application/vnd.github.v3+json", 'User-Agent': 'zhongwenool'}
  middleware Maxwell.Middleware.Opts, [connect_timeout: 3000]
  middleware Maxwell.Middleware.Json
  middleware Maxwell.Middleware.Logger

  adapter Maxwell.Adapter.Hackney # default adapter is Maxwell.Adapter.Httpc

  #List public repositories for the specified user.
  #:hackney.request(:get,
  #                'https://api.github.com/users/zhongwencool/repos',
  #                ['Content-Type': "application/vnd.github.v3+json", 'User-Agent': 'zhongwenool'],
  #                [],
  #                [connect_timeout: 3000])
  def user_repos(username) do
    put_path("/users/" <> username <> "/repos") |> get
  end

  # Edit owner repositories
  # :hackney.request(:patch,
  #                  'https://api.github.com/repos/owner/repo',
  #                  ['Content-Type': "application/vnd.github.v3+json", 'User-Agent': 'zhongwenool'],
  #                  "{\"name\":\"name\",\"description\":\"desc\"}",
  #                  [connect_timeout: 3000])
  def edit_repo_desc(owner, repo, name, desc) do
    new
    |> put_path("/repos/#{owner}/#{repo}")
    |> put_req_body(%{name: name, description: desc})
    |> patch
  end
end

ExVCR. Record and replay HTTP interactions library for elixir. It's inspired by Ruby's VCR (https://github.com/vcr/vcr), and trying to provide similar functionalities.

Basics

  • The following HTTP libraries can be applied.

    • ibrowse-based libraries.
    • hackney-based libraries.
      • HTTPoison
      • support is very limited, and tested only with sync request of HTTPoison yet.
    • httpc-based libraries.
      • erlang-oauth
      • tirexs
      • support is very limited, and tested only with :httpc.request/1 and :httpc.request/4
  • HTTP interactions are recorded as JSON file.

    • The JSON file can be recorded automatically (vcr_cassettes) or manually updated (custom_cassettes)