diff --git a/elixir.md b/elixir.md index d2b9ef614..41dda0a60 100644 --- a/elixir.md +++ b/elixir.md @@ -69,7 +69,21 @@ tuple_size(tuple) ### Maps ```elixir -put_in(data, keys, value) +import Map + +map = %{a: "Apple"} # atom keys (:a) +map = %{"a" => "Apple"} # string keys ("a") + +put(map, :b, "Banana") +update(map, :a, &(&1 + 1)) +update(map, :a, fun a -> a + 1 end) +get_and_update(map, :a, &(&1 || "default")) + +# Deep functions (_in) +put_in(map, [:b, :c], "Banana") +put_in(map[:b][:c], "Banana") # via macros +get_and_update_in(users, ["john", :age], &{&1, &1 + 1}) + Map.get(map, key) Map.put(map, key, value) ``` @@ -163,6 +177,7 @@ Also see [Enum](#enum). ```js import List list = [ 1, 2, 3, 4 ] +list = [ 1 | list ] # unshift (prepend) first(list) last(list) @@ -207,7 +222,7 @@ end %User{name: "John", age: 20} ``` -### Functions +## Functions ### Function heads @@ -216,3 +231,25 @@ def join(a, b \\ nil) def join(a, b) when is_nil(b) do: a end def join(a, b) do: a <> b; end ``` + +## Modules + +### Metaprogramming + +```elixir +__MODULE__ +__MODULE__.__info__ + +@after_compile __MODULE__ +def __before_compile__(env) +def __after_compile__(env, _bytecode) +def __using__(opts) # invoked on `use` + +@on_definition {__MODULE__, :on_def} +def on_def(_env, kind, name, args, guards, body) + +@on_load :load_check +def load_check +``` + +[Reference](http://elixir-lang.org/docs/stable/elixir/Module.html) diff --git a/phoenix-conn.md b/phoenix-conn.md index 2f16d9c0a..ec6d154d9 100644 --- a/phoenix-conn.md +++ b/phoenix-conn.md @@ -38,9 +38,51 @@ conn.secret_key_base # ... conn.state # :unset, :set, :file, :sent, :chunked ``` -## Session +## Assigns +```elixir +conn = assign(conn, :user_id, 100) +conn.assigns[:hello] ``` + +```elixir +conn = async_assign(conn, :location, fn -> geoip_lookup() end) +await_assign(conn, :location) +``` + +## Fetchables + +```elixir +conn = fetch_session(conn) # or plug :fetch_session + conn = put_session(conn, :message, "new stuff we just set in the session") get_session(conn, :message) +conn = clear_session(conn) +``` + +Also: `flash` `cookie` `params` + +```elixir +conn +|> put_flash(:info, "Success") +|> put_flash(:error, "Oh no") +``` + +```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, "") ``` diff --git a/phoenix-ecto.md b/phoenix-ecto.md new file mode 100644 index 000000000..11a21a981 --- /dev/null +++ b/phoenix-ecto.md @@ -0,0 +1,84 @@ +--- +title: "Phoenix: Ecto models" +category: Elixir +--- + +## Schema + +```elixir +defmodule User do + use Ecto.Schema + + schema "users" do + field :name + field :age, :integer + end +end +``` + +## Changesets + +```elixir +def changeset(user, params \\ :empty) do + user + |> cast(params, ~w(name email), ~w(age)) # params to Changeset + + |> validate_format(:email, ~r/@/) + + |> validate_inclusion(:age, 18..100) + |> validate_exclusion(:role, ~w(admin superadmin)) + |> validate_subset(:pets, ~w(cat dog parrot whale)) + + |> validate_length(:body, min: 1) + |> validate_length(:body, min: 1, max: 160) + |> validate_length(:partners, is: 2) + + |> validate_number(:pi, greater_than: 3) + |> validate_number(:pi, less_than: 4) + |> validate_number(:pi, equal_to: 42) + + |> validate_change(:title, fn _, _ -> []) + |> validate_confirmation(:password, message: "does not match") + + |> unique_constraint(:email) + |> foreign_key_constraint(:post_id) + |> assoc_constraint(:post) # ensure post_id exists + |> exclude_constraint(:name) +end +``` + +```elixir +changeset.valid? +changeset.errors #=> [title: "empty"] + +changeset.changes #=> %{} +changeset.params +changeset.required #=> [:title] +changeset.optional #=> [:body] +``` + +### Updating + +```elixir +changeset +|> change(title: "New title") +|> change(%{ title: "New title" }) +|> put_change(:title, "New title") +|> force_change(:title, "New title") +|> update_change(:title, &(&1 <> "...")) + +|> delete_change(:title) +|> merge(other_changeset) + +|> add_error(:title, "empty") +``` + +### Getting + +```elixir +get_change(changeset, :title) #=> "hi" (if changed) +get_field(changeset, :title) #=> "hi" (even if unchanged) + +fetch_change(changeset, :title) #=> {:ok, "hi"} | :error +fetch_field(changeset, :title) #=> {:changes | :model, "value"} | :error +``` diff --git a/phoenix-routing.md b/phoenix-routing.md index 5c0a8581c..ef9e39994 100644 --- a/phoenix-routing.md +++ b/phoenix-routing.md @@ -13,12 +13,19 @@ mix phoenix.routes get "/", PageController, :index ``` +Also: `put` `post` `patch` `options` `delete` `head` + ## Resources ```elixir resources "/users", UserController resources "/users", UserController, only: [:index, :show] resources "/users", UserController, except: [:delete] + + as: :person # helper name (person_path) + name: :person # ...? + param: :id # name of parameter for this resource + ``` | Method | Path | Helper |