├── .gitignore
├── LICENSE.txt
├── README.md
├── config
└── config.exs.sample
├── lib
├── sips_downloader.ex
└── sips_downloader
│ ├── dpdcart.ex
│ ├── episode_downloader.ex
│ ├── episodes_feed.ex
│ ├── parallel_downloader.ex
│ └── xml_parser.ex
├── misc
├── feed
└── feed_without_description
├── mix.exs
├── mix.lock
└── test
├── feed
├── full_feed
├── sips_downloader_test.exs
└── test_helper.exs
/.gitignore:
--------------------------------------------------------------------------------
1 | /_build
2 | /deps
3 | erl_crash.dump
4 | *.ez
5 | deps
6 | config/config.exs
7 | sips_downloader
8 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Dávid Kovács
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SipsDownloader
2 | ==============
3 |
4 | Elixir module for downloading the ElixirSips episodes and all other files.
5 |
6 | The login credentials and download location must be set in config/config.exs.
7 |
8 | ## Installation
9 |
10 | Clone this repository
11 |
12 | ```
13 | git clone https://github.com/DavsX/SipsDownloader
14 | cd SipsDownloader
15 | ```
16 |
17 | Update config/config.exs, then generate an executable
18 |
19 | ```
20 | mv config/config.exs.sample config/config.exs
21 | vim config/config.exs
22 | mix do deps.get, escript.build
23 | ```
24 |
25 | Run the executable
26 |
27 | ```
28 | ./sips_downloader
29 | ```
30 |
--------------------------------------------------------------------------------
/config/config.exs.sample:
--------------------------------------------------------------------------------
1 | use Mix.Config
2 |
3 | config :sips,
4 | download_dir: "/tmp",
5 | username: "username",
6 | password: "password"
7 |
--------------------------------------------------------------------------------
/lib/sips_downloader.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader do
2 | @moduledoc """
3 | Downloads new ElixirSips episodes (subscription to ElixirSips required)
4 |
5 | Credentials and other information needs to be specified in config/config.exs (see provided sample)
6 |
7 | Execute:
8 | iex> SipsDownloader.run()
9 | """
10 |
11 | def main(_args) do
12 | run
13 | end
14 |
15 | def run do
16 | username = Application.get_env(:sips, :username)
17 | password = Application.get_env(:sips, :password)
18 | download_dir = Application.get_env(:sips, :download_dir)
19 |
20 | session_id =
21 | SipsDownloader.DPDCart.get_login_url
22 | |> SipsDownloader.DPDCart.get_login_session(username, password)
23 |
24 | episodes_to_download =
25 | SipsDownloader.EpisodesFeed.download_episodes_feed(username, password)
26 | |> SipsDownloader.XMLParser.parse_episodes
27 | |> Enum.filter(&episode_to_download(download_dir, &1))
28 | |> Enum.reverse
29 |
30 | if Enum.empty?(episodes_to_download) do
31 | IO.puts "No new episodes to download"
32 | else
33 | IO.puts "Downloading episodes"
34 | SipsDownloader.ParallelDownloader.run(episodes_to_download, session_id, download_dir)
35 | end
36 | end
37 |
38 | def episode_to_download(dir, {name, _}) do
39 | (Path.join(dir, name) |> File.exists?) == false
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/lib/sips_downloader/dpdcart.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.DPDCart do
2 | def get_login_url do
3 | url = get_login_page() |> SipsDownloader.XMLParser.parse_login_url
4 |
5 | "https://elixirsips.dpdcart.com" <> url
6 | end
7 |
8 | def get_login_page do
9 | login_page_url = "https://elixirsips.dpdcart.com/subscriber/content"
10 | %HTTPoison.Response{body: body, status_code: 200} = HTTPoison.get!(login_page_url)
11 | body
12 | end
13 |
14 | def get_login_session(url, username, password) do
15 | headers = %{"Content-type" => "application/x-www-form-urlencoded"}
16 | post_data = {:form, [username: username, password: password]}
17 | {:ok, response} = HTTPoison.post(url, post_data, headers)
18 | extract_session_id(response.headers)
19 | end
20 |
21 | def extract_session_id(headers) do
22 | cookie = headers |> Enum.find(&cookie_header?/1)
23 | {_, "symfony=" <> cookie_val} = cookie
24 | cookie_val |> String.split(";") |> List.first
25 | end
26 |
27 | def cookie_header?(header) do
28 | case header do
29 | {"Set-Cookie", "symfony=" <> _} -> true
30 | _ -> false
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/sips_downloader/episode_downloader.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.EpisodeDownloader do
2 | def run(work = {_name, url}, state) do
3 | result = case make_async_request(url, state.session_id) do
4 | {:ok, %HTTPoison.AsyncResponse{}} ->
5 | state = Map.merge(state, %{fh: nil, file_size: nil, downloaded_size: nil})
6 | process_download(work, state)
7 |
8 | {:error, %HTTPoison.Error{reason: reason}} ->
9 | {:error, reason}
10 | end
11 |
12 | send(state.parent, {state.work_ref, self(), work, result})
13 | end
14 |
15 | defp make_async_request(url, session_id) do
16 | HTTPoison.get(url, [], [
17 | hackney: [cookie: [{"symfony", session_id}]],
18 | stream_to: self()
19 | ])
20 | end
21 |
22 | defp process_download(work = {name, _url}, state = %{fh: nil, dir: dir}) do
23 | receive do
24 | %HTTPoison.AsyncStatus{code: 200} ->
25 | {:ok, fh} = Path.expand(dir) |> Path.join(name) |> Kernel.<>(".tmp") |> File.open([:write, :append])
26 | process_download(work, %{state | fh: fh})
27 |
28 | %HTTPoison.AsyncStatus{code: 302} ->
29 | receive_redirect_location()
30 |
31 | %HTTPoison.AsyncStatus{code: code} ->
32 | {:error, "Could not download episode [#{name}]. Status code #{code}"}
33 |
34 | result ->
35 | {:error, "Expected %HTTPoison.AsyncStatus, got [#{inspect result}]"}
36 | after
37 | 5_000 -> {:error, "Expected %HTTPoison.AsyncStatus, got nothing after 5s"}
38 | end
39 | end
40 |
41 | defp process_download(work, state = %{file_size: nil, downloaded_size: nil}) do
42 | receive do
43 | %HTTPoison.AsyncHeaders{headers: headers} ->
44 | content_length = Enum.find(headers, fn {type, _} -> type == "Content-Length" end)
45 | |> elem(1)
46 | |> String.to_integer
47 |
48 | state = %{state | file_size: content_length, downloaded_size: 0}
49 | process_download(work, state)
50 |
51 | result ->
52 | {:error, "Expected %HTTPoison.AsyncHeaders, got [#{inspect result}]"}
53 | after
54 | 5_000 -> {:error, "Expected %HTTPoison.AsyncHeaders, got nothing after 5s"}
55 | end
56 | end
57 |
58 | defp process_download(work = {name, _url}, state) do
59 | file_size = state.file_size
60 | downloaded_size = state.downloaded_size
61 | fh = state.fh
62 |
63 | receive do
64 | %HTTPoison.AsyncChunk{chunk: chunk} ->
65 | chunk_len = byte_size(chunk)
66 | :ok = IO.binwrite(fh, chunk)
67 | process_download(work, %{state | downloaded_size: downloaded_size + chunk_len})
68 |
69 | %HTTPoison.AsyncEnd{} ->
70 | file_name = Path.join(state.dir, name)
71 | temp_file_name = file_name <> ".tmp"
72 |
73 | if file_size == downloaded_size do
74 | :ok = File.cp(temp_file_name, file_name)
75 | :ok = File.close(fh)
76 | :ok = File.rm(temp_file_name)
77 |
78 | {:ok}
79 | else
80 | :ok = File.close(fh)
81 | :ok = File.rm(temp_file_name)
82 |
83 | {:error, "Did not manage to download the whole file! #{downloaded_size}/#{file_size}"}
84 | end
85 |
86 | result ->
87 | {:error, "Expected %HTTPoison.AsyncChunk/End, got [#{inspect result}]"}
88 |
89 | after
90 | 5_000 -> {:error, "Expected %HTTPoison.AsyncChunk/End, got nothing after 5s"}
91 | end
92 | end
93 |
94 | defp receive_redirect_location() do
95 | receive do
96 | %HTTPoison.AsyncHeaders{headers: headers} ->
97 | {"Location", location} = Enum.find(headers, fn {type, _} -> type == "Location" end)
98 | {:redirect, location}
99 |
100 | result ->
101 | {:error, "Expected %HTTPoison.AsyncHeaders, got [#{inspect result}]"}
102 | after
103 | 5_000 -> {:error, "Expected %HTTPoison.AsyncHeaders, got nothing after 5s"}
104 | end
105 | end
106 | end
107 |
--------------------------------------------------------------------------------
/lib/sips_downloader/episodes_feed.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.EpisodesFeed do
2 | def download_episodes_feed(username, password) do
3 | feed_url = "https://elixirsips.dpdcart.com/feed"
4 | hackney = [basic_auth: {username, password}]
5 |
6 | IO.puts "Downloading episodes_feed"
7 |
8 | case HTTPoison.get(feed_url, [], [hackney: hackney]) do
9 | {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
10 | body
11 | {:ok, %HTTPoison.Response{status_code: code}} ->
12 | raise "Failed to download feed. Status code #{code}"
13 | {:error, response} ->
14 | raise "Failed to download feed: #{response.reason}"
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/sips_downloader/parallel_downloader.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.ParallelDownloader do
2 | def run(episodes, session_id, download_dir) do
3 | {:ok, sup} = Task.Supervisor.start_link()
4 |
5 | state = %{
6 | dir: download_dir,
7 | max_running: 5,
8 | parent: self(),
9 | pids: %{},
10 | running: 0,
11 | session_id: session_id,
12 | supervisor: sup,
13 | work_ref: make_ref()
14 | }
15 |
16 | schedule_downloads(episodes, state)
17 | end
18 |
19 | defp schedule_downloads([], %{running: 0}), do: IO.puts "Finished downloading!"
20 | defp schedule_downloads(episode_queue, state) do
21 | if (state.running < state.max_running) and (length(episode_queue) > 0) do
22 | {:ok, episode_queue, state} = download_episode(episode_queue, state)
23 | schedule_downloads(episode_queue, state)
24 | else
25 | {:ok, episode_queue, state} = receive_download_msg(episode_queue, state)
26 | schedule_downloads(episode_queue, state)
27 | end
28 | end
29 |
30 | defp receive_download_msg(episode_queue, state) do
31 | work_ref = state.work_ref
32 | receive do
33 | {^work_ref, worker_pid, _work = {name, _url}, {:ok}} ->
34 | IO.puts "Finished #{name}"
35 | pids = Map.delete(state.pids, worker_pid)
36 | state = %{state | pids: pids, running: state.running - 1}
37 | {:ok, episode_queue, state}
38 |
39 | {^work_ref, worker_pid, _work = {name, _url}, {:redirect, location}} ->
40 | IO.puts "Redirect for #{name}"
41 | pids = Map.delete(state.pids, worker_pid)
42 | state = %{state | pids: pids, running: state.running - 1}
43 | new_work = {name, location}
44 | episode_queue = [new_work | episode_queue]
45 | {:ok, episode_queue, state}
46 |
47 | {^work_ref, worker_pid, _work = {name, _url}, {:error, reason}} ->
48 | IO.puts "Failed to download #{name}: #{reason}"
49 | pids = Map.delete(state.pids, worker_pid)
50 | state = %{state | pids: pids, running: state.running - 1}
51 | {:ok, episode_queue, state}
52 |
53 | {:DOWN, monitor_ref, _, worker_pid, reason} ->
54 | if Map.has_key?(state.pids, worker_pid) do
55 | Process.demonitor(monitor_ref)
56 | {_work = {name, _url}, pids} = Map.pop(state.pids, worker_pid)
57 | IO.puts "Failed to download #{name}: #{inspect reason}"
58 | state = %{state | pids: pids, running: state.running - 1}
59 | {:ok, episode_queue, state}
60 | else
61 | {:ok, episode_queue, state}
62 | end
63 |
64 | true ->
65 | {:ok, episode_queue, state}
66 | end
67 | end
68 |
69 | defp download_episode([work | queue], state) do
70 | {:ok, worker_pid} = spawn_worker(work, state)
71 |
72 | pids = Map.put(state.pids, worker_pid, work)
73 | state = %{state | pids: pids, running: state.running + 1}
74 |
75 | {:ok, queue, state}
76 | end
77 |
78 | defp spawn_worker(work = {name, _url}, state) do
79 | IO.puts "Starting download: #{name}"
80 |
81 | worker_state = Map.take(state, [:work_ref, :dir, :session_id, :parent])
82 |
83 | {:ok, worker_pid} = Task.Supervisor.start_child(
84 | state.supervisor, SipsDownloader.EpisodeDownloader, :run, [work, worker_state]
85 | )
86 |
87 | Process.monitor(worker_pid)
88 |
89 | {:ok, worker_pid}
90 | end
91 | end
92 |
--------------------------------------------------------------------------------
/lib/sips_downloader/xml_parser.ex:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.XMLParser do
2 | require Record
3 |
4 | Record.defrecord :xmlElement, Record.extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl")
5 | Record.defrecord :xmlAttribute, Record.extract(:xmlAttribute, from_lib: "xmerl/include/xmerl.hrl")
6 | Record.defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")
7 |
8 | def parse_login_url(string) do
9 | string
10 | |> Floki.find("form")
11 | |> Floki.attribute("action")
12 | |> Enum.at(0)
13 | end
14 |
15 | def parse_episodes(feed) do
16 | feed
17 | |> to_xml
18 | |> episode_descriptions
19 | |> Enum.map(&normalize_string/1)
20 | |> Enum.map(&parse_episode_title_and_link/1)
21 | |> List.flatten
22 | end
23 |
24 | def to_xml(str) do
25 | String.replace(str, ~r/&.*;/, "")
26 | |> :erlang.binary_to_list
27 | |> :xmerl_scan.string
28 | |> elem(0)
29 | end
30 |
31 | def episode_descriptions(xml) do
32 | ~c{//channel/item/description/text()}
33 | |> :xmerl_xpath.string(xml)
34 | |> Enum.map(&(xmlText(&1, :value)))
35 | |> Enum.map(&normalize_string/1)
36 | end
37 |
38 | def normalize_string(string) do
39 | string
40 | |> to_string
41 | |> String.split(["\n"])
42 | |> Enum.map(&String.strip/1)
43 | |> Enum.join("")
44 | end
45 |
46 | def parse_episode_title_and_link(episode_description) do
47 | attached_files_part =
48 | episode_description
49 | |> String.split("
Attached Files
")
50 | |> List.last
51 |
52 | episode_xml = to_xml("" <> attached_files_part)
53 |
54 | link_elems = '//ul/li/a' |> :xmerl_xpath.string(episode_xml)
55 |
56 | Enum.map(link_elems, fn (link_elem) ->
57 | {get_link_title(link_elem), get_link_href(link_elem)}
58 | end)
59 | end
60 |
61 | def get_link_title(link_elem) do
62 | link_elem
63 | |> xmlElement(:content)
64 | |> List.first
65 | |> xmlText(:value)
66 | |> to_string
67 | |> String.strip
68 | end
69 |
70 | def get_link_href(link_elem) do
71 | link_elem
72 | |> xmlElement(:attributes)
73 | |> Enum.find(&(:href == xmlAttribute(&1, :name)))
74 | |> xmlElement(:content)
75 | |> to_string
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/misc/feed_without_description:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Elixir Sips
5 | https://elixirsips.dpdcart.com/
6 |
7 | Wed, 01 Jul 2015 07:34:00 -0400
8 | josh.rubyist@gmail.com (Josh Adams)
9 | en
10 | Copyright 2015 Elixir Sips
11 | getdpd.com
12 | ElixirSips is a twice-weekly small dose of knowledge related to the Elixir programming language.
13 | -
14 |
15 | https://elixirsips.dpdcart.com/subscriber/post?id=821
16 |
17 | dpd-b49e1e04b7a47bee866c63837bb98c824e47225d
18 | Wed, 01 Jul 2015 07:34:00 -0400
19 |
20 |
21 | -
22 |
23 | https://elixirsips.dpdcart.com/subscriber/post?id=819
24 |
25 | dpd-36d06370d0b0796c87c6a6b56de85a2d66d780af
26 | Sat, 27 Jun 2015 09:22:00 -0400
27 |
28 |
29 | -
30 |
31 | https://elixirsips.dpdcart.com/subscriber/post?id=815
32 |
33 | dpd-9a2fa70dd941592721d62c52865406f54fb3af01
34 | Wed, 24 Jun 2015 12:42:00 -0400
35 |
36 |
37 | -
38 |
39 | https://elixirsips.dpdcart.com/subscriber/post?id=810
40 |
41 | dpd-2981c3e60955bf57de1ee08d61839371e44fff58
42 | Fri, 19 Jun 2015 08:16:00 -0400
43 |
44 |
45 | -
46 |
47 | https://elixirsips.dpdcart.com/subscriber/post?id=808
48 |
49 | dpd-a6df8eb71e88c7098b7cd81e4c41a950cc402917
50 | Wed, 17 Jun 2015 09:19:00 -0400
51 |
52 |
53 | -
54 |
55 | https://elixirsips.dpdcart.com/subscriber/post?id=784
56 |
57 | dpd-e0e5332038b108ca27551d1198cd16e3e957b0b7
58 | Thu, 04 Jun 2015 22:49:00 -0400
59 |
60 |
61 | -
62 |
63 | https://elixirsips.dpdcart.com/subscriber/post?id=777
64 |
65 | dpd-e11c101e940fdf135fbf4a0c74c9dae37d0df2cf
66 | Tue, 02 Jun 2015 22:16:00 -0400
67 |
68 | Building a renderer for our Logo interpreter.
69 |
70 | -
71 |
72 | https://elixirsips.dpdcart.com/subscriber/post?id=776
73 |
74 | dpd-5446cc8d8c9ccd06bf00a85aec8ec4172950767e
75 | Sat, 30 May 2015 21:08:00 -0400
76 |
77 | Implementing the Logo graphical programming language in Elixir with wxWidgets. In this episode we just implement the underlying GenServer.
78 |
79 | -
80 |
81 | https://elixirsips.dpdcart.com/subscriber/post?id=774
82 |
83 | dpd-9c4e2499cd7e9d3da28502c6f053a96d6465fa88
84 | Fri, 29 May 2015 00:07:00 -0400
85 |
86 | Modeling a double-entry ledger. Terribly. And then discussing what went wrong.
87 |
88 | -
89 |
90 | https://elixirsips.dpdcart.com/subscriber/post?id=761
91 |
92 | dpd-156d0b4466f5b68ea81ece29014ae2b363c93538
93 | Thu, 21 May 2015 23:37:00 -0400
94 |
95 | Exploring L Systems, on our way to generating fractals.
96 |
97 | -
98 |
99 | https://elixirsips.dpdcart.com/subscriber/post?id=758
100 |
101 | dpd-845306ba77a2b1b2bbf126d526109caaecaa8278
102 | Wed, 13 May 2015 20:01:00 -0400
103 |
104 | Executing our jobs on their schedule. Bonus intro to defdelegate and ExUnit's `@tag`s.
105 |
106 | -
107 |
108 | https://elixirsips.dpdcart.com/subscriber/post?id=757
109 |
110 | dpd-b0aa6fa5d1b58b4a830006dc739b33b57dd29c30
111 | Fri, 08 May 2015 07:58:00 -0400
112 |
113 | Determining if a given time is matched by a Schedule.
114 |
115 | -
116 |
117 | https://elixirsips.dpdcart.com/subscriber/post?id=755
118 |
119 | dpd-ba144cb69da49b33a044f873ed42f458d38adabf
120 | Sat, 02 May 2015 10:45:00 -0400
121 |
122 | Building a parser for cron-style job definitions.
123 |
124 | -
125 |
126 | https://elixirsips.dpdcart.com/subscriber/post?id=754
127 |
128 | dpd-ec5082c3c81960e8fccc25c52bacea299baa1e2b
129 | Thu, 30 Apr 2015 21:43:00 -0400
130 |
131 | A less-verbose way to define multiple function clauses, courtesy of Dave Thomas.
132 |
133 | -
134 |
135 | https://elixirsips.dpdcart.com/subscriber/post?id=753
136 |
137 | dpd-db3cc80f439626ec5f75e295168642d6e07b3145
138 | Sun, 26 Apr 2015 00:01:00 -0400
139 |
140 | Getting a dynamically spawned process into a supervision tree to avoid orphaned processes, among other things.
141 |
142 | -
143 |
144 | https://elixirsips.dpdcart.com/subscriber/post?id=746
145 |
146 | dpd-434ea42ad6c8d1d06d216710d1992d37f0d16066
147 | Thu, 23 Apr 2015 16:06:00 -0400
148 |
149 | Using the `detergentex` library, which wraps the
150 | erlang `detergent` library, to interact with SOAP
151 | services in Elixir.
152 |
153 | -
154 |
155 | https://elixirsips.dpdcart.com/subscriber/post?id=744
156 |
157 | dpd-d33a09418921d033fdcd444e29e2fc0731d2fc5b
158 | Thu, 16 Apr 2015 21:28:00 -0400
159 |
160 | Exploring the standard library's Code module's `eval_string` function for fun and whatnot.
161 |
162 | -
163 |
164 | https://elixirsips.dpdcart.com/subscriber/post?id=742
165 |
166 | dpd-4a46f97061c681389ed4c3f0c4ba43b69ee66e9b
167 | Sat, 11 Apr 2015 18:54:00 -0400
168 |
169 | A comically brief overview of erlcloud and evidence that it does, in fact, work for me.
170 |
171 | -
172 |
173 | https://elixirsips.dpdcart.com/subscriber/post?id=740
174 |
175 | dpd-da1d5954df47faa609204c615518928791d5da26
176 | Thu, 09 Apr 2015 21:43:00 -0400
177 |
178 | A dig through Sonny Scroggins' example of integrating a Phoenix application with GitHub via his OAuth2 package.
179 |
180 | -
181 |
182 | https://elixirsips.dpdcart.com/subscriber/post?id=733
183 |
184 | dpd-537587b7f62ed37c257b004087f8f868a78de9cd
185 | Wed, 01 Apr 2015 18:55:00 -0400
186 |
187 | Basic TCP/IP interactions built into Erlang's kernel application for you.
188 |
189 | -
190 |
191 | https://elixirsips.dpdcart.com/subscriber/post?id=732
192 |
193 | dpd-c66db07a4b4754fb5c48623fcff2eaa9f7b69e3a
194 | Tue, 31 Mar 2015 21:29:00 -0400
195 |
196 | Building a basic API with Phoenix, and allowing remote domains to access it from the browser.
197 |
198 | -
199 |
200 | https://elixirsips.dpdcart.com/subscriber/post?id=730
201 |
202 | dpd-e03c6c229e258d43db66ba923630a788e8e77fd8
203 | Sat, 28 Mar 2015 15:57:00 -0400
204 |
205 | Evaluating javascript on a SpiderMonkey interpreter and getting back Erlang terms.
206 |
207 | -
208 |
209 | https://elixirsips.dpdcart.com/subscriber/post?id=729
210 |
211 | dpd-9424815bed16a09dc9cff6261233a9cef58b64cc
212 | Sat, 28 Mar 2015 15:16:00 -0400
213 |
214 | Exploring a running Erlang system using tools from the shell.
215 |
216 | -
217 |
218 | https://elixirsips.dpdcart.com/subscriber/post?id=720
219 |
220 | dpd-45d429d6603673157a7cd2e6372304e55fc3ac58
221 | Tue, 17 Mar 2015 22:24:00 -0400
222 |
223 | Talking to Elixir from Java
224 |
225 | -
226 |
227 | https://elixirsips.dpdcart.com/subscriber/post?id=719
228 |
229 | dpd-151b5f5d5075d3202fb7487f331ba85ad0430a0e
230 | Fri, 13 Mar 2015 21:05:00 -0400
231 |
232 | Modifying messages inside of our ejabberd server, specifically - making everyone yell at each other.
233 |
234 | -
235 |
236 | https://elixirsips.dpdcart.com/subscriber/post?id=718
237 |
238 | dpd-4c30ef69eaac733e69473a1f4668fa3d7e4316a7
239 | Thu, 12 Mar 2015 22:07:00 -0400
240 |
241 | Getting started interacting with a battle-hardened XMPP chat server by writing Elixir modules for it.
242 |
243 | -
244 |
245 | https://elixirsips.dpdcart.com/subscriber/post?id=716
246 |
247 | dpd-e1751af797c4f1307c68f71bba0e00b9a4c1a79b
248 | Fri, 06 Mar 2015 21:31:00 -0500
249 |
250 | Generate markup from blocks of elixir code, in the style of _why the lucky stiff's markaby.
251 |
252 | -
253 |
254 | https://elixirsips.dpdcart.com/subscriber/post?id=714
255 |
256 | dpd-e803848bb958b19303529b4b071824ec69cba226
257 | Tue, 03 Mar 2015 23:44:00 -0500
258 |
259 | Easily send emails, parse emails, and verify email related features in your tests using this One Neat Trick.
260 |
261 | -
262 |
263 | https://elixirsips.dpdcart.com/subscriber/post?id=710
264 |
265 | dpd-eb535897309f8344fcea73020a27ddcdd6cb4caf
266 | Mon, 02 Mar 2015 14:23:00 -0500
267 |
268 | An elixir library for trivially specifying relative dates and times.
269 |
270 | -
271 |
272 | https://elixirsips.dpdcart.com/subscriber/post?id=705
273 |
274 | dpd-f49a420e1fe7a98b74b854396f7e4a443a2af0e7
275 | Sun, 01 Mar 2015 14:31:00 -0500
276 |
277 | Interacting with Erlang's native date and time types.
278 |
279 | -
280 |
281 | https://elixirsips.dpdcart.com/subscriber/post?id=703
282 |
283 | dpd-f41f618d39f1ecd5a003c8b2a3622c139a0c3554
284 | Fri, 20 Feb 2015 20:10:00 -0500
285 |
286 | A project that adds code generation to Phoenix for building models, controllers, templates, and channels.
287 |
288 | -
289 |
290 | https://elixirsips.dpdcart.com/subscriber/post?id=698
291 |
292 | dpd-beaeb46bd3c742812b96552df89b9e2521c7599d
293 | Tue, 17 Feb 2015 20:56:00 -0500
294 |
295 | Building quick 'binaries' after a fashion using Elixir's tooling.
296 |
297 | -
298 |
299 | https://elixirsips.dpdcart.com/subscriber/post?id=696
300 |
301 | dpd-6908aae4d850ee73b81ef2994a2c98b1bb01488e
302 | Wed, 11 Feb 2015 21:31:00 -0500
303 |
304 | Elixir ships with a Set behaviour, and a default HashSet implementation.
305 |
306 | -
307 |
308 | https://elixirsips.dpdcart.com/subscriber/post?id=695
309 |
310 | dpd-2dfbeab1b57c04c1b95df9c248db85dfdacaa7e4
311 | Tue, 10 Feb 2015 21:35:00 -0500
312 |
313 | Using `goma`, which is essentially WebMachine for The Internet Gopher Protocol, to build an elixir-powered gopher server.
314 |
315 | -
316 |
317 | https://elixirsips.dpdcart.com/subscriber/post?id=693
318 |
319 | dpd-87ef3d65563417c89fe166f34d92087bc9507d6c
320 | Thu, 05 Feb 2015 21:17:00 -0500
321 |
322 | Elixir's package manager, hex.pm, also provides a documentation server for elixir packages. We'll see how to push documentation up.
323 |
324 | -
325 |
326 | https://elixirsips.dpdcart.com/subscriber/post?id=692
327 |
328 | dpd-d9f0a938bff2bc69e69de65ad890d51af68ff229
329 | Tue, 03 Feb 2015 20:37:00 -0500
330 |
331 | Two of the core building blocks that the Erlang VM provides. I'd neglected discussing them until now. Oops.
332 |
333 | -
334 |
335 | https://elixirsips.dpdcart.com/subscriber/post?id=691
336 |
337 | dpd-7948abbc366cb961c1105a329949426ba607bfc4
338 | Sun, 01 Feb 2015 13:02:00 -0500
339 |
340 | Building out an erlagi handler module in Elixir that interacts with a remote HTTP API.
341 |
342 | -
343 |
344 | https://elixirsips.dpdcart.com/subscriber/post?id=688
345 |
346 | dpd-f2c8a30c643e48b247bbd02f326617ef9edb2feb
347 | Sat, 31 Jan 2015 16:35:00 -0500
348 |
349 | Using the `erlagi` application from Elixir to control the logic of an extension in a PBX system via Asterisk's AGI protocol.
350 |
351 | -
352 |
353 | https://elixirsips.dpdcart.com/subscriber/post?id=680
354 |
355 | dpd-bcc38614b2c6a209b36584b6ef895c758e4cd099
356 | Thu, 22 Jan 2015 20:23:00 -0500
357 |
358 | Another benchmarking tool, with a little bit less setup required.
359 |
360 | -
361 |
362 | https://elixirsips.dpdcart.com/subscriber/post?id=679
363 |
364 | dpd-d7d73146694311e2ba95ad13d61a3bcc80356e11
365 | Mon, 19 Jan 2015 21:04:00 -0500
366 |
367 | An easy way to interact with ElasticSearch.
368 |
369 | -
370 |
371 | https://elixirsips.dpdcart.com/subscriber/post?id=678
372 |
373 | dpd-d1948a5a47138c34e463f8df906c62991c49037f
374 | Sat, 17 Jan 2015 21:34:00 -0500
375 |
376 | An Elixir package providing fantastically simple support for Postgres's built-in pubsub notifications.
377 |
378 | -
379 |
380 | https://elixirsips.dpdcart.com/subscriber/post?id=671
381 |
382 | dpd-e4ddf485e1b49e9a33f7e8e848edb265e5fd830c
383 | Tue, 13 Jan 2015 20:39:00 -0500
384 |
385 | An exploration of where our randomness in Tetris went so horribly wrong, along with an exposition
386 | of how to think about which process your code is running in, and why that's important.
387 |
388 | -
389 |
390 | https://elixirsips.dpdcart.com/subscriber/post?id=669
391 |
392 | dpd-5e3092780d751537d1e6d8660cdc24ce5e09bab5
393 | Wed, 07 Jan 2015 00:52:00 -0500
394 |
395 | An Elixir profiler, useful for finding where your program is spending its time.
396 |
397 | -
398 |
399 | https://elixirsips.dpdcart.com/subscriber/post?id=663
400 |
401 | dpd-624c28e2f55980e246502e699e1b07cf2b2c66b2
402 | Sat, 27 Dec 2014 20:55:00 -0500
403 |
404 | Using Phoenix's websockets to build a JavaScript canvas-based renderer and interaction module for Extris games running in processes on the server.
405 |
406 | -
407 |
408 | https://elixirsips.dpdcart.com/subscriber/post?id=662
409 |
410 | dpd-1dcdd2c2d0b9773eed1bd43b88c26b6ea6973ae2
411 | Mon, 22 Dec 2014 20:04:00 -0500
412 |
413 | A module in the Erlang Standard Library meant for doing basic graphics.
414 |
415 | -
416 |
417 | https://elixirsips.dpdcart.com/subscriber/post?id=659
418 |
419 | dpd-9f8495ceada8026321e6ff0a2853c31cfd9eb241
420 | Sat, 20 Dec 2014 12:07:00 -0500
421 |
422 | Programmatically interacting with Docker using Elixir and erldocker.
423 |
424 | -
425 |
426 | https://elixirsips.dpdcart.com/subscriber/post?id=657
427 |
428 | dpd-e233171442d1ae0754eacc4696e939640b5bfe20
429 | Tue, 16 Dec 2014 21:03:00 -0500
430 |
431 | Becoming an SSH client and sending commands to an SSH server with Elixir.
432 |
433 | -
434 |
435 | https://elixirsips.dpdcart.com/subscriber/post?id=654
436 |
437 | dpd-a87e5eb201b180640c670543ba086c7b7d4a9f72
438 | Tue, 09 Dec 2014 18:59:00 -0500
439 |
440 | Handling typical unix-script style stdin and stdout pipes trivially from your Elixir scripts.
441 |
442 | -
443 |
444 | https://elixirsips.dpdcart.com/subscriber/post?id=645
445 |
446 | dpd-ee99fa700b78a267fa1f8c55f8c01511456df35f
447 | Wed, 03 Dec 2014 23:33:00 -0500
448 |
449 | Letting the computer (rather than logs or users) tell you when you've written crap code.
450 |
451 | -
452 |
453 | https://elixirsips.dpdcart.com/subscriber/post?id=643
454 |
455 | dpd-c00cd6d759f761b0a0b742de63f9c29a96a6f699
456 | Mon, 01 Dec 2014 07:59:00 -0500
457 |
458 | Layering type information over your functions to aid users and static analysis tools, and to catch errors.
459 |
460 | -
461 |
462 | https://elixirsips.dpdcart.com/subscriber/post?id=638
463 |
464 | dpd-927333737693cfb77a9706a96783b0b26e0a5224
465 | Tue, 25 Nov 2014 20:44:00 -0500
466 |
467 | Writing a renderer for the Tetris clone using SDL.
468 |
469 | -
470 |
471 | https://elixirsips.dpdcart.com/subscriber/post?id=637
472 |
473 | dpd-e37cbee9e0fe7e7d1788f953d18f89b6aa406ce5
474 | Sat, 22 Nov 2014 17:16:00 -0500
475 |
476 | Using the SDL library for graphics from your Elixir programs.
477 |
478 | -
479 |
480 | https://elixirsips.dpdcart.com/subscriber/post?id=634
481 |
482 | dpd-4ee0aac740bec073ce1bb91ff3ff5929c5c828b7
483 | Thu, 20 Nov 2014 08:16:00 -0500
484 |
485 | Test-driven implementation of clearing full lines off of the board.
486 |
487 | -
488 |
489 | https://elixirsips.dpdcart.com/subscriber/post?id=631
490 |
491 | dpd-2f8286bdd29e9bb7d86e9676638a666c86a1ff8e
492 | Fri, 14 Nov 2014 21:37:00 -0500
493 |
494 | Introducing collision detection and cleaning up the renderer / game board data structure.
495 |
496 | -
497 |
498 | https://elixirsips.dpdcart.com/subscriber/post?id=627
499 |
500 | dpd-6a46442be4571a93705954a582c5885a497ff685
501 | Thu, 06 Nov 2014 23:22:00 -0500
502 |
503 | Introducing multiple processes into the game, and running the render loop separately from the game logic.
504 |
505 | -
506 |
507 | https://elixirsips.dpdcart.com/subscriber/post?id=624
508 |
509 | dpd-f233bbfc33aa85e7832a11426671183d2d95dc55
510 | Sun, 02 Nov 2014 23:18:00 -0500
511 |
512 | Defining the bottom game board boundary and providing the next shape when needed.
513 |
514 | -
515 |
516 | https://elixirsips.dpdcart.com/subscriber/post?id=622
517 |
518 | dpd-811a3aa5d8966503cc49ed3c9757055a5bcf9586
519 | Sun, 02 Nov 2014 21:23:00 -0500
520 |
521 | Writing some tests and implementing board boundary collision.
522 |
523 | -
524 |
525 | https://elixirsips.dpdcart.com/subscriber/post?id=619
526 |
527 | dpd-fef031dde7b866f23950072bea13e731c590177f
528 | Tue, 28 Oct 2014 21:04:00 -0400
529 |
530 | Turning a gigantic module into something a little more sensible and well-factored.
531 |
532 | -
533 |
534 | https://elixirsips.dpdcart.com/subscriber/post?id=615
535 |
536 | dpd-9490d359b6f6480466e0d17fb0ceeb5025c70a7c
537 | Fri, 24 Oct 2014 07:41:00 -0400
538 |
539 | Making pieces fall and drawing the game board.
540 |
541 | -
542 |
543 | https://elixirsips.dpdcart.com/subscriber/post?id=613
544 |
545 | dpd-f3edf3f7c6d966f64791adb64d9e9cc6f3eca92a
546 | Sun, 19 Oct 2014 10:20:00 -0400
547 |
548 | Handling keyboard input in a wx application.
549 |
550 | -
551 |
552 | https://elixirsips.dpdcart.com/subscriber/post?id=610
553 |
554 | dpd-7fe2b76fd43d84e2c2f074f626c6360885b422ab
555 | Tue, 14 Oct 2014 19:11:00 -0400
556 |
557 | Using libpcap from Elixir to see the stream of data passing across your computer's network interface.
558 |
559 | -
560 |
561 | https://elixirsips.dpdcart.com/subscriber/post?id=608
562 |
563 | dpd-aa0ea81d95cc77daf72a85eb9a4d7b2cc14e32c5
564 | Fri, 10 Oct 2014 20:11:00 -0400
565 |
566 | A pleasant-to-use benchmarking tool that includes graph output.
567 |
568 | -
569 |
570 | https://elixirsips.dpdcart.com/subscriber/post?id=604
571 |
572 | dpd-e8e5511796e5bc8f391ff65b4014adf8899e50f8
573 | Sun, 05 Oct 2014 21:34:00 -0400
574 |
575 | Streaming a Twitter search to the browser, because Phoenix Channels are meant to be paired with Elixir Streams, I promise.
576 |
577 | -
578 |
579 | https://elixirsips.dpdcart.com/subscriber/post?id=601
580 |
581 | dpd-c89075095b1d46d4a13e2d11958d01656caf19ae
582 | Sun, 28 Sep 2014 20:31:00 -0400
583 |
584 | A library for interacting with the Twitter API, using standard requests or the streaming responses.
585 |
586 | -
587 |
588 | https://elixirsips.dpdcart.com/subscriber/post?id=598
589 |
590 | dpd-083ba8cf5050fa6ce7eeb0af9491f43cbcc0ff43
591 | Tue, 23 Sep 2014 08:53:00 -0400
592 |
593 | A pleasant abstraction around `gen_tcp`, `gen_udp`, `gen_sctp`, and `ssl`.
594 |
595 | -
596 |
597 | https://elixirsips.dpdcart.com/subscriber/post?id=597
598 |
599 | dpd-c58f993cd7989a400eede8dd47a7af8d46a27d9f
600 | Mon, 22 Sep 2014 08:24:00 -0400
601 |
602 | Upgrading an application in-place without losing the running state.
603 |
604 | -
605 |
606 | https://elixirsips.dpdcart.com/subscriber/post?id=593
607 |
608 | dpd-acf2a0f4cb183eb062a40a9598a9302c7a626f39
609 | Tue, 16 Sep 2014 21:39:00 -0400
610 |
611 | Using `exrm` to build a release of the BEAM Toolbox webapp, for deployment.
612 |
613 | -
614 |
615 | https://elixirsips.dpdcart.com/subscriber/post?id=587
616 |
617 | dpd-b8ac8701972a04a0cbd6b0c60bf492c2737bbbe0
618 | Wed, 03 Sep 2014 10:30:00 -0400
619 |
620 | Building a parser for a custom text format.
621 |
622 | -
623 |
624 | https://elixirsips.dpdcart.com/subscriber/post?id=583
625 |
626 | dpd-c665b632229ab6dc424973039ae636f48e4890be
627 | Wed, 27 Aug 2014 21:50:00 -0400
628 |
629 | Generating killer marketing strategies with Elixir.
630 |
631 | -
632 |
633 | https://elixirsips.dpdcart.com/subscriber/post?id=580
634 |
635 | dpd-5111589d3b478af44902337fe7afe52576b60989
636 | Fri, 22 Aug 2014 22:31:00 -0400
637 |
638 | Trivial interop between Ruby and Elixir processes using BERT-RPC.
639 |
640 | -
641 |
642 | https://elixirsips.dpdcart.com/subscriber/post?id=579
643 |
644 | dpd-5f317ac754021b12102cae9ba157bc2d809b5649
645 | Fri, 22 Aug 2014 21:02:00 -0400
646 |
647 | Switching to the expression style in Ecto, and using Phoenix's new routing helpers because we must.
648 |
649 | -
650 |
651 | https://elixirsips.dpdcart.com/subscriber/post?id=575
652 |
653 | dpd-91f1b312424926a9a9a6b2426cb0a927dbd78102
654 | Thu, 14 Aug 2014 21:56:00 -0400
655 |
656 | Building a projects listing page, and reviewing some changes to the toolbox.
657 |
658 | -
659 |
660 | https://elixirsips.dpdcart.com/subscriber/post?id=573
661 |
662 | dpd-f81f297bd0350327a6e0c1faced14ab6811363a3
663 | Tue, 12 Aug 2014 22:17:00 -0400
664 |
665 | Building a CLI utility for categorizing our projects as a Mix task.
666 |
667 | -
668 |
669 | https://elixirsips.dpdcart.com/subscriber/post?id=570
670 |
671 | dpd-585b5ae36896368f777ef3195edb016d1ead6e91
672 | Sat, 09 Aug 2014 19:06:00 -0400
673 |
674 | Making the BEAM Toolbox a bit more useful, including adding in Disqus support.
675 |
676 | -
677 |
678 | https://elixirsips.dpdcart.com/subscriber/post?id=568
679 |
680 | dpd-02f5a698c7d6d087cdb5cd18d3b5cdcf85e7363b
681 | Wed, 06 Aug 2014 21:13:00 -0400
682 |
683 | Managing relationships in Ecto, and integrating Ecto into a Phoenix application.
684 |
685 | -
686 |
687 | https://elixirsips.dpdcart.com/subscriber/post?id=565
688 |
689 | dpd-2fc64308b007410f03d937162254b10973ab220b
690 | Fri, 01 Aug 2014 21:26:00 -0400
691 |
692 | In which we contribute to the elixir codebase and open a pull request.
693 |
694 | -
695 |
696 | https://elixirsips.dpdcart.com/subscriber/post?id=564
697 |
698 | dpd-49e8f9751e2d5a3208fb6ffb842a523e7f46162c
699 | Fri, 01 Aug 2014 20:07:00 -0400
700 |
701 | Resurrecting the Toolbox with an Ecto-based data layer from scratch, and synchronizing data with the Hex API.
702 |
703 | -
704 |
705 | https://elixirsips.dpdcart.com/subscriber/post?id=560
706 |
707 | dpd-302ae6d30a495321152d507c8b317be4d435d738
708 | Thu, 24 Jul 2014 13:30:00 -0400
709 |
710 | An unusually formatted episode discussing an ad hoc serial protocol for controlling an Arduino Motor Controller.
711 |
712 | -
713 |
714 | https://elixirsips.dpdcart.com/subscriber/post?id=558
715 |
716 | dpd-5a370d8efd28e8e2cc174a2b2449aad11fac37f1
717 | Sat, 19 Jul 2014 18:13:00 -0400
718 |
719 | Fixing some bugs and setting up a Zapier integration.
720 |
721 | -
722 |
723 | https://elixirsips.dpdcart.com/subscriber/post?id=555
724 |
725 | dpd-883ff61ee202bcb7ba7da9fbae418e4bd3ae21a9
726 | Wed, 16 Jul 2014 08:18:00 -0400
727 |
728 | Deploying our application to a VPS from scratch and pushing in our first message.
729 |
730 | -
731 |
732 | https://elixirsips.dpdcart.com/subscriber/post?id=551
733 |
734 | dpd-d9706ecb2eddc2f1265977c3767132d703e63b14
735 | Sat, 12 Jul 2014 10:07:00 -0400
736 |
737 | Using Phoenix to build an HTTP API for posting links into the system, and a page to view posted links.
738 |
739 | -
740 |
741 | https://elixirsips.dpdcart.com/subscriber/post?id=549
742 |
743 | dpd-4d7756a95e58a7151b033edbeb9ac9386df4d36e
744 | Wed, 09 Jul 2014 18:31:00 -0400
745 |
746 | Using poolboy to build a service for extracting data from a set of links and collecting them into memory for viewing later.
747 |
748 | -
749 |
750 | https://elixirsips.dpdcart.com/subscriber/post?id=546
751 |
752 | dpd-180544202457b1d326bf80666b28af22046a3e75
753 | Sun, 06 Jul 2014 20:02:00 -0400
754 |
755 | Exploring test coverage report generation, using both Erlang's `cover` application and the Coverex tool.
756 |
757 | -
758 |
759 | https://elixirsips.dpdcart.com/subscriber/post?id=544
760 |
761 | dpd-0fdc55a7a7013258f5a35f37fa503d09e73e0356
762 | Thu, 03 Jul 2014 23:44:00 -0400
763 |
764 | Taking advantage of Phoenix's native websockets support to build an in-browser bash terminal proxy.
765 |
766 | -
767 |
768 | https://elixirsips.dpdcart.com/subscriber/post?id=542
769 |
770 | dpd-b02d6c3df00731d250faf39354fe4a7095f9ee04
771 | Sun, 29 Jun 2014 19:39:00 -0400
772 |
773 | Easy cross-language serialization and deserialization of data structures using Google's Protocol Buffers and exprotobuf.
774 |
775 | -
776 |
777 | https://elixirsips.dpdcart.com/subscriber/post?id=540
778 |
779 | dpd-5798eed6be9e1bf456e98152b373fc342ec95a2b
780 | Wed, 25 Jun 2014 19:32:00 -0400
781 |
782 | External Process interaction like the Port module but both simpler and more powerful.
783 |
784 | -
785 |
786 | https://elixirsips.dpdcart.com/subscriber/post?id=536
787 |
788 | dpd-b3f1b7c7e02310104d87c390dddbf98cd266e7a7
789 | Fri, 20 Jun 2014 22:03:00 -0400
790 |
791 | Using Elixir to do a word frequency count on a corpus of text and generate input for a WordCloud generator.
792 |
793 | -
794 |
795 | https://elixirsips.dpdcart.com/subscriber/post?id=534
796 |
797 | dpd-4b8e26be7785f03eafdc51bb0c0f47c64e8351ed
798 | Wed, 18 Jun 2014 20:13:00 -0400
799 |
800 | (and friends) Easy access to deeply nested data structures.
801 |
802 | -
803 |
804 | https://elixirsips.dpdcart.com/subscriber/post?id=532
805 |
806 | dpd-12ef837138f05aff4c38e8236d52abdde5768a2a
807 | Fri, 13 Jun 2014 20:35:00 -0400
808 |
809 | Awesome Print for Elixir. An easy way to get insight into unfamiliar data structures.
810 |
811 | -
812 |
813 | https://elixirsips.dpdcart.com/subscriber/post?id=529
814 |
815 | dpd-a3f00fa2222695d5201010c1cfe11d6d636da20a
816 | Wed, 11 Jun 2014 20:40:00 -0400
817 |
818 | Generating PCM Audio and making some noise
819 |
820 | -
821 |
822 | https://elixirsips.dpdcart.com/subscriber/post?id=526
823 |
824 | dpd-47d220d5ef4b985a9f07078a20d08a8462c21181
825 | Sat, 07 Jun 2014 14:49:00 -0400
826 |
827 | A replacement for the `pg` module that has some better semantics for distribution.
828 |
829 | -
830 |
831 | https://elixirsips.dpdcart.com/subscriber/post?id=525
832 |
833 | dpd-dcfd4eac814073147a5516503376089f77c5a9f8
834 | Thu, 05 Jun 2014 20:04:00 -0400
835 |
836 | A fantastic method for polymorphism in Elixir. Pairs well with structs. Slight oaky flavor.
837 |
838 | -
839 |
840 | https://elixirsips.dpdcart.com/subscriber/post?id=520
841 |
842 | dpd-43db540c7570c6c7ed3c617a99240f0bbb1f243a
843 | Sat, 31 May 2014 20:37:00 -0400
844 |
845 | Elixir's built-in templating language, useful for embedding Elixir code inside of a string.
846 |
847 | -
848 |
849 | https://elixirsips.dpdcart.com/subscriber/post?id=518
850 |
851 | dpd-8132ce5c5d34243a225e1c82697de23d3bc624b9
852 | Tue, 27 May 2014 21:26:00 -0400
853 |
854 | A client for the Ubigraph visualization server, and an easy way to view a BEAM application's supervision tree in 3D.
855 |
856 | -
857 |
858 | https://elixirsips.dpdcart.com/subscriber/post?id=516
859 |
860 | dpd-87e63ba90c98728379af851919648fe07b7a40a6
861 | Fri, 23 May 2014 20:01:00 -0400
862 |
863 | An abstraction for computing a value in the background and receiving the value later.
864 |
865 | -
866 |
867 | https://elixirsips.dpdcart.com/subscriber/post?id=514
868 |
869 | dpd-b2e65fcb8b6c7f0ab5b36a4d9ce38912d250ee4d
870 | Wed, 21 May 2014 08:41:00 -0400
871 |
872 | A simple abstraction around state.
873 |
874 | -
875 |
876 | https://elixirsips.dpdcart.com/subscriber/post?id=511
877 |
878 | dpd-0baf24d09f1946547bcbbd3cb58b3bcee0a4472d
879 | Sat, 17 May 2014 19:30:00 -0400
880 |
881 | Manually raising exceptions, handling them, defining your own, and using them idiomatically.
882 |
883 | -
884 |
885 | https://elixirsips.dpdcart.com/subscriber/post?id=510
886 |
887 | dpd-4553c702f0b65282255299c8889144327e829525
888 | Thu, 15 May 2014 19:15:00 -0400
889 |
890 | A brief overview of Elixir's 'lazy, composable Enumerables'
891 |
892 | -
893 |
894 | https://elixirsips.dpdcart.com/subscriber/post?id=508
895 |
896 | dpd-4b31583fdd92d59e040252cb3d5b1570e62e6858
897 | Mon, 12 May 2014 20:17:00 -0400
898 |
899 | A disk-based version of ETS with a few restrictions.
900 |
901 | -
902 |
903 | https://elixirsips.dpdcart.com/subscriber/post?id=506
904 |
905 | dpd-f152d5bdd1d5be150249695d77b4fca5a394c08e
906 | Thu, 08 May 2014 20:57:00 -0400
907 |
908 | Erlang term storage - a queryable database for your processes to store terms in.
909 |
910 | -
911 |
912 | https://elixirsips.dpdcart.com/subscriber/post?id=502
913 |
914 | dpd-f3f23a2777bb286c18290efd430e60f228c7e6ed
915 | Thu, 01 May 2014 18:39:00 -0400
916 |
917 | Process-local state that you likely should never use :)
918 |
919 | -
920 |
921 | https://elixirsips.dpdcart.com/subscriber/post?id=501
922 |
923 | dpd-d95d596e71b591965a5a2bcb28620aabd0ad89e1
924 | Wed, 30 Apr 2014 23:48:00 -0400
925 |
926 | Implementing our calculator's logic and wiring it up to wx events.
927 |
928 | -
929 |
930 | https://elixirsips.dpdcart.com/subscriber/post?id=497
931 |
932 | dpd-a9cc177724158a781f328e595c039bb8bc2b2f07
933 | Fri, 25 Apr 2014 21:20:00 -0400
934 |
935 | Building a GUI calculator using Erlang's native wx bindings.
936 |
937 | -
938 |
939 | https://elixirsips.dpdcart.com/subscriber/post?id=495
940 |
941 | dpd-e0cb5d7e0131590b491d2c9275de535b803756c8
942 | Thu, 24 Apr 2014 18:56:00 -0400
943 |
944 | Elixir's new package manager.
945 |
946 | -
947 |
948 | https://elixirsips.dpdcart.com/subscriber/post?id=492
949 |
950 | dpd-c28fdc36d4fe5fd5474dff2c71630e66287db5f6
951 | Fri, 18 Apr 2014 21:54:00 -0400
952 |
953 | A graphical tool for inspection of a running Erlang/Elixir system and its processes.
954 |
955 | -
956 |
957 | https://elixirsips.dpdcart.com/subscriber/post?id=491
958 |
959 | dpd-e72209bdb29b4bff0ac78eb7ca979cc27c412b48
960 | Wed, 16 Apr 2014 22:17:00 -0400
961 |
962 | Interacting with external programs as if they were simple processes.
963 |
964 | -
965 |
966 | https://elixirsips.dpdcart.com/subscriber/post?id=486
967 |
968 | dpd-6ebee8d2f0b706ca970a4367194f0127231575fc
969 | Fri, 11 Apr 2014 23:08:00 -0400
970 |
971 | Using HashNuke's Elixir buildpack for Heroku to deploy BEAM Toolbox. Also, a brief intro to ExConf.
972 |
973 | -
974 |
975 | https://elixirsips.dpdcart.com/subscriber/post?id=484
976 |
977 | dpd-4d63be468edc18b13f5aa6e8cb8dab4a7bf8262f
978 | Thu, 10 Apr 2014 08:48:00 -0400
979 |
980 | Serving static files without an opaque and complicated-looking cowboy handler.
981 |
982 | -
983 |
984 | https://elixirsips.dpdcart.com/subscriber/post?id=482
985 |
986 | dpd-a658ffc1634b8bc86668e72bd37bfd6f5e73e03d
987 | Sun, 06 Apr 2014 22:29:00 -0400
988 |
989 | Using Erlang's `ssh` module to provide ssh access to a shell running your Elixir code.
990 |
991 | -
992 |
993 | https://elixirsips.dpdcart.com/subscriber/post?id=481
994 |
995 | dpd-d99967a1059c652a616cf9921718fd67080257fb
996 | Sun, 06 Apr 2014 19:48:00 -0400
997 |
998 | A look at using the `digraph`module from the Erlang standard library to implement pathfinding on a map.
999 |
1000 | -
1001 |
1002 | https://elixirsips.dpdcart.com/subscriber/post?id=474
1003 |
1004 | dpd-4e61ce171d447be49260aa7e2b150fa18f95897e
1005 | Thu, 27 Mar 2014 21:02:00 -0400
1006 |
1007 | A quick tour of the `dbg` module from Erlang, and its tracing features.
1008 |
1009 | -
1010 |
1011 | https://elixirsips.dpdcart.com/subscriber/post?id=472
1012 |
1013 | dpd-0660032706dba19d1e9f0cf08d7cb3e37a21a744
1014 | Tue, 25 Mar 2014 22:44:00 -0400
1015 |
1016 | Using processes, gs, and shelling out to `sox` to build an Elixir-based synthesizer module.
1017 |
1018 | -
1019 |
1020 | https://elixirsips.dpdcart.com/subscriber/post?id=469
1021 |
1022 | dpd-36c61c1cf1777823ac10c7606ccd7b5f75a67920
1023 | Sat, 22 Mar 2014 19:20:00 -0400
1024 |
1025 | Exploring Elixir's library for building composable web application modules.
1026 |
1027 | -
1028 |
1029 | https://elixirsips.dpdcart.com/subscriber/post?id=467
1030 |
1031 | dpd-7322184862f713f43c6c8395259fc337d9153c22
1032 | Tue, 18 Mar 2014 22:32:00 -0400
1033 |
1034 | Elixir's list comprehensions have been entirely revamped, and made much more general. In this episode, we cover new style comprehensions and show off a few tricks they have that older style list comprehensions lacked.
1035 |
1036 | -
1037 |
1038 | https://elixirsips.dpdcart.com/subscriber/post?id=465
1039 |
1040 | dpd-73820b197f2fe7c911ffd1a6e6327bbef4ac578f
1041 | Sun, 16 Mar 2014 22:35:00 -0400
1042 |
1043 | Looking at building a basic mix task, and how you can go about testing it.
1044 |
1045 | -
1046 |
1047 | https://elixirsips.dpdcart.com/subscriber/post?id=462
1048 |
1049 | dpd-cce33fba9f7149ccba921db7d3dc8d2e751d6956
1050 | Thu, 13 Mar 2014 00:14:00 -0400
1051 |
1052 | Building a module that caches our GitHub data for a given project.
1053 |
1054 | -
1055 |
1056 | https://elixirsips.dpdcart.com/subscriber/post?id=461
1057 |
1058 | dpd-bb321df4c9d144a7344f2fdb61fb74694b61d882
1059 | Sun, 09 Mar 2014 21:59:00 -0400
1060 |
1061 | Moving our ad-hoc, tuple-based data layer to one powered by maps/structs.
1062 |
1063 | -
1064 |
1065 | https://elixirsips.dpdcart.com/subscriber/post?id=460
1066 |
1067 | dpd-0ef3f8fd496568b10e0d0d39c5d5e8934c0d3e6e
1068 | Sun, 09 Mar 2014 21:00:00 -0400
1069 |
1070 | Converting a production use of Records to use maps instead.
1071 |
1072 | -
1073 |
1074 | https://elixirsips.dpdcart.com/subscriber/post?id=454
1075 |
1076 | dpd-d1041c309aec57eed32a2ddae004a25b76051172
1077 | Fri, 28 Feb 2014 08:47:00 -0500
1078 |
1079 | Introducing structs and demonstrating how they can take the place of public Records.
1080 |
1081 | -
1082 |
1083 | https://elixirsips.dpdcart.com/subscriber/post?id=453
1084 |
1085 | dpd-4bf94deea259915d3c357b7588820bc5b3318f66
1086 | Thu, 27 Feb 2014 21:59:00 -0500
1087 |
1088 | An introduction to maps, a new feature in Erlang R17 and Elixir 0.13
1089 |
1090 | -
1091 |
1092 | https://elixirsips.dpdcart.com/subscriber/post?id=448
1093 |
1094 | dpd-55b3631f3c7a1da543dc917e68b1ae622dcce5d2
1095 | Thu, 20 Feb 2014 09:10:00 -0500
1096 |
1097 | Adding an integration testing layer that drives a browser using Hound, extracting a Controller helper, and adding Project pages.
1098 |
1099 | -
1100 |
1101 | https://elixirsips.dpdcart.com/subscriber/post?id=444
1102 |
1103 | dpd-cc87a225650e38932c583a9c9a6f14a40dba3e78
1104 | Sat, 15 Feb 2014 09:37:00 -0500
1105 |
1106 | Further work on the data layer, and introducing defoverridable.
1107 |
1108 | -
1109 |
1110 | https://elixirsips.dpdcart.com/subscriber/post?id=442
1111 |
1112 | dpd-b5a31a1c01922facab2dd79afa8f1dcd8f78d168
1113 | Wed, 12 Feb 2014 08:58:00 -0500
1114 |
1115 | Introducing BEAM Toolbox and starting work on the data layer.
1116 |
1117 | -
1118 |
1119 | https://elixirsips.dpdcart.com/subscriber/post?id=439
1120 |
1121 | dpd-210f6831832d5b498f195a3b100c52c0f1373294
1122 | Thu, 06 Feb 2014 19:27:00 -0500
1123 |
1124 | Accepting environment variables for configuration and filtering out files we don't want. Plus, a call to action to build BEAM Toolbox.
1125 |
1126 | -
1127 |
1128 | https://elixirsips.dpdcart.com/subscriber/post?id=434
1129 |
1130 | dpd-6a2c146afddf3c6d0aac75a41537080b0fbd0988
1131 | Sat, 01 Feb 2014 16:35:00 -0500
1132 |
1133 | Building a poor man's livereload system using inotify and websockets.
1134 |
1135 | -
1136 |
1137 | https://elixirsips.dpdcart.com/subscriber/post?id=433
1138 |
1139 | dpd-8756e2da33bdff1224a927bb6725375ee4bf3065
1140 | Fri, 31 Jan 2014 21:35:00 -0500
1141 |
1142 | Using Eml for markup, and bringing in Compassand Zurb Foundation for styles.
1143 |
1144 | -
1145 |
1146 | https://elixirsips.dpdcart.com/subscriber/post?id=429
1147 |
1148 | dpd-9eecb23975d8d108aea78a6cf6fac511e602b68d
1149 | Fri, 24 Jan 2014 23:20:00 -0500
1150 |
1151 | Writing an integration test suite and dealing with macros for the first time.
1152 |
1153 | -
1154 |
1155 | https://elixirsips.dpdcart.com/subscriber/post?id=428
1156 |
1157 | dpd-13698c101c78abe21fabecbde8e98ad865cd2c93
1158 | Fri, 24 Jan 2014 19:35:00 -0500
1159 |
1160 | Building a HTTP Server to render Markdown files, using the Phoenix web framework.
1161 |
1162 | -
1163 |
1164 | https://elixirsips.dpdcart.com/subscriber/post?id=424
1165 |
1166 | dpd-5b77eca5d0443e39ab5c5e4e495e4879af7daba9
1167 | Sat, 18 Jan 2014 10:02:00 -0500
1168 |
1169 | Sending messages to remote machines, and Joe Armstrong's favorite program.
1170 |
1171 | -
1172 |
1173 | https://elixirsips.dpdcart.com/subscriber/post?id=422
1174 |
1175 | dpd-db9a5eb0b78fe97ab2c8430979a97433124b2f26
1176 | Mon, 13 Jan 2014 21:55:00 -0500
1177 |
1178 | Sending messages from one Elixir node to another.
1179 |
1180 | -
1181 |
1182 | https://elixirsips.dpdcart.com/subscriber/post?id=418
1183 |
1184 | dpd-d133276fb29a92296ec17f38cec53dfabe6816a6
1185 | Thu, 09 Jan 2014 07:46:00 -0500
1186 |
1187 | Making your Elixir application redistributable using Erlang releases.
1188 |
1189 | -
1190 |
1191 | https://elixirsips.dpdcart.com/subscriber/post?id=417
1192 |
1193 | dpd-c00b5d5fe3f67a42fa32b512cd5d481b72a52365
1194 | Tue, 07 Jan 2014 09:25:00 -0500
1195 |
1196 | In today's episode, we cover the second half of the File module.
1197 |
1198 | -
1199 |
1200 | https://elixirsips.dpdcart.com/subscriber/post?id=414
1201 |
1202 | dpd-499a0a8b85df049ab85293a4be963e699eb25287
1203 | Thu, 02 Jan 2014 08:52:00 -0500
1204 |
1205 | An overview of the first portion of the File module in the standard library.
1206 |
1207 | -
1208 |
1209 | https://elixirsips.dpdcart.com/subscriber/post?id=413
1210 |
1211 | dpd-00de1169c5f8066cb354b4ad6d3872accb638452
1212 | Thu, 02 Jan 2014 08:10:00 -0500
1213 |
1214 | In this episode, we look at manipulating bits. This is typically useful for wire protocols.
1215 |
1216 | -
1217 |
1218 | https://elixirsips.dpdcart.com/subscriber/post?id=411
1219 |
1220 | dpd-72bb8b378b48b17690f5e00ea5abc5761354b5b5
1221 | Fri, 27 Dec 2013 09:31:00 -0500
1222 |
1223 | In this episode, we use what we know about binary deconstruction to build a library to parse IP packets.
1224 |
1225 | -
1226 |
1227 | https://elixirsips.dpdcart.com/subscriber/post?id=409
1228 |
1229 | dpd-6b3e01c68dd4f87245ff2e5213242d90346c47f4
1230 | Thu, 26 Dec 2013 07:49:00 -0500
1231 |
1232 | Erlang provides extremely good tools for handling binaries, and Elixir benefits from them as well. In this episode, we look at how to construct and deconstruct binaries quickly.
1233 |
1234 | -
1235 |
1236 | https://elixirsips.dpdcart.com/subscriber/post?id=405
1237 |
1238 | dpd-56d26d6d1fbb5a7950dc729092911cdec2d9ac05
1239 | Thu, 19 Dec 2013 08:48:00 -0500
1240 |
1241 | Fantastic logging for your applications.
1242 |
1243 | -
1244 |
1245 | https://elixirsips.dpdcart.com/subscriber/post?id=404
1246 |
1247 | dpd-261731b9e92d9ee9a3c86ff411b1a2537603fe92
1248 | Tue, 17 Dec 2013 16:25:00 -0500
1249 |
1250 | Building a simple cache, and a performance comparison with node.js and ruby.
1251 |
1252 | -
1253 |
1254 | https://elixirsips.dpdcart.com/subscriber/post?id=399
1255 |
1256 | dpd-f2cb043205443522542977a84f173d74a5095b35
1257 | Thu, 12 Dec 2013 08:45:00 -0500
1258 |
1259 | Building a basic web app with the Weber MVC framework.
1260 |
1261 | -
1262 |
1263 | https://elixirsips.dpdcart.com/subscriber/post?id=398
1264 |
1265 | dpd-65b2f632050407fd4525404b1282c579d6ed14b2
1266 | Mon, 09 Dec 2013 02:28:00 -0500
1267 |
1268 | Introduction to Elixiak - an ActiveRecord-like wrapper for Riak in Elixir.
1269 |
1270 | -
1271 |
1272 | https://elixirsips.dpdcart.com/subscriber/post?id=396
1273 |
1274 | dpd-7cfb53216e3d6f1319bec0f1f878739e03dca03e
1275 | Sun, 08 Dec 2013 18:59:00 -0500
1276 |
1277 | Using IEx.pry to inspect and debug a running process.
1278 |
1279 | -
1280 |
1281 | https://elixirsips.dpdcart.com/subscriber/post?id=392
1282 |
1283 | dpd-a71b04315dd935bbc978fc0c48b2e6c4f8a8a663
1284 | Tue, 03 Dec 2013 08:13:00 -0500
1285 |
1286 | Basic Introduction to writing Elixir scripts that can be invoked and passed arguments from the command line.
1287 |
1288 | -
1289 |
1290 | https://elixirsips.dpdcart.com/subscriber/post?id=389
1291 |
1292 | dpd-ef4d8f3f5fc91b2757f9db478454889a62b1f2be
1293 | Thu, 28 Nov 2013 10:07:00 -0500
1294 |
1295 | Building network servers in Elixir using Erlang's `:gen_tcp` module.
1296 |
1297 | -
1298 |
1299 | https://elixirsips.dpdcart.com/subscriber/post?id=387
1300 |
1301 | dpd-b591602d8d685dfc5b65373c9eec81be2ba3533e
1302 | Tue, 26 Nov 2013 09:05:00 -0500
1303 |
1304 | Simplified generation of generic servers.
1305 |
1306 | -
1307 |
1308 | https://elixirsips.dpdcart.com/subscriber/post?id=382
1309 |
1310 | dpd-9fce90acc12b203cf01876bb05427ee108630e6e
1311 | Thu, 21 Nov 2013 09:25:00 -0500
1312 |
1313 | A survey of the HTTP Client landscape.
1314 |
1315 | -
1316 |
1317 | https://elixirsips.dpdcart.com/subscriber/post?id=380
1318 |
1319 | dpd-4332e4d1b7b33b371e7b0d86f83862092c9f0b77
1320 | Tue, 19 Nov 2013 07:53:00 -0500
1321 |
1322 | A glimpse into XML parsing in Elixir, by way of interoperating with an Erlang module.
1323 |
1324 | -
1325 |
1326 | https://elixirsips.dpdcart.com/subscriber/post?id=377
1327 |
1328 | dpd-8fdb7bb8bce5bdf73f15457057d88bdc801e4374
1329 | Thu, 14 Nov 2013 19:14:00 -0500
1330 |
1331 | A brief overview of the second portion of the Dict module.
1332 |
1333 | -
1334 |
1335 | https://elixirsips.dpdcart.com/subscriber/post?id=376
1336 |
1337 | dpd-b2055c1c5f75983643083fdaeb9f6a4ed25a4a5c
1338 | Thu, 14 Nov 2013 19:10:00 -0500
1339 |
1340 | A brief overview of the first portion of the Dict module.
1341 |
1342 | -
1343 |
1344 | https://elixirsips.dpdcart.com/subscriber/post?id=372
1345 |
1346 | dpd-290d62fd9b993b10aa73be0786505f57c4c9775e
1347 | Thu, 07 Nov 2013 22:20:00 -0500
1348 |
1349 | Overhauling our Dynamo webapp to use Ecto for its persistence layer.
1350 |
1351 | -
1352 |
1353 | https://elixirsips.dpdcart.com/subscriber/post?id=370
1354 |
1355 | dpd-77f9f7e016cf01cd0868b6c56d03c0ff9e7816de
1356 | Tue, 05 Nov 2013 15:07:00 -0500
1357 |
1358 | A brief introduction to using Ecto with Postgres for persistence.
1359 |
1360 | -
1361 |
1362 | https://elixirsips.dpdcart.com/subscriber/post?id=367
1363 |
1364 | dpd-9ba61b7503e2a2d8c97d21be0bdc943e94e2818e
1365 | Fri, 01 Nov 2013 22:41:00 -0400
1366 |
1367 | Making a supervised process's state live through a crash.
1368 |
1369 | -
1370 |
1371 | https://elixirsips.dpdcart.com/subscriber/post?id=363
1372 |
1373 | dpd-4e48d92ef15a55278c611d3898036214ac98efb4
1374 | Tue, 29 Oct 2013 08:00:00 -0400
1375 |
1376 | Exploring OTP's Supervisors, and how they help us recover from crashes in processes.
1377 |
1378 | -
1379 |
1380 | https://elixirsips.dpdcart.com/subscriber/post?id=362
1381 |
1382 | dpd-676d292488550356f768d103eecdf164e1ad32ca
1383 | Fri, 25 Oct 2013 19:05:00 -0400
1384 |
1385 | We build a couple more components in the ZeldaCat game for more practice with GenEvent
1386 |
1387 | -
1388 |
1389 | https://elixirsips.dpdcart.com/subscriber/post?id=361
1390 |
1391 | dpd-4c1da796dbd7b1ecb3709e70212dd3f3b934a90c
1392 | Wed, 23 Oct 2013 12:38:00 -0400
1393 |
1394 | An introduction to OTP's GenEvent
1395 |
1396 | -
1397 |
1398 | https://elixirsips.dpdcart.com/subscriber/post?id=359
1399 |
1400 | dpd-c393e93f2dcb42019ba8c0c2bc7b8aa5e9976141
1401 | Mon, 21 Oct 2013 11:02:00 -0400
1402 |
1403 | Wrapping up the Enum module
1404 |
1405 | -
1406 |
1407 | https://elixirsips.dpdcart.com/subscriber/post?id=350
1408 |
1409 | dpd-0f8303cdbc9ee941521caaf7b76731da0b3d4d19
1410 | Tue, 15 Oct 2013 23:06:00 -0400
1411 |
1412 | A brief overview of the second portion of the Enum module from the standard library
1413 |
1414 | -
1415 |
1416 | https://elixirsips.dpdcart.com/subscriber/post?id=348
1417 |
1418 | dpd-8049517948868c47e602daa299edb1dadd758da3
1419 | Sun, 13 Oct 2013 22:01:00 -0400
1420 |
1421 | A brief overview of the first portion of the Enum module from the standard library
1422 |
1423 | -
1424 |
1425 | https://elixirsips.dpdcart.com/subscriber/post?id=344
1426 |
1427 | dpd-dc264ea5c3e0543c762c273788859c236e2a1dec
1428 | Tue, 08 Oct 2013 09:49:00 -0400
1429 |
1430 | Elixir supports the Pipe Operator - `|>` - which acts very similar to pipes in Unix. We'll dig into it.
1431 |
1432 | -
1433 |
1434 | https://elixirsips.dpdcart.com/subscriber/post?id=341
1435 |
1436 | dpd-b9660be464972f6ba5dae7527063c62fc046317e
1437 | Fri, 04 Oct 2013 08:59:00 -0400
1438 |
1439 | An overview of the GenFSM OTP module and an example use case.
1440 |
1441 | -
1442 |
1443 | https://elixirsips.dpdcart.com/subscriber/post?id=338
1444 |
1445 | dpd-5a5f721b54d22157b4be94f84e1f4532daa2de1c
1446 | Tue, 01 Oct 2013 16:15:00 -0400
1447 |
1448 | In this episode, we cover the basics of building a GenServer using OTP.
1449 |
1450 | -
1451 |
1452 | https://elixirsips.dpdcart.com/subscriber/post?id=332
1453 |
1454 | dpd-ded71a95e10e1d9b65825db7415a0b4c2bf3ec9e
1455 | Fri, 27 Sep 2013 00:24:00 -0400
1456 |
1457 | Modeling a BankAccount with a process
1458 |
1459 | -
1460 |
1461 | https://elixirsips.dpdcart.com/subscriber/post?id=331
1462 |
1463 | dpd-dae0ac7be55f42aa7c2c813c1ee4a76485a473a8
1464 | Thu, 26 Sep 2013 22:29:00 -0400
1465 |
1466 | In today's episode, we're going to play with processes a bit to get a feel for how they can be used.
1467 |
1468 | -
1469 |
1470 | https://elixirsips.dpdcart.com/subscriber/post?id=324
1471 |
1472 | dpd-e76ebd6726108f35a5c8f75fd1b3561b01f16d82
1473 | Thu, 19 Sep 2013 09:02:00 -0400
1474 |
1475 | Just a quick rundown of Records in Elixir
1476 |
1477 | -
1478 |
1479 | https://elixirsips.dpdcart.com/subscriber/post?id=323
1480 |
1481 | dpd-89b5f6b22a787a4f94b7fa3844d8c858149ecb73
1482 | Tue, 17 Sep 2013 08:46:00 -0400
1483 |
1484 | List Comprehensions are a nice feature for generating lists from other lists. In this episode, we cover the basics, and we test drive a module to generate a deck of cards.
1485 |
1486 | -
1487 |
1488 | https://elixirsips.dpdcart.com/subscriber/post?id=322
1489 |
1490 | dpd-a99258169e716dd101a33fae00e27a8955cbf660
1491 | Sun, 15 Sep 2013 21:15:00 -0400
1492 |
1493 | In Episode 9, we integrate the work we did in Dynamo with our experiments in Amnesia, to hook persistence into our Dwitter application.
1494 |
1495 | -
1496 |
1497 | https://elixirsips.dpdcart.com/subscriber/post?id=317
1498 |
1499 | dpd-00f8b115e467f028f97dff6ee4173c8a51c44a50
1500 | Tue, 10 Sep 2013 11:22:00 -0400
1501 |
1502 | The second part in the series on building Dwitter, a Twitter clone, using the Dynamo web framework.
1503 |
1504 | -
1505 |
1506 | https://elixirsips.dpdcart.com/subscriber/post?id=313
1507 |
1508 | dpd-070bcc897c0822994b5119f31bece510220f188c
1509 | Thu, 05 Sep 2013 12:45:00 -0400
1510 |
1511 | Building a basic web application in Elixir using Dynamo
1512 |
1513 | -
1514 |
1515 | https://elixirsips.dpdcart.com/subscriber/post?id=311
1516 |
1517 | dpd-4df77bde9eb54fd358b172a7606761a69f3cd17b
1518 | Tue, 03 Sep 2013 10:52:00 -0400
1519 |
1520 | This is an exceptionally long episode (21 minutes) on Unit Testing in Elixir. It's substantially longer than my intended episode length, but I think it's a very important topic so I'm willing to put up with the length.
1521 |
1522 | -
1523 |
1524 | https://elixirsips.dpdcart.com/subscriber/post?id=298
1525 |
1526 | dpd-969472a9610dc652fd4076e9fe793c5abe669af5
1527 | Fri, 30 Aug 2013 08:57:00 -0400
1528 |
1529 | - Use mix to begin a new project
1530 | - Define a module
1531 | - Compile and use that module
1532 | - Examine a module's return value
1533 | - Document a module and its functions
1534 | - Generate nice HTML documentation output using ExDoc
1535 |
1536 | -
1537 |
1538 | https://elixirsips.dpdcart.com/subscriber/post?id=284
1539 |
1540 | dpd-db84d34c2d16860fe1fc943d083ad82788e3acb9
1541 | Wed, 28 Aug 2013 08:00:00 -0400
1542 |
1543 | In Elixir, functions are first class types. Today we look at: Defining Anonymous Functions; Calling Anonymous Functions; Using Functions as first class types.
1544 |
1545 | -
1546 |
1547 | https://elixirsips.dpdcart.com/subscriber/post?id=280
1548 |
1549 | dpd-3d393067166e1151725896b4a5dc0f89d886aa86
1550 | Fri, 23 Aug 2013 09:02:00 -0400
1551 |
1552 | An overview of Pattern Matching in Elixir
1553 |
1554 | -
1555 |
1556 | https://elixirsips.dpdcart.com/subscriber/post?id=275
1557 |
1558 | dpd-44f4b90e9da71339292e198d7fd419ef2220d051
1559 | Mon, 19 Aug 2013 22:48:00 -0400
1560 |
1561 | A quick overview of some of the basic types in Elixir: Atoms, Numbers, Lists, Tuples, Regexes, and Booleans.
1562 |
1563 | -
1564 |
1565 | https://elixirsips.dpdcart.com/subscriber/post?id=271
1566 |
1567 | dpd-e902c86df08867fcb3693be8cb5dd3985aecd62b
1568 | Sun, 18 Aug 2013 22:10:00 -0400
1569 |
1570 | In the first episode ever, I introduce Elixir Sips and walk through installing Erlang and Elixir
1571 |
1572 |
1573 |
1574 |
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloader.Mixfile do
2 | use Mix.Project
3 |
4 | def project do
5 | [app: :sips_downloader,
6 | version: "0.2.2",
7 | name: "SipsDownloader",
8 | source_url: "https://github.com/DavsX/SipsDownloader",
9 | elixir: "~> 1.0",
10 | description: description,
11 | package: package,
12 | deps: deps,
13 | escript: escript]
14 | end
15 |
16 | defp description do
17 | """
18 | Automatically download new ElixirSips episodes
19 | """
20 | end
21 |
22 | defp package do
23 | [
24 | maintainers: ["Dávid Kovács"],
25 | files: ["bin", "config", "lib", "mix.exs", "README*", "LICENSE*"],
26 | licenses: ["MIT"],
27 | links: %{"GitHub" => "https://github.com/DavsX/SipsDownloader"}
28 | ]
29 | end
30 |
31 | def application do
32 | [applications: [:httpoison]]
33 | end
34 |
35 | defp deps do
36 | [{:httpoison, "~> 0.7"},
37 | {:floki, "~> 0.6"},
38 | {:html_entities, "~> 0.2"}]
39 | end
40 |
41 | defp escript do
42 | [main_module: SipsDownloader]
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/mix.lock:
--------------------------------------------------------------------------------
1 | %{"floki": {:hex, :floki, "0.6.0"},
2 | "hackney": {:hex, :hackney, "1.3.2"},
3 | "html_entities": {:hex, :html_entities, "0.2.1"},
4 | "httpoison": {:hex, :httpoison, "0.7.4"},
5 | "idna": {:hex, :idna, "1.0.2"},
6 | "mochiweb": {:hex, :mochiweb, "2.12.2"},
7 | "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}}
8 |
--------------------------------------------------------------------------------
/test/feed:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Elixir Sips
5 | https://elixirsips.dpdcart.com/
6 |
7 | Wed, 01 Jul 2015 07:34:00 -0400
8 | josh.rubyist@gmail.com (Josh Adams)
9 | en
10 | Copyright 2015 Elixir Sips
11 | getdpd.com
12 | ElixirSips is a twice-weekly small dose of knowledge related to the Elixir programming language.
13 | -
14 |
15 | https://elixirsips.dpdcart.com/subscriber/post?id=821
16 |
18 |
19 |
Episode 173: Deploying Phoenix Applications to Heroku
20 |
27 |
28 | Attached Files
29 |
41 |
42 | ]]>
43 | dpd-b49e1e04b7a47bee866c63837bb98c824e47225d
44 | Wed, 01 Jul 2015 07:34:00 -0400
45 |
46 |
47 | -
48 |
49 | https://elixirsips.dpdcart.com/subscriber/post?id=821
50 |
52 |
53 |
Episode 173: Deploying Phoenix Applications to Heroku
54 |
61 |
62 | Attached Files
63 |
75 |
76 | ]]>
77 | dpd-b49e1e04b7a47bee866c63837bb98c824e47225d
78 | Wed, 01 Jul 2015 07:34:00 -0400
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/test/sips_downloader_test.exs:
--------------------------------------------------------------------------------
1 | defmodule SipsDownloaderTest do
2 | use ExUnit.Case
3 |
4 | setup do
5 | feed = File.read!("test/feed")
6 | {:ok, feed: feed}
7 | end
8 |
9 | test "processing feed", %{feed: feed} do
10 | links = SipsDownloader.FeedParser.parse_episodes(feed)
11 | expected = [{"Link1_title.mp4", "Link1_href"},
12 | {"Link2_title.mp4", "Link2_href"},
13 | {"Link3_title.mp4", "Link3_href"},
14 | {"Link4_title.mp4", "Link4_href"}]
15 |
16 | assert links == expected
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------