Update
This commit is contained in:
parent
b223efbeec
commit
f33fb9da78
|
@ -7,12 +7,14 @@ category: Ansible
|
||||||
|
|
||||||
- apt_key: id=AC40B2F7 url="http://..."
|
- apt_key: id=AC40B2F7 url="http://..."
|
||||||
state=present
|
state=present
|
||||||
|
|
||||||
- apt: pkg=nodejs state=present
|
- apt: pkg=nodejs state=present
|
||||||
state=present # absent | latest
|
state=present # absent | latest
|
||||||
update_cache=yes
|
update_cache=yes
|
||||||
force=no
|
force=no
|
||||||
|
|
||||||
|
- apt: deb=https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
|
||||||
|
|
||||||
- apt_repository: repo='deb https://... raring main'
|
- apt_repository: repo='deb https://... raring main'
|
||||||
state=present
|
state=present
|
||||||
|
|
||||||
|
@ -58,3 +60,7 @@ category: Ansible
|
||||||
- shell: apt-get install nginx -y
|
- shell: apt-get install nginx -y
|
||||||
- script: /x/y/script.sh
|
- script: /x/y/script.sh
|
||||||
|
|
||||||
|
### local_action
|
||||||
|
|
||||||
|
- name: do something locally
|
||||||
|
local_action: shell echo hello
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
title: "CSS: System font stack"
|
||||||
|
category: CSS
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
|
```
|
|
@ -25,3 +25,20 @@ RUN bundle install
|
||||||
```
|
```
|
||||||
WORKDIR /myapp
|
WORKDIR /myapp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Onbuild
|
||||||
|
|
||||||
|
```docker
|
||||||
|
ONBUILD RUN bundle install # when used with another file
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
```docker
|
||||||
|
EXPOSE 5900
|
||||||
|
CMD ["bundle", "exec", "rails", "server"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reference
|
||||||
|
|
||||||
|
- <https://docs.docker.com/engine/reference/builder/>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
title: Elixir metaprogramming
|
||||||
|
category: Elixir
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kernel
|
||||||
|
|
||||||
|
Most of these magic is defined in [Kernel.SpecialForms](http://devdocs.io/elixir/elixir/kernel.specialforms).
|
||||||
|
|
||||||
|
### Pseudo-variables
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
__DIR__ # current dir
|
||||||
|
__MODULE__ # current module
|
||||||
|
__CALLER__ # caller of the function
|
||||||
|
```
|
||||||
|
|
||||||
|
### [`__ENV__`](http://devdocs.io/elixir/elixir/kernel.specialforms#__ENV__/0)
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Map.keys(__ENV__)
|
||||||
|
[:__struct__, :aliases, :context, :context_modules, :export_vars, :file,
|
||||||
|
:function, :functions, :lexical_tracker, :line, :macro_aliases, :macros,
|
||||||
|
:module, :requires, :vars]
|
||||||
|
```
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
__CALLER__.module |> Module.definitions_in |> IO.inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
apply(Enum, :reverse, [[1, 2, 3]])
|
||||||
|
```
|
|
@ -191,7 +191,8 @@ Also see [Enum](#enum).
|
||||||
```js
|
```js
|
||||||
import List
|
import List
|
||||||
list = [ 1, 2, 3, 4 ]
|
list = [ 1, 2, 3, 4 ]
|
||||||
list = [ 1 | list ] # unshift (prepend)
|
list = list ++ [5] # push (append)
|
||||||
|
list = [ 0 | list ] # unshift (prepend)
|
||||||
|
|
||||||
first(list)
|
first(list)
|
||||||
last(list)
|
last(list)
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
title: ExUnit
|
||||||
|
category: Elixir
|
||||||
|
---
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule MyTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
use ExUnit.Case, async: true # for async
|
||||||
|
|
||||||
|
test "the truth" do
|
||||||
|
assert 1 + 1 == 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Capture IO
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
import ExUnit.CaptureIO
|
||||||
|
|
||||||
|
test "capture io" do
|
||||||
|
result = capture_io(fn ->
|
||||||
|
IO.puts "sup"
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert result == "sup\n"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Capture logs
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config :ex_unit, capture_logs: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Async
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defmodule AssertionTest do
|
||||||
|
# run concurrently with other test cases
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### [Assertions](http://devdocs.io/elixir/ex_unit/exunit.assertions)
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
assert x == y
|
||||||
|
refute x == y
|
||||||
|
|
||||||
|
assert_raise ArithmeticError, fn ->
|
||||||
|
1 + "test"
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raise ArithmeticError, "message", fn -> ...
|
||||||
|
assert_raise ArithmeticError, ~r/message/, fn -> ...
|
||||||
|
|
||||||
|
flunk "This should've been an error"
|
||||||
|
|
||||||
|
|
||||||
|
## Also see
|
||||||
|
|
||||||
|
- <http://devdocs.io/elixir/ex_unit/exunit#configure/1>
|
|
@ -3,7 +3,8 @@ title: "Phoenix: Plug.Conn"
|
||||||
category: Elixir
|
category: Elixir
|
||||||
---
|
---
|
||||||
|
|
||||||
## Request
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
conn.host #=> "example.com"
|
conn.host #=> "example.com"
|
||||||
|
@ -16,9 +17,19 @@ conn.scheme #=> :http
|
||||||
conn.peer #=> { {127, 0, 0, 1}, 12345 }
|
conn.peer #=> { {127, 0, 0, 1}, 12345 }
|
||||||
conn.remote_ip #=> { 151, 236, 219, 228 }
|
conn.remote_ip #=> { 151, 236, 219, 228 }
|
||||||
conn.req_headers #=> [{"content-type", "text/plain"}]
|
conn.req_headers #=> [{"content-type", "text/plain"}]
|
||||||
|
conn |> get_req_header("referrer")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Response
|
### Updating
|
||||||
|
Usually only useful for tests.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/json")
|
||||||
|
```
|
||||||
|
|
||||||
|
Response
|
||||||
|
--------
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
conn.resp_body #=> "..."
|
conn.resp_body #=> "..."
|
||||||
|
@ -28,6 +39,64 @@ conn.resp_headers #=> ...
|
||||||
conn.status #=> ...
|
conn.status #=> ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Sending responses
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# Plug.Conn
|
||||||
|
conn
|
||||||
|
|> html("<html><head>...")
|
||||||
|
|> json(%{ message: "Hello" })
|
||||||
|
|> text("Hello")
|
||||||
|
|
||||||
|
|> redirect(to: "/foo")
|
||||||
|
|> redirect(external: "http://www.google.com/")
|
||||||
|
|> halt()
|
||||||
|
|
||||||
|
|> put_resp_content_type("text/plain")
|
||||||
|
|> put_resp_cookie("abc", "def")
|
||||||
|
|> put_resp_header("X-Delivered-By", "myapp")
|
||||||
|
|> put_status(202)
|
||||||
|
|> put_status(:not_found)
|
||||||
|
|
||||||
|
|> put_private(:plug_foo, "...") # reserved for libraries
|
||||||
|
|
||||||
|
|> send_resp(201, "")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phoenix views
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# Phoenix.Controller
|
||||||
|
conn
|
||||||
|
|> render("index.html")
|
||||||
|
|> render("index.html", hello: "world")
|
||||||
|
|> render(MyApp.ErrorView, "404.html")
|
||||||
|
|
||||||
|
|> put_layout(:foo)
|
||||||
|
|> put_layout(false)
|
||||||
|
|> put_view(ErrorView)
|
||||||
|
|> put_secure_browser_headers()
|
||||||
|
# prevent clickjacking, nosniff, and xss protection
|
||||||
|
# x-frame-options, x-content-type-options, x-xss-protection
|
||||||
|
|
||||||
|
|> put_new_view(ErrorView) # if not set yet
|
||||||
|
|> put_new_layout(:foo)
|
||||||
|
```
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
layout(conn)
|
||||||
|
```
|
||||||
|
|
||||||
|
Accepts
|
||||||
|
-------
|
||||||
|
|
||||||
|
```js
|
||||||
|
plug :accepts, ["html", "json"]
|
||||||
|
conn |> accepts(["html", "json"])
|
||||||
|
get_format(conn) #=> "html"
|
||||||
|
conn.accepts
|
||||||
|
```
|
||||||
|
|
||||||
## Misc
|
## Misc
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
|
@ -41,8 +110,8 @@ conn.state # :unset, :set, :file, :sent, :chunked
|
||||||
## Assigns
|
## Assigns
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
conn = assign(conn, :user_id, 100)
|
|
||||||
conn.assigns[:hello]
|
conn.assigns[:hello]
|
||||||
|
conn |> assign(:user_id, 100)
|
||||||
```
|
```
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
|
@ -50,7 +119,7 @@ conn = async_assign(conn, :location, fn -> geoip_lookup() end)
|
||||||
await_assign(conn, :location)
|
await_assign(conn, :location)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Fetchables
|
## Session
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
conn = fetch_session(conn) # or plug :fetch_session
|
conn = fetch_session(conn) # or plug :fetch_session
|
||||||
|
@ -69,20 +138,4 @@ conn
|
||||||
```
|
```
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
|> halt
|
|
||||||
|
|
||||||
|> put_resp_content_type("text/plain")
|
|
||||||
|> put_layout(false)
|
|
||||||
|> put_status(202)
|
|
||||||
|> put_status(:not_found)
|
|
||||||
|
|
||||||
|> render "index.html"
|
|
||||||
|> render "index.html", hello: "world"
|
|
||||||
|> render MyApp.ErrorView, "404.html"
|
|
||||||
|
|
||||||
|> redirect to: "/foo"
|
|
||||||
|> redirect external: "http://www.google.com/"
|
|
||||||
|> text "Hello"
|
|
||||||
|
|
||||||
|> send_resp(201, "")
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,6 +3,14 @@ title: "Phoenix: Ecto models"
|
||||||
category: Elixir
|
category: Elixir
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Generating
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mix phoenix.gen.html Profile profiles email:string age:integer
|
||||||
|
|
||||||
|
$ mix phoenix.gen.html User users email:string hashed_password:string
|
||||||
|
```
|
||||||
|
|
||||||
## Schema
|
## Schema
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
|
@ -12,6 +20,10 @@ defmodule User do
|
||||||
schema "users" do
|
schema "users" do
|
||||||
field :name
|
field :name
|
||||||
field :age, :integer
|
field :age, :integer
|
||||||
|
# :id :binary :integer :float :boolean :string :binary
|
||||||
|
# {:array, inner_type} :decimal :map
|
||||||
|
|
||||||
|
field :password, virtual: true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
@ -60,7 +72,7 @@ changeset.optional #=> [:body]
|
||||||
### Updating
|
### Updating
|
||||||
|
|
||||||
```elixir
|
```elixir
|
||||||
changeset
|
changeset #(or model)
|
||||||
|> change(title: "New title")
|
|> change(title: "New title")
|
||||||
|> change(%{ title: "New title" })
|
|> change(%{ title: "New title" })
|
||||||
|> put_change(:title, "New title")
|
|> put_change(:title, "New title")
|
||||||
|
@ -82,3 +94,79 @@ get_field(changeset, :title) #=> "hi" (even if unchanged)
|
||||||
fetch_change(changeset, :title) #=> {:ok, "hi"} | :error
|
fetch_change(changeset, :title) #=> {:ok, "hi"} | :error
|
||||||
fetch_field(changeset, :title) #=> {:changes | :model, "value"} | :error
|
fetch_field(changeset, :title) #=> {:changes | :model, "value"} | :error
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Ecto
|
||||||
|
|
||||||
|
### Get one
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Repo.get(User, id)
|
||||||
|
Repo.get_by(User, email: "john@hello.com") #=> %User{} | nil
|
||||||
|
|
||||||
|
# also get! get_by!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create/update
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
changeset |> Repo.update
|
||||||
|
changeset |> Repo.insert
|
||||||
|
changeset |> Repo.insert_or_update
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
User
|
||||||
|
|> Ecto.Changeset.change(%{name: "hi"})
|
||||||
|
|> Repo.insert
|
||||||
|
```
|
||||||
|
|
||||||
|
## Many
|
||||||
|
|
||||||
|
### Queries
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
from p in Post,
|
||||||
|
where: p.title == "Hello",
|
||||||
|
where: [state: "Sweden"],
|
||||||
|
|
||||||
|
limit: 1,
|
||||||
|
offset: 10,
|
||||||
|
|
||||||
|
order_by: c.name,
|
||||||
|
order_by: [c.name, c.title],
|
||||||
|
order_by: [asc: c.name, desc: c.title],
|
||||||
|
|
||||||
|
preload: [:comments],
|
||||||
|
preload: [comments: {c, likes: l}],
|
||||||
|
|
||||||
|
join: c in assoc(c, :comments),
|
||||||
|
join: p in Post, on: c.post_id == p.id,
|
||||||
|
group_by: p,
|
||||||
|
|
||||||
|
select: p,
|
||||||
|
select: {p.title, p.description},
|
||||||
|
select: [p.title, p.description],
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get many
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Repo.all(User)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update many
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Repo.update_all(Post, set: [title: "Title"])
|
||||||
|
Repo.update_all(Post, inc: [views: 1])
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chaining `_all` with queries
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
from(p in Post, where: p.id < 10)
|
||||||
|
|> Repo.update_all(...)
|
||||||
|
|
||||||
|
from(p in Post, where: p.id < 10)
|
||||||
|
|> Repo.all()
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue