diff --git a/ActivityPub.Federator.HTTP.Tesla.html b/ActivityPub.Federator.HTTP.Tesla.html index 74928670257..e4b452a1276 100644 --- a/ActivityPub.Federator.HTTP.Tesla.html +++ b/ActivityPub.Federator.HTTP.Tesla.html @@ -429,11 +429,11 @@
Perform a DELETE request.
See request/1
or request/2
for options definition.
delete("/users")
-delete("/users", query: [scope: "admin"])
-delete(client, "/users")
-delete(client, "/users", query: [scope: "admin"])
-delete(client, "/users", body: %{name: "Jon"})
+Perform a DELETE request.
See request/1
or request/2
for options definition.
delete("/users")
+delete("/users", query: [scope: "admin"])
+delete(client, "/users")
+delete(client, "/users", query: [scope: "admin"])
+delete(client, "/users", body: %{name: "Jon"})
Perform a DELETE request.
See request!/1
or request!/2
for options definition.
delete!("/users")
-delete!("/users", query: [scope: "admin"])
-delete!(client, "/users")
-delete!(client, "/users", query: [scope: "admin"])
-delete!(client, "/users", body: %{name: "Jon"})
+Perform a DELETE request.
See request!/1
or request!/2
for options definition.
delete!("/users")
+delete!("/users", query: [scope: "admin"])
+delete!(client, "/users")
+delete!(client, "/users", query: [scope: "admin"])
+delete!(client, "/users", body: %{name: "Jon"})
Perform a GET request.
See request/1
or request/2
for options definition.
get("/users")
-get("/users", query: [scope: "admin"])
-get(client, "/users")
-get(client, "/users", query: [scope: "admin"])
-get(client, "/users", body: %{name: "Jon"})
+Perform a GET request.
See request/1
or request/2
for options definition.
get("/users")
+get("/users", query: [scope: "admin"])
+get(client, "/users")
+get(client, "/users", query: [scope: "admin"])
+get(client, "/users", body: %{name: "Jon"})
Perform a GET request.
See request!/1
or request!/2
for options definition.
get!("/users")
-get!("/users", query: [scope: "admin"])
-get!(client, "/users")
-get!(client, "/users", query: [scope: "admin"])
-get!(client, "/users", body: %{name: "Jon"})
+Perform a GET request.
See request!/1
or request!/2
for options definition.
get!("/users")
+get!("/users", query: [scope: "admin"])
+get!(client, "/users")
+get!(client, "/users", query: [scope: "admin"])
+get!(client, "/users", body: %{name: "Jon"})
Perform a HEAD request.
See request/1
or request/2
for options definition.
head("/users")
-head("/users", query: [scope: "admin"])
-head(client, "/users")
-head(client, "/users", query: [scope: "admin"])
-head(client, "/users", body: %{name: "Jon"})
+Perform a HEAD request.
See request/1
or request/2
for options definition.
head("/users")
+head("/users", query: [scope: "admin"])
+head(client, "/users")
+head(client, "/users", query: [scope: "admin"])
+head(client, "/users", body: %{name: "Jon"})
Perform a HEAD request.
See request!/1
or request!/2
for options definition.
head!("/users")
-head!("/users", query: [scope: "admin"])
-head!(client, "/users")
-head!(client, "/users", query: [scope: "admin"])
-head!(client, "/users", body: %{name: "Jon"})
+Perform a HEAD request.
See request!/1
or request!/2
for options definition.
head!("/users")
+head!("/users", query: [scope: "admin"])
+head!(client, "/users")
+head!(client, "/users", query: [scope: "admin"])
+head!(client, "/users", body: %{name: "Jon"})
Perform a OPTIONS request.
See request/1
or request/2
for options definition.
options("/users")
-options("/users", query: [scope: "admin"])
-options(client, "/users")
-options(client, "/users", query: [scope: "admin"])
-options(client, "/users", body: %{name: "Jon"})
+Perform a OPTIONS request.
See request/1
or request/2
for options definition.
options("/users")
+options("/users", query: [scope: "admin"])
+options(client, "/users")
+options(client, "/users", query: [scope: "admin"])
+options(client, "/users", body: %{name: "Jon"})
Perform a OPTIONS request.
See request!/1
or request!/2
for options definition.
options!("/users")
-options!("/users", query: [scope: "admin"])
-options!(client, "/users")
-options!(client, "/users", query: [scope: "admin"])
-options!(client, "/users", body: %{name: "Jon"})
+Perform a OPTIONS request.
See request!/1
or request!/2
for options definition.
options!("/users")
+options!("/users", query: [scope: "admin"])
+options!(client, "/users")
+options!(client, "/users", query: [scope: "admin"])
+options!(client, "/users", body: %{name: "Jon"})
Perform a PATCH request.
See request/1
or request/2
for options definition.
patch("/users", %{name: "Jon"})
-patch("/users", %{name: "Jon"}, query: [scope: "admin"])
-patch(client, "/users", %{name: "Jon"})
-patch(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a PATCH request.
See request/1
or request/2
for options definition.
patch("/users", %{name: "Jon"})
+patch("/users", %{name: "Jon"}, query: [scope: "admin"])
+patch(client, "/users", %{name: "Jon"})
+patch(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
Perform a PATCH request.
See request!/1
or request!/2
for options definition.
patch!("/users", %{name: "Jon"})
-patch!("/users", %{name: "Jon"}, query: [scope: "admin"])
-patch!(client, "/users", %{name: "Jon"})
-patch!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a PATCH request.
See request!/1
or request!/2
for options definition.
patch!("/users", %{name: "Jon"})
+patch!("/users", %{name: "Jon"}, query: [scope: "admin"])
+patch!(client, "/users", %{name: "Jon"})
+patch!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
Perform a POST request.
See request/1
or request/2
for options definition.
post("/users", %{name: "Jon"})
-post("/users", %{name: "Jon"}, query: [scope: "admin"])
-post(client, "/users", %{name: "Jon"})
-post(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a POST request.
See request/1
or request/2
for options definition.
post("/users", %{name: "Jon"})
+post("/users", %{name: "Jon"}, query: [scope: "admin"])
+post(client, "/users", %{name: "Jon"})
+post(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
Perform a POST request.
See request!/1
or request!/2
for options definition.
post!("/users", %{name: "Jon"})
-post!("/users", %{name: "Jon"}, query: [scope: "admin"])
-post!(client, "/users", %{name: "Jon"})
-post!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a POST request.
See request!/1
or request!/2
for options definition.
post!("/users", %{name: "Jon"})
+post!("/users", %{name: "Jon"}, query: [scope: "admin"])
+post!(client, "/users", %{name: "Jon"})
+post!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
Perform a PUT request.
See request/1
or request/2
for options definition.
put("/users", %{name: "Jon"})
-put("/users", %{name: "Jon"}, query: [scope: "admin"])
-put(client, "/users", %{name: "Jon"})
-put(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a PUT request.
See request/1
or request/2
for options definition.
put("/users", %{name: "Jon"})
+put("/users", %{name: "Jon"}, query: [scope: "admin"])
+put(client, "/users", %{name: "Jon"})
+put(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
Perform a PUT request.
See request!/1
or request!/2
for options definition.
put!("/users", %{name: "Jon"})
-put!("/users", %{name: "Jon"}, query: [scope: "admin"])
-put!(client, "/users", %{name: "Jon"})
-put!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
+Perform a PUT request.
See request!/1
or request!/2
for options definition.
put!("/users", %{name: "Jon"})
+put!("/users", %{name: "Jon"}, query: [scope: "admin"])
+put!(client, "/users", %{name: "Jon"})
+put!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
ExampleApi.request(method: :get, url: "/users/path")
+ExampleApi.request(method: :get, url: "/users/path")
# use shortcut methods
-ExampleApi.get("/users/1")
-ExampleApi.post(client, "/users", %{name: "Jon"})
+ExampleApi.get("/users/1")
+ExampleApi.post(client, "/users", %{name: "Jon"})
Perform a TRACE request.
See request/1
or request/2
for options definition.
trace("/users")
-trace("/users", query: [scope: "admin"])
-trace(client, "/users")
-trace(client, "/users", query: [scope: "admin"])
-trace(client, "/users", body: %{name: "Jon"})
+Perform a TRACE request.
See request/1
or request/2
for options definition.
trace("/users")
+trace("/users", query: [scope: "admin"])
+trace(client, "/users")
+trace(client, "/users", query: [scope: "admin"])
+trace(client, "/users", body: %{name: "Jon"})
Perform a TRACE request.
See request!/1
or request!/2
for options definition.
trace!("/users")
-trace!("/users", query: [scope: "admin"])
-trace!(client, "/users")
-trace!(client, "/users", query: [scope: "admin"])
-trace!(client, "/users", body: %{name: "Jon"})
+Perform a TRACE request.
See request!/1
or request!/2
for options definition.
trace!("/users")
+trace!("/users", query: [scope: "admin"])
+trace!(client, "/users")
+trace!(client, "/users", query: [scope: "admin"])
+trace!(client, "/users", body: %{name: "Jon"})
ACLs represent fully populated access control rules that can be reused. -Can be reused to secure multiple objects, thus exists independently of any object.
The table doesn't have any fields of its own:
has_many(:grants, Grant)
-has_many(:controlled, Controlled)
+Can be reused to secure multiple objects, thus exists independently of any object.The table doesn't have any fields of its own:
has_many(:grants, Grant)
+has_many(:controlled, Controlled)
iex> Exception.format_mfa(Foo, :bar, 1)
-{Foo, :bar, "Foo.bar/1"}
-iex> Exception.format_mfa(Foo, :bar, [])
-{Foo, :bar, "Foo.bar()"}
-iex> Exception.format_mfa(nil, :bar, [])
-{nil, :bar, "nil.bar()"}
Anonymous functions are reported as -func/arity-anonfn-count-, +
iex> Exception.format_mfa(Foo, :bar, 1)
+{Foo, :bar, "Foo.bar/1"}
+iex> Exception.format_mfa(Foo, :bar, [])
+{Foo, :bar, "Foo.bar()"}
+iex> Exception.format_mfa(nil, :bar, [])
+{nil, :bar, "nil.bar()"}
Anonymous functions are reported as -func/arity-anonfn-count-, where func is the name of the enclosing function. Convert to "anonymous fn in func/arity"
diff --git a/Bonfire.Common.Localise.Cldr.AcceptLanguage.html b/Bonfire.Common.Localise.Cldr.AcceptLanguage.html index a376a0f5bbf..e027f670988 100644 --- a/Bonfire.Common.Localise.Cldr.AcceptLanguage.html +++ b/Bonfire.Common.Localise.Cldr.AcceptLanguage.html @@ -142,7 +142,7 @@Cldr.LanguageTag
.The format of an Accept-Language
header is as follows in ABNF
format:
Accept-Language = "Accept-Language" ":"
1#( language-range [ ";" "q" "=" qvalue ] )
- language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
Each language-range MAY be given an associated quality value which represents an + language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
Each language-range MAY be given an associated quality value which represents an estimate of the user's preference for the languages specified by that range. The quality value defaults to "q=1". For example,
Accept-Language: da, en-gb;q=0.8, en;q=0.7
would mean: "I prefer Danish, but will accept British English and other types of English."
@@ -255,54 +255,54 @@iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
+ transform: %{},
+ language_variants: []
+ }}
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("da;q=0.1,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("xx,yy;q=0.3")
-{:error,
- {Cldr.NoMatchingLocale,
- "No configured locale could be matched to \"xx,yy;q=0.3\""}}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("invalid_tag")
-{:error, {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+ transform: %{},
+ language_variants: []
+ }}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("xx,yy;q=0.3")
+{:error,
+ {Cldr.NoMatchingLocale,
+ "No configured locale could be matched to \"xx,yy;q=0.3\""}}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.best_match("invalid_tag")
+{:error, {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
iex> Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3", TestBackend.Cldr)
-{:ok,
- [
- {1.0,
- %Cldr.LanguageTag{
+iex> Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3", TestBackend.Cldr)
+{:ok,
+ [
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
- ]}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("invalid_tag")
-{:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
-
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3,invalid_tag")
-{:ok,
- [
- {1.0,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }}
+ ]}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("invalid_tag")
+{:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse("da,zh-TW;q=0.3,invalid_tag")
+{:ok,
+ [
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }},
- {:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
- ]}
+ transform: %{},
+ language_variants: []
+ }},
+ {:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+ ]}
iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3")
-[
- {1.0,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3")
+[
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }}
-]
+ transform: %{},
+ language_variants: []
+ }}
+]
Bonfire.Common.Localise.Cldr.AcceptLanguage.parse! "invalid_tag"
** (Cldr.AcceptLanguageError) "Expected a BCP47 language tag. Could not parse the remaining "g" starting at position 11
(ex_cldr) lib/cldr/accept_language.ex:304: Cldr.AcceptLanguage.parse!/1
-iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag")
-[
- {1.0,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.AcceptLanguage.parse!("da,zh-TW;q=0.3,invalid_tag")
+[
+ {1.0,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "da",
cldr_locale_name: :da,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "da",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :da,
requested_locale_name: "da",
script: :Latn,
territory: :DK,
- transform: %{},
- language_variants: []
- }},
- {0.3,
- %Cldr.LanguageTag{
+ transform: %{},
+ language_variants: []
+ }},
+ {0.3,
+ %Cldr.LanguageTag{
backend: TestBackend.Cldr,
canonical_locale_name: "zh-TW",
cldr_locale_name: :"zh-Hant",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: nil,
language: "zh",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :"zh-Hant",
requested_locale_name: "zh-TW",
script: :Hant,
territory: :TW,
- transform: %{},
- language_variants: []
- }},
- {:error,
- {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
-]
+ transform: %{},
+ language_variants: []
+ }},
+ {:error,
+ {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"g\" starting at position 11"}}
+]
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en-GB"
-{:ok, Cldr.Calendar.GB}
+{:ok, Cldr.Calendar.GB}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en-GB-u-ca-gregory"
-{:ok, Cldr.Calendar.Gregorian}
+{:ok, Cldr.Calendar.Gregorian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "en"
-{:ok, Cldr.Calendar.US}
+{:ok, Cldr.Calendar.US}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_locale "fa-IR"
-{:ok, Cldr.Calendar.Persian}
+{:ok, Cldr.Calendar.Persian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_territory :US
-{:ok, Cldr.Calendar.Gregorian}
+{:ok, Cldr.Calendar.Gregorian}
iex> Bonfire.Common.Localise.Cldr.Calendar.calendar_from_territory :XX
-{:error, {Cldr.UnknownTerritoryError, "The territory :XX is unknown"}}
iex: MyApp.Cldr.Calendar.strftime_options!
-[
- am_pm_names: #Function<0.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- month_names: #Function<1.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- abbreviated_month_names: #Function<2.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- day_of_week_names: #Function<3.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>,
- abbreviated_day_of_week_names: #Function<4.32021692/1 in MyApp.Cldr.Calendar.strftime_options/2>
-]
iex: NimbleStrftime.format(Date.today(), MyApp.Cldr.Calendar.strftime_options!())
+iex: NimbleStrftime.format(Date.today(), MyApp.Cldr.Calendar.strftime_options!())
MyApp.Cldr.Currency.currencies_for_locale("en") => {:ok, - %{
FJD: %Cldr.Currency{
+ %{ FJD: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "FJD",
- count: %{one: "Fijian dollar", other: "Fijian dollars"},
+ count: %{one: "Fijian dollar", other: "Fijian dollars"},
digits: 2,
from: nil,
iso_digits: 2,
@@ -427,12 +427,12 @@ currencies_for_locale(locale, only \\ :all,
symbol: "FJD",
tender: true,
to: nil
- },
- SUR: %Cldr.Currency{
+ },
+ SUR: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "SUR",
- count: %{one: "Soviet rouble", other: "Soviet roubles"},
+ count: %{one: "Soviet rouble", other: "Soviet roubles"},
digits: 2,
from: nil,
iso_digits: nil,
@@ -442,7 +442,7 @@ currencies_for_locale(locale, only \\ :all,
symbol: "SUR",
tender: true,
to: nil
- },
+ },
...
}}
@@ -493,11 +493,11 @@ currencies_for_locale!(locale, only \\ :all
Example
MyApp.Cldr.Currency.currencies_for_locale!("en")
- => %{
FJD: %Cldr.Currency{
+ => %{FJD: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "FJD",
- count: %{one: "Fijian dollar", other: "Fijian dollars"},
+ count: %{one: "Fijian dollar", other: "Fijian dollars"},
digits: 2,
from: nil,
iso_digits: 2,
@@ -507,12 +507,12 @@ currencies_for_locale!(locale, only \\ :all
symbol: "FJD",
tender: true,
to: nil
-},
-SUR: %Cldr.Currency{
+},
+SUR: %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "SUR",
- count: %{one: "Soviet rouble", other: "Soviet roubles"},
+ count: %{one: "Soviet rouble", other: "Soviet roubles"},
digits: 2,
from: nil,
iso_digits: nil,
@@ -522,7 +522,7 @@ currencies_for_locale!(locale, only \\ :all
symbol: "SUR",
tender: true,
to: nil
-},
+},
...
}
@@ -580,13 +580,13 @@ currency_for_code(currency_or_currency_code
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("AUD")
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("AUD")
+{:ok,
+ %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "AUD",
- count: %{one: "Australian dollar", other: "Australian dollars"},
+ count: %{one: "Australian dollar", other: "Australian dollars"},
digits: 2,
iso_digits: 2,
name: "Australian Dollar",
@@ -594,15 +594,15 @@ currency_for_code(currency_or_currency_code
rounding: 0,
symbol: "A$",
tender: true
-}}
+}}
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("THB")
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code("THB")
+{:ok,
+ %Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "THB",
- count: %{one: "Thai baht", other: "Thai baht"},
+ count: %{one: "Thai baht", other: "Thai baht"},
digits: 2,
iso_digits: 2,
name: "Thai Baht",
@@ -610,7 +610,7 @@ currency_for_code(currency_or_currency_code
rounding: 0,
symbol: "THB",
tender: true
-}}
+}}
@@ -669,12 +669,12 @@ currency_for_code!(currency_or_currency_cod
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("AUD")
-%Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("AUD")
+%Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "AUD",
- count: %{one: "Australian dollar", other: "Australian dollars"},
+ count: %{one: "Australian dollar", other: "Australian dollars"},
digits: 2,
iso_digits: 2,
name: "Australian Dollar",
@@ -682,14 +682,14 @@ currency_for_code!(currency_or_currency_cod
rounding: 0,
symbol: "A$",
tender: true
-}
+}
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("THB")
-%Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_for_code!("THB")
+%Cldr.Currency{
cash_digits: 2,
cash_rounding: 0,
code: "THB",
- count: %{one: "Thai baht", other: "Thai baht"},
+ count: %{one: "Thai baht", other: "Thai baht"},
digits: 2,
iso_digits: 2,
name: "Thai Baht",
@@ -697,7 +697,7 @@ currency_for_code!(currency_or_currency_cod
rounding: 0,
symbol: "THB",
tender: true
-}
+}
@@ -738,15 +738,15 @@ currency_from_locale(locale)
Examples
-iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale("en")
+iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale("en")
iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale locale
:USD
-iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale("en-AU")
+iex> {:ok, locale} = Bonfire.Common.Localise.Cldr.validate_locale("en-AU")
iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale locale
:AUD
-iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale("en-GB")
+iex> Bonfire.Common.Localise.Cldr.Currency.currency_from_locale("en-GB")
:GBP
@@ -790,14 +790,14 @@ currency_history_for_locale(language_tag)
Example
-iex> MyApp.Cldr.Currency.currency_history_for_locale("en")
-{:ok,
- %{
- USD: %{from: ~D[1792-01-01], to: nil},
- USN: %{tender: false},
- USS: %{from: nil, tender: false, to: ~D[2014-03-01]}
- }
-}
+iex> MyApp.Cldr.Currency.currency_history_for_locale("en")
+{:ok,
+ %{
+ USD: %{from: ~D[1792-01-01], to: nil},
+ USN: %{tender: false},
+ USS: %{from: nil, tender: false, to: ~D[2014-03-01]}
+ }
+}
@@ -856,9 +856,9 @@ currency_strings(locale, only \\ :all, exce
Example
-MyApp.Cldr.Currency.currency_strings("en")
-=> {:ok,
- %{
+MyApp.Cldr.Currency.currency_strings("en")
+=> {:ok,
+ %{
"mexican silver pesos" => :MXP,
"sudanese dinar" => :SDD,
"bad" => :BAD,
@@ -868,7 +868,7 @@ currency_strings(locale, only \\ :all, exce
"guyanaese dollars" => :GYD,
"equatorial guinean ekwele" => :GQE,
...
- }}
+ }}
@@ -927,8 +927,8 @@ currency_strings!(locale_name, only \\ :all
Example
-MyApp.Cldr.Currency.currency_strings!("en")
-=> %{
+MyApp.Cldr.Currency.currency_strings!("en")
+=> %{
"mexican silver pesos" => :MXP,
"sudanese dinar" => :SDD,
"bad" => :BAD,
@@ -938,7 +938,7 @@ currency_strings!(locale_name, only \\ :all
"guyanaese dollars" => :GYD,
"equatorial guinean ekwele" => :GQE,
...
- }
+ }
@@ -976,10 +976,10 @@ current_currency_from_locale(locale)
Example
-iex> MyApp.Cldr.Currency.current_currency_from_locale("en")
+iex> MyApp.Cldr.Currency.current_currency_from_locale("en")
:USD
-iex> MyApp.Cldr.Currency.current_currency_from_locale("en-AU")
+iex> MyApp.Cldr.Currency.current_currency_from_locale("en-AU")
:AUD
@@ -1027,7 +1027,7 @@ current_territory_currencies()
Example
-iex> Bonfire.Common.Localise.Cldr.Currency.current_territory_currencies()
+iex> Bonfire.Common.Localise.Cldr.Currency.current_territory_currencies()
@@ -1119,11 +1119,11 @@ known_currency_code(currency_code)
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code("AUD")
-{:ok, :AUD}
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code("AUD")
+{:ok, :AUD}
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code("GGG")
-{:error, {Cldr.UnknownCurrencyError, "The currency \"GGG\" is invalid"}}
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code("GGG")
+{:error, {Cldr.UnknownCurrencyError, "The currency \"GGG\" is invalid"}}
@@ -1170,13 +1170,13 @@ known_currency_code?(currency_code)
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?("AUD")
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?("AUD")
true
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?("GGG")
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?("GGG")
false
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?(:XCV)
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_code?(:XCV)
false
@@ -1211,7 +1211,7 @@ known_currency_codes()
Example
-iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_codes()
+iex> Bonfire.Common.Localise.Cldr.Currency.known_currency_codes()
@@ -1270,14 +1270,14 @@ new(currency, options \\ [])
Example
-iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "Custom Name", digits: 0)
-{:ok,
- %Cldr.Currency{
+iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "Custom Name", digits: 0)
+{:ok,
+ %Cldr.Currency{
alt_code: :XAE,
cash_digits: 0,
cash_rounding: nil,
code: :XAE,
- count: %{other: "Custom Name"},
+ count: %{other: "Custom Name"},
digits: 0,
from: nil,
iso_digits: 0,
@@ -1287,11 +1287,11 @@ new(currency, options \\ [])
symbol: "XAE",
tender: false,
to: nil
- }}
-iex> MyApp.Cldr.Currency.new(:XAH, name: "Custom Name")
-{:error, "Required options are missing. Required options are [:name, :digits]"}
-iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "XAE", digits: 0)
-{:error, {Cldr.CurrencyAlreadyDefined, "Currency :XAE is already defined."}}
+ }}
+iex> MyApp.Cldr.Currency.new(:XAH, name: "Custom Name")
+{:error, "Required options are missing. Required options are [:name, :digits]"}
+iex> Bonfire.Common.Localise.Cldr.Currency.new(:XAE, name: "XAE", digits: 0)
+{:error, {Cldr.CurrencyAlreadyDefined, "Currency :XAE is already defined."}}
@@ -1349,20 +1349,20 @@ pluralize(number, currency, options \\ [])<
Examples
-iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(1, :USD)
-{:ok, "US dollar"}
+iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(1, :USD)
+{:ok, "US dollar"}
-iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(3, :USD)
-{:ok, "US dollars"}
+iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(3, :USD)
+{:ok, "US dollars"}
-iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(12, :USD, locale: "zh")
-{:ok, "美元"}
+iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(12, :USD, locale: "zh")
+{:ok, "美元"}
-iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(12, :USD, locale: "fr")
-{:ok, "dollars des États-Unis"}
+iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(12, :USD, locale: "fr")
+{:ok, "dollars des États-Unis"}
-iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(1, :USD, locale: "fr")
-{:ok, "dollar des États-Unis"}
+iex> Bonfire.Common.Localise.Cldr.Currency.pluralize(1, :USD, locale: "fr")
+{:ok, "dollar des États-Unis"}
@@ -1404,8 +1404,8 @@ strings_for_currency(currency, locale)
Example
-iex> MyApp.Cldr.Currency.strings_for_currency(:AUD, "en")
-["a$", "australian dollars", "aud", "australian dollar"]
+iex> MyApp.Cldr.Currency.strings_for_currency(:AUD, "en")
+["a$", "australian dollars", "aud", "australian dollar"]
diff --git a/Bonfire.Common.Localise.Cldr.Date.Interval.html b/Bonfire.Common.Localise.Cldr.Date.Interval.html
index b841c5a39cf..93aa6ac109d 100644
--- a/Bonfire.Common.Localise.Cldr.Date.Interval.html
+++ b/Bonfire.Common.Localise.Cldr.Date.Interval.html
@@ -296,30 +296,30 @@ to_string(from, to, options)
Examples
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-12-31]
-{:ok, "Jan 1 – Dec 31, 2020"}
+{:ok, "Jan 1 – Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12]
-{:ok, "Jan 1 – 12, 2020"}
+{:ok, "Jan 1 – 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-12-01],
...> format: :long, style: :year_and_month
-{:ok, "January – December 2020"}
+{:ok, "January – December 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :short
-{:ok, "1/1/2020 – 1/12/2020"}
+{:ok, "1/1/2020 – 1/12/2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long, locale: "fr"
-{:ok, "mer. 1 – dim. 12 janv. 2020"}
+{:ok, "mer. 1 – dim. 12 janv. 2020"}
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long, locale: "th", number_system: :thai
-{:ok, "พ. ๑ ม.ค. – อา. ๑๒ ม.ค. ๒๐๒๐"}
+
{:ok, "พ. ๑ ม.ค. – อา. ๑๒ ม.ค. ๒๐๒๐"}
@@ -396,17 +396,17 @@ to_string!(from, to, options)
Examples
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-31])
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-31])
"Jan 1 – Dec 31, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12])
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12])
"Jan 1 – 12, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :long
"Wed, Jan 1 – Sun, Jan 12, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-01]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-12-01]),
...> format: :long, style: :year_and_month
"January – December 2020"
@@ -414,11 +414,11 @@ to_string!(from, to, options)
iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! ~I"2020-01/12"
"Jan 1 – Dec 31, 2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :short
"1/1/2020 – 1/12/2020"
-iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
+iex> Bonfire.Common.Localise.Cldr.Date.Interval.to_string! Date.range(~D[2020-01-01], ~D[2020-01-12]),
...> format: :long, locale: "fr"
"mer. 1 – dim. 12 janv. 2020"
diff --git a/Bonfire.Common.Localise.Cldr.Date.html b/Bonfire.Common.Localise.Cldr.Date.html
index e2a8ab87f35..1cd970dd695 100644
--- a/Bonfire.Common.Localise.Cldr.Date.html
+++ b/Bonfire.Common.Localise.Cldr.Date.html
@@ -242,22 +242,22 @@ to_string(date, options \\ [])
Examples
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :medium, locale: "en"
-{:ok, "Jul 10, 2017"}
+{:ok, "Jul 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], locale: "en"
-{:ok, "Jul 10, 2017"}
+{:ok, "Jul 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :full, locale: "en"
-{:ok, "Monday, July 10, 2017"}
+{:ok, "Monday, July 10, 2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :short, locale: "en"
-{:ok, "7/10/17"}
+{:ok, "7/10/17"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :short, locale: "fr"
-{:ok, "10/07/2017"}
+{:ok, "10/07/2017"}
iex> Bonfire.Common.Localise.Cldr.Date.to_string ~D[2017-07-10], format: :long, locale: "af"
-{:ok, "10 Julie 2017"}
+{:ok, "10 Julie 2017"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.calendars_for(:en)
-{:ok, [:buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem,
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.calendars_for(:en)
+{:ok, [:buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem,
:generic, :gregorian, :hebrew, :indian, :islamic, :islamic_civil,
- :islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]}
+ :islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats(:en)
-{:ok, %Cldr.Date.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats(:en)
+{:ok, %Cldr.Date.Formats{
full: "EEEE, MMMM d, y",
long: "MMMM d, y",
medium: "MMM d, y",
short: "M/d/yy"
-}}
+}}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats(:en, :buddhist)
-{:ok, %Cldr.Date.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_formats(:en, :buddhist)
+{:ok, %Cldr.Date.Formats{
full: "EEEE, MMMM d, y G",
long: "MMMM d, y G",
medium: "MMM d, y G",
short: "M/d/y GGGGG"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_at_formats(:en)
-{:ok, %Cldr.DateTime.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_at_formats(:en)
+{:ok, %Cldr.DateTime.Formats{
full: "{1} 'at' {0}",
long: "{1} 'at' {0}",
medium: "{1}, {0}",
- short: "{1}, {0}"}
-}
+ short: "{1}, {0}"}
+}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_at_formats(:en, :buddhist)
-{:ok, %Cldr.DateTime.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_at_formats(:en, :buddhist)
+{:ok, %Cldr.DateTime.Formats{
full: "{1} 'at' {0}",
long: "{1} 'at' {0}",
medium: "{1}, {0}",
- short: "{1}, {0}"}
-}
+ short: "{1}, {0}"}
+}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_available_formats "en"
-{
+{
:ok,
- %{
+ %{
d: "d",
h: "h a",
hm: "h:mm a",
@@ -626,7 +626,7 @@ date_time_available_formats(locale \\ Bonfi
hmv: "h:mm a v",
ms: "mm:ss",
y: "y",
- yw: %{one: "'week' w 'of' Y", other: "'week' w 'of' Y"},
+ yw: %{one: "'week' w 'of' Y", other: "'week' w 'of' Y"},
Bh: "h B",
Bhm: "h:mm B",
Bhms: "h:mm:ss B",
@@ -652,7 +652,7 @@ date_time_available_formats(locale \\ Bonfi
MEd: "E, M/d",
MMM: "LLL",
MMMEd: "E, MMM d",
- MMMMW: %{one: "'week' W 'of' MMMM", other: "'week' W 'of' MMMM"},
+ MMMMW: %{one: "'week' W 'of' MMMM", other: "'week' W 'of' MMMM"},
MMMMd: "MMMM d",
MMMd: "MMM d",
Md: "M/d",
@@ -665,8 +665,8 @@ date_time_available_formats(locale \\ Bonfi
yMd: "M/d/y",
yQQQ: "QQQ y",
yQQQQ: "QQQQ y"
- }
-}
+ }
+}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats(:en)
-{:ok, %Cldr.DateTime.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats(:en)
+{:ok, %Cldr.DateTime.Formats{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
-}}
+}}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats(:en, :buddhist)
-{:ok, %Cldr.DateTime.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_formats(:en, :buddhist)
+{:ok, %Cldr.DateTime.Formats{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.date_time_interval_fallback :en, :gregorian
-[0, " – ", 1]
+[0, " – ", 1]
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_format :en
-{:ok, ["GMT", 0]}
+{:ok, ["GMT", 0]}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_zero_format :en
-{:ok, "GMT"}
+{:ok, "GMT"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.gmt_zero_format :fr
-{:ok, "UTC"}
+{:ok, "UTC"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.hour_format "en"
-{:ok, {"+HH:mm", "-HH:mm"}}
+{:ok, {"+HH:mm", "-HH:mm"}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats(:en)
-{:ok, %Cldr.Time.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats(:en)
+{:ok, %Cldr.Time.Formats{
full: "h:mm:ss a zzzz",
long: "h:mm:ss a z",
medium: "h:mm:ss a",
short: "h:mm a"
-}}
+}}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats(:en, :buddhist)
-{:ok, %Cldr.Time.Formats{
+iex> Bonfire.Common.Localise.Cldr.DateTime.Format.time_formats(:en, :buddhist)
+{:ok, %Cldr.Time.Formats{
full: "h:mm:ss a zzzz",
long: "h:mm:ss a z",
medium: "h:mm:ss a",
short: "h:mm a"
-}}
+}}
iex> Bonfire.Common.Localise.Cldr.DateTime.Formatter.format ~U[2017-09-03 10:23:00.0Z], "yy/MM/dd hh:MM", "en"
-{:ok, "17/09/03 10:09"}
+{:ok, "17/09/03 10:09"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Interval.to_string ~U[2020-01-01 00:00:00.0Z],
...> ~U[2020-12-31 10:00:00.0Z]
-{:ok, "Jan 1, 2020, 12:00:00 AM – Dec 31, 2020, 10:00:00 AM"}
+{:ok, "Jan 1, 2020, 12:00:00 AM – Dec 31, 2020, 10:00:00 AM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Interval.to_string ~U[2020-01-01 00:00:00.0Z], nil
-{:ok, "Jan 1, 2020, 12:00:00 AM –"}
+{:ok, "Jan 1, 2020, 12:00:00 AM –"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(-1)
-{:ok, "1 second ago"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(-1)
+{:ok, "1 second ago"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1)
-{:ok, "in 1 second"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1)
+{:ok, "in 1 second"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day)
-{:ok, "tomorrow"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day)
+{:ok, "tomorrow"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
-{:ok, "demain"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, locale: "fr")
+{:ok, "demain"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, style: :narrow)
-{:ok, "tomorrow"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1, unit: :day, style: :narrow)
+{:ok, "tomorrow"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year)
-{:ok, "in 1,234 years"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year)
+{:ok, "in 1,234 years"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
-{:ok, "dans 1 234 ans"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(1234, unit: :year, locale: "fr")
+{:ok, "dans 1 234 ans"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(31)
-{:ok, "in 31 seconds"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(31)
+{:ok, "in 31 seconds"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
-{:ok, "in 3 days"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], relative_to: ~D[2017-04-26])
+{:ok, "in 3 days"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :short, locale: "fr")
-{:ok, "dans 5 min"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :short, locale: "fr")
+{:ok, "dans 5 min"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :narrow, locale: "fr")
-{:ok, "+5 min"}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(310, style: :narrow, locale: "fr")
+{:ok, "+5 min"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string 2, unit: :wed, style: :short, locale: "en"
-{:ok, "in 2 Wed."}
+{:ok, "in 2 Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string 1, unit: :wed, style: :short
-{:ok, "next Wed."}
+{:ok, "next Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :wed, style: :short
-{:ok, "last Wed."}
+{:ok, "last Wed."}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :wed
-{:ok, "last Wednesday"}
+{:ok, "last Wednesday"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :quarter
-{:ok, "last quarter"}
+{:ok, "last quarter"}
iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string -1, unit: :mon, locale: "fr"
-{:ok, "lundi dernier"}
+{:ok, "lundi dernier"}
-iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
-{:error, {Cldr.UnknownTimeUnit,
- "Unknown time unit :ziggeraut. Valid time units are [:day, :fri, :hour, :minute, :mon, :month, :quarter, :sat, :second, :sun, :thu, :tue, :wed, :week, :year]"}}
+iex> Bonfire.Common.Localise.Cldr.DateTime.Relative.to_string(~D[2017-04-29], unit: :ziggeraut)
+{:error, {Cldr.UnknownTimeUnit,
+ "Unknown time unit :ziggeraut. Valid time units are [:day, :fri, :hour, :minute, :mon, :month, :quarter, :sat, :second, :sun, :thu, :tue, :wed, :week, :year]"}}
iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime
-{:ok, "Jan 1, 2000, 11:59:59 PM"}
+{:ok, "Jan 1, 2000, 11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, locale: "en"
-{:ok, "Jan 1, 2000, 11:59:59 PM"}
+{:ok, "Jan 1, 2000, 11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :long, locale: "en"
-{:ok, "January 1, 2000, 11:59:59 PM UTC"}
+{:ok, "January 1, 2000, 11:59:59 PM UTC"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :hms, locale: "en"
-{:ok, "11:59:59 PM"}
+{:ok, "11:59:59 PM"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :full, locale: "en"
-{:ok, "Saturday, January 1, 2000, 11:59:59 PM GMT"}
+{:ok, "Saturday, January 1, 2000, 11:59:59 PM GMT"}
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string datetime, format: :full, locale: "fr"
-{:ok, "samedi 1 janvier 2000, 23:59:59 UTC"}
+{:ok, "samedi 1 janvier 2000, 23:59:59 UTC"}
iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string! datetime, locale: "en"
"Jan 1, 2000, 11:59:59 PM"
iex> Bonfire.Common.Localise.Cldr.DateTime.to_string! datetime, format: :long, locale: "en"
diff --git a/Bonfire.Common.Localise.Cldr.Interval.html b/Bonfire.Common.Localise.Cldr.Interval.html
index 3d260051c90..999c613e283 100644
--- a/Bonfire.Common.Localise.Cldr.Interval.html
+++ b/Bonfire.Common.Localise.Cldr.Interval.html
@@ -306,11 +306,11 @@ to_string(interval, options)
iex> use CalendarInterval
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~I"2020-01-01/12",
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
-iex> Bonfire.Common.Localise.Cldr.Interval.to_string Date.range(~D[2020-01-01], ~D[2020-12-31]),
+iex> Bonfire.Common.Localise.Cldr.Interval.to_string Date.range(~D[2020-01-01], ~D[2020-12-31]),
...> format: :long
-{:ok, "Wed, Jan 1 – Thu, Dec 31, 2020"}
+{:ok, "Wed, Jan 1 – Thu, Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-31]
-{:ok, "Jan 1 – Dec 31, 2020"}
+{:ok, "Jan 1 – Dec 31, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12]
-{:ok, "Jan 1 – 12, 2020"}
+{:ok, "Jan 1 – 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-01-12],
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~D[2020-01-01], ~D[2020-12-01],
...> format: :long, style: :year_and_month
-{:ok, "January – December 2020"}
+{:ok, "January – December 2020"}
iex> use CalendarInterval
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~I"2020-01-01/12",
...> format: :long
-{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
+{:ok, "Wed, Jan 1 – Sun, Jan 12, 2020"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-12-01 10:05:00.0Z],
...> format: :long
-{:ok, "January 1, 2020, 12:00:00 AM UTC – December 1, 2020, 10:05:00 AM UTC"}
+{:ok, "January 1, 2020, 12:00:00 AM UTC – December 1, 2020, 10:05:00 AM UTC"}
iex> Bonfire.Common.Localise.Cldr.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:05:00.0Z],
...> format: :long
-{:ok, "January 1, 2020, 12:00:00 AM UTC – 10:05:00 AM UTC"}
+{:ok, "January 1, 2020, 12:00:00 AM UTC – 10:05:00 AM UTC"}
> Bonfire.Common.Localise.Cldr.Language.Language.available_languages(:en)
-["aa", "ab", "ace", "ach", "ada", "ady", "ae", "aeb", "af", "afh", "agq", "ain",
+> Bonfire.Common.Localise.Cldr.Language.Language.available_languages(:en)
+["aa", "ab", "ace", "ach", "ada", "ady", "ae", "aeb", "af", "afh", "agq", "ain",
"ak", "akk", "akz", "ale", "aln", "alt", "am", "an", "ang", "anp", "ar",
"ar-001", "arc", "arn", "aro", "arp", "arq", "ars", "arw", "ary", "arz", "as",
"asa", "ase", "ast", "av", "avk", "awa", "ay", "az", "ba", "bal", "ban", "bar",
-"bas", "bax", "bbc", "bbj", ...]
+"bas", "bax", "bbc", "bbj", ...]
> Bonfire.Common.Localise.Cldr.Language.Language.known_languages(:en)
-%{"bez" => %{standard: "Bena"}, "lo" => %{standard: "Lao"},
-"kha" => %{standard: "Khasi"}, "eo" => %{standard: "Esperanto"},
-"rm" => %{standard: "Romansh"}, "ja" => %{standard: "Japanese"},
-"sw-CD" => %{standard: "Congo Swahili"},
-"pdc" => %{standard: "Pennsylvania German"}, "om" => %{standard: "Oromo"},
-"jut" => %{standard: "Jutish"}, "lij" => %{standard: "Ligurian"},
-"kut" => %{standard: "Kutenai"}, "vep" => %{standard: "Veps"},
-"yao" => %{standard: "Yao"}, "gez" => %{standard: "Geez"},
-"cr" => %{standard: "Cree"}, "ne" => %{standard: "Nepali"},
-"zbl" => %{standard: "Blissymbols"}, "ae" => %{standard: "Avestan"},
-"rof" => %{standard: "Rombo"}, "tkl" => %{standard: "Tokelau"},
-"rgn" => %{standard: "Romagnol"}, "el" => %{standard: "Greek"},
-"myv" => %{standard: "Erzya"}, "smj" => %{standard: "Lule Sami"},
-"fo" => %{standard: "Faroese"}, "ii" => %{standard: "Sichuan Yi"},
-"bum" => %{standard: "Bulu"}, "za" => %{standard: "Zhuang"},
-"raj" => %{standard: "Rajasthani"}, "mrj" => %{standard: "Western Mari"},
-"stq" => %{standard: "Saterland Frisian"}, "hu" => %{standard: "Hungarian"},
-"mga" => %{standard: "Middle Irish"}, "bej" => %{standard: "Beja"},
-"yue" => %{standard: "Cantonese"}, "xog" => %{standard: "Soga"},
-"ttt" => %{standard: "Muslim Tat"}, "uga" => %{standard: "Ugaritic"},
-"rup" => %{standard: "Aromanian"},
-"crs" => %{standard: "Seselwa Creole French"}, "oc" => %{standard: "Occitan"},
-"chp" => %{standard: "Chipewyan"}, "zen" => %{standard: "Zenaga"},
-"kmb" => %{standard: "Kimbundu"}, "nr" => %{standard: "South Ndebele"},
-"tiv" => %{standard: "Tiv"}, "aln" => %{standard: "Gheg Albanian"},
-"sh" => %{standard: "Serbo-Croatian"}, "fil" => %{...}, ...}
+> Bonfire.Common.Localise.Cldr.Language.Language.known_languages(:en)
+%{"bez" => %{standard: "Bena"}, "lo" => %{standard: "Lao"},
+"kha" => %{standard: "Khasi"}, "eo" => %{standard: "Esperanto"},
+"rm" => %{standard: "Romansh"}, "ja" => %{standard: "Japanese"},
+"sw-CD" => %{standard: "Congo Swahili"},
+"pdc" => %{standard: "Pennsylvania German"}, "om" => %{standard: "Oromo"},
+"jut" => %{standard: "Jutish"}, "lij" => %{standard: "Ligurian"},
+"kut" => %{standard: "Kutenai"}, "vep" => %{standard: "Veps"},
+"yao" => %{standard: "Yao"}, "gez" => %{standard: "Geez"},
+"cr" => %{standard: "Cree"}, "ne" => %{standard: "Nepali"},
+"zbl" => %{standard: "Blissymbols"}, "ae" => %{standard: "Avestan"},
+"rof" => %{standard: "Rombo"}, "tkl" => %{standard: "Tokelau"},
+"rgn" => %{standard: "Romagnol"}, "el" => %{standard: "Greek"},
+"myv" => %{standard: "Erzya"}, "smj" => %{standard: "Lule Sami"},
+"fo" => %{standard: "Faroese"}, "ii" => %{standard: "Sichuan Yi"},
+"bum" => %{standard: "Bulu"}, "za" => %{standard: "Zhuang"},
+"raj" => %{standard: "Rajasthani"}, "mrj" => %{standard: "Western Mari"},
+"stq" => %{standard: "Saterland Frisian"}, "hu" => %{standard: "Hungarian"},
+"mga" => %{standard: "Middle Irish"}, "bej" => %{standard: "Beja"},
+"yue" => %{standard: "Cantonese"}, "xog" => %{standard: "Soga"},
+"ttt" => %{standard: "Muslim Tat"}, "uga" => %{standard: "Ugaritic"},
+"rup" => %{standard: "Aromanian"},
+"crs" => %{standard: "Seselwa Creole French"}, "oc" => %{standard: "Occitan"},
+"chp" => %{standard: "Chipewyan"}, "zen" => %{standard: "Zenaga"},
+"kmb" => %{standard: "Kimbundu"}, "nr" => %{standard: "South Ndebele"},
+"tiv" => %{standard: "Tiv"}, "aln" => %{standard: "Gheg Albanian"},
+"sh" => %{standard: "Serbo-Croatian"}, "fil" => %{...}, ...}
iex> Bonfire.Common.Localise.Cldr.Language.Language.to_string("eo")
-{:ok, "Esperanto"}
+iex> Bonfire.Common.Localise.Cldr.Language.Language.to_string("eo")
+{:ok, "Esperanto"}
Cldr backend module that formats lists.
If we have a list of days like ["Monday", "Tuesday", "Wednesday"]
-then we can format that list for a given locale by:
iex> Bonfire.Common.Localise.Cldr.List.to_string(["Monday", "Tuesday", "Wednesday"], locale: "en")
-{:ok, "Monday, Tuesday, and Wednesday"}
+then we can format that list for a given locale by:iex> Bonfire.Common.Localise.Cldr.List.to_string(["Monday", "Tuesday", "Wednesday"], locale: "en")
+{:ok, "Monday, Tuesday, and Wednesday"}
iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "en")
-{:ok, ["a", ", ", "b", ", and ", "c"]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "en")
+{:ok, ["a", ", ", "b", ", and ", "c"]}
-iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "en", format: :unit_narrow)
-{:ok, ["a", " ", "b", " ", "c"]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "en", format: :unit_narrow)
+{:ok, ["a", " ", "b", " ", "c"]}
-iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "fr")
-{:ok, ["a", ", ", "b", " et ", "c"]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a", "b", "c"], locale: "fr")
+{:ok, ["a", ", ", "b", " et ", "c"]}
-iex> Bonfire.Common.Localise.Cldr.List.intersperse([1,2,3,4,5,6])
-{:ok, [1, ", ", 2, ", ", 3, ", ", 4, ", ", 5, ", and ", 6]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse([1,2,3,4,5,6])
+{:ok, [1, ", ", 2, ", ", 3, ", ", 4, ", ", 5, ", and ", 6]}
-iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a"])
-{:ok, ["a"]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse(["a"])
+{:ok, ["a"]}
-iex> Bonfire.Common.Localise.Cldr.List.intersperse([1,2])
-{:ok, [1, " and ", 2]}
+iex> Bonfire.Common.Localise.Cldr.List.intersperse([1,2])
+{:ok, [1, " and ", 2]}
iex> Bonfire.Common.Localise.Cldr.List.intersperse!(["a", "b", "c"], locale: "en")
-["a", ", ", "b", ", and ", "c"]
+iex> Bonfire.Common.Localise.Cldr.List.intersperse!(["a", "b", "c"], locale: "en")
+["a", ", ", "b", ", and ", "c"]
-iex> Bonfire.Common.Localise.Cldr.List.intersperse!(["a", "b", "c"], locale: "en", format: :unit_narrow)
-["a", " ", "b", " ", "c"]
+iex> Bonfire.Common.Localise.Cldr.List.intersperse!(["a", "b", "c"], locale: "en", format: :unit_narrow)
+["a", " ", "b", " ", "c"]
iex> Bonfire.Common.Localise.Cldr.List.list_formats_for(:en)
-[:or, :or_narrow, :or_short, :standard, :standard_narrow, :standard_short,
- :unit, :unit_narrow, :unit_short]
+iex> Bonfire.Common.Localise.Cldr.List.list_formats_for(:en)
+[:or, :or_narrow, :or_short, :standard, :standard_narrow, :standard_short,
+ :unit, :unit_narrow, :unit_short]
iex> Bonfire.Common.Localise.Cldr.List.list_patterns_for(:en)
-%{
- or: %{
- 2 => [0, " or ", 1],
- end: [0, ", or ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- or_narrow: %{
- 2 => [0, " or ", 1],
- end: [0, ", or ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- or_short: %{
- 2 => [0, " or ", 1],
- end: [0, ", or ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- standard: %{
- 2 => [0, " and ", 1],
- end: [0, ", and ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- standard_narrow: %{
- 2 => [0, ", ", 1],
- end: [0, ", ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- standard_short: %{
- 2 => [0, " & ", 1],
- end: [0, ", & ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- unit: %{
- 2 => [0, ", ", 1],
- end: [0, ", ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- },
- unit_narrow: %{
- 2 => [0, " ", 1],
- end: [0, " ", 1],
- middle: [0, " ", 1],
- start: [0, " ", 1]
- },
- unit_short: %{
- 2 => [0, ", ", 1],
- end: [0, ", ", 1],
- middle: [0, ", ", 1],
- start: [0, ", ", 1]
- }
-}
+iex> Bonfire.Common.Localise.Cldr.List.list_patterns_for(:en)
+%{
+ or: %{
+ 2 => [0, " or ", 1],
+ end: [0, ", or ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ or_narrow: %{
+ 2 => [0, " or ", 1],
+ end: [0, ", or ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ or_short: %{
+ 2 => [0, " or ", 1],
+ end: [0, ", or ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ standard: %{
+ 2 => [0, " and ", 1],
+ end: [0, ", and ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ standard_narrow: %{
+ 2 => [0, ", ", 1],
+ end: [0, ", ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ standard_short: %{
+ 2 => [0, " & ", 1],
+ end: [0, ", & ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ unit: %{
+ 2 => [0, ", ", 1],
+ end: [0, ", ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ },
+ unit_narrow: %{
+ 2 => [0, " ", 1],
+ end: [0, " ", 1],
+ middle: [0, " ", 1],
+ start: [0, " ", 1]
+ },
+ unit_short: %{
+ 2 => [0, ", ", 1],
+ end: [0, ", ", 1],
+ middle: [0, ", ", 1],
+ start: [0, ", ", 1]
+ }
+}
iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "en")
-{:ok, "a, b, and c"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "en")
+{:ok, "a, b, and c"}
-iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "en", format: :unit_narrow)
-{:ok, "a b c"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "en", format: :unit_narrow)
+{:ok, "a b c"}
-iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "fr")
-{:ok, "a, b et c"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string(["a", "b", "c"], locale: "fr")
+{:ok, "a, b et c"}
-iex> Bonfire.Common.Localise.Cldr.List.to_string([1,2,3,4,5,6])
-{:ok, "1, 2, 3, 4, 5, and 6"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string([1,2,3,4,5,6])
+{:ok, "1, 2, 3, 4, 5, and 6"}
-iex> Bonfire.Common.Localise.Cldr.List.to_string(["a"])
-{:ok, "a"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string(["a"])
+{:ok, "a"}
-iex> Bonfire.Common.Localise.Cldr.List.to_string([1,2])
-{:ok, "1 and 2"}
+iex> Bonfire.Common.Localise.Cldr.List.to_string([1,2])
+{:ok, "1 and 2"}
iex> Bonfire.Common.Localise.Cldr.List.to_string!(["a", "b", "c"], locale: "en")
+iex> Bonfire.Common.Localise.Cldr.List.to_string!(["a", "b", "c"], locale: "en")
"a, b, and c"
-iex> Bonfire.Common.Localise.Cldr.List.to_string!(["a", "b", "c"], locale: "en", format: :unit_narrow)
+iex> Bonfire.Common.Localise.Cldr.List.to_string!(["a", "b", "c"], locale: "en", format: :unit_narrow)
"a b c"
iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:"fr-CA")
-{:ok, [:"fr-CA", :fr, :und]}
+iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:"fr-CA")
+{:ok, [:"fr-CA", :fr, :und]}
# Fallbacks are typically formed by progressively
# stripping variant, territory and script from the
# given locale name. But not always - there are
# certain fallbacks that take a different path.
-iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:nb)
-{:ok, [:nb, :no, :und]}
+iex> Bonfire.Common.Localise.Cldr.Locale.fallback_locale_names(:nb)
+{:ok, [:nb, :no, :und]}
Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:"fr-CA")
-=> {:ok,
- [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
- #Cldr.LanguageTag<und [validated]>]}
+Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:"fr-CA")
+=> {:ok,
+ [#Cldr.LanguageTag<fr-CA [validated]>, #Cldr.LanguageTag<fr [validated]>,
+ #Cldr.LanguageTag<und [validated]>]}
# Fallbacks are typically formed by progressively
# stripping variant, territory and script from the
# given locale name. But not always - there are
# certain fallbacks that take a different path.
-Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:nb))
-=> {:ok,
- [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
- #Cldr.LanguageTag<und [validated]>]}
+Bonfire.Common.Localise.Cldr.Locale.fallback_locales(:nb))
+=> {:ok,
+ [#Cldr.LanguageTag<nb [validated]>, #Cldr.LanguageTag<no [validated]>,
+ #Cldr.LanguageTag<und [validated]>]}
iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host "a.b.com.au"
-Elixir.Bonfire.Common.Localise.Cldr.validate_locale(:"en-AU")
+Elixir.Bonfire.Common.Localise.Cldr.validate_locale(:"en-AU")
-iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com.tv")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"tv\""}}
+iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com.tv")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"tv\""}}
-iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
+iex> Bonfire.Common.Localise.Cldr.Locale.locale_from_host("a.b.com")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
iex> Cldr.Locale.territory_from_host("a.b.com.au")
-{:ok, :AU}
+iex> Cldr.Locale.territory_from_host("a.b.com.au")
+{:ok, :AU}
-iex> Cldr.Locale.territory_from_host("a.b.com")
-{:error,
- {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
+iex> Cldr.Locale.territory_from_host("a.b.com")
+{:error,
+ {Cldr.UnknownLocaleError, "No locale was identified for territory \"com\""}}
iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1, "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1, "en", %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 2, "en", %{one: "one", two: "two", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 22, "en", %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 22, "en", %{one: "one", two: "two", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(1), "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(1), "en", %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize Decimal.new(2), "en", %{one: "one", two: "two"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
"few"
-iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Cardinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
"other"
#=> Bonfire.Common.Localise.Cldr.Number.Format.Format.decimal_format_list
-["#", "#,##,##0%",
+["#", "#,##,##0%",
"#,##,##0.###", "#,##,##0.00¤", "#,##,##0.00¤;(#,##,##0.00¤)",
"#,##,##0 %", "#,##0%", "#,##0.###", "#,##0.00 ¤",
"#,##0.00 ¤;(#,##0.00 ¤)", "#,##0.00¤", "#,##0.00¤;(#,##0.00¤)",
@@ -472,7 +472,7 @@ decimal_format_list()
"000 B ¤", "000 E ¤", "000 K ¤", "000 MRD ¤", "000 Md ¤", "000 Mio'.' ¤",
"000 Mio ¤", "000 Mld ¤", "000 Mln ¤", "000 Mn ¤", "000 Mrd'.' ¤",
"000 Mrd ¤", "000 Mr ¤", "000 M ¤", "000 NT ¤", "000 N ¤", "000 Tn ¤",
-"000 Tr ¤", ...]
+"000 Tr ¤", ...]
iex> Bonfire.Common.Localise.Cldr.Number.Format.decimal_format_list_for(:en)
-{:ok, ["#,##0%", "#,##0.###", "#,##0.00", "#,##0.00;(#,##0.00)","#E0",
+iex> Bonfire.Common.Localise.Cldr.Number.Format.decimal_format_list_for(:en)
+{:ok, ["#,##0%", "#,##0.###", "#,##0.00", "#,##0.00;(#,##0.00)","#E0",
"0 billion", "0 million", "0 thousand",
"0 trillion", "00 billion", "00 million", "00 thousand", "00 trillion",
"000 billion", "000 million", "000 thousand", "000 trillion", "000B", "000K",
@@ -529,7 +529,7 @@ decimal_format_list_for(locale \\ Bonfire.C
"¤#,##0.00", "¤#,##0.00;(¤#,##0.00)", "¤000B", "¤000K", "¤000M",
"¤000T", "¤00B", "¤00K", "¤00M", "¤00T", "¤0B", "¤0K", "¤0M", "¤0T",
"¤ #,##0.00", "¤ #,##0.00;(¤ #,##0.00)", "¤ 000B", "¤ 000K", "¤ 000M",
- "¤ 000T", "¤ 00B", "¤ 00K", "¤ 00M", "¤ 00T", "¤ 0B", "¤ 0K", "¤ 0M", "¤ 0T"]}
+ "¤ 000T", "¤ 00B", "¤ 00K", "¤ 00M", "¤ 00T", "¤ 0B", "¤ 0K", "¤ 0M", "¤ 0T"]}
iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for(:en)
-{:ok, %{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for(:en)
+{:ok, %{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}}
iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for!(:en)
-%{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.default_grouping_for!(:en)
+%{fraction: %{first: 0, rest: 0}, integer: %{first: 3, rest: 3}}
iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for("en")
-{:ok, 1}
+iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for("en")
+{:ok, 1}
iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for!("en")
+iex> Bonfire.Common.Localise.Cldr.Number.Format.minimum_grouping_digits_for!("en")
1
iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1, :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1, :en, %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 2, :en, %{one: "one", two: "two"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 22, :en, %{one: "one", two: "two", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 22, :en, %{one: "one", two: "two", other: "other"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(1), :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(1), :en, %{one: "one"}
"one"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one"}
nil
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one", two: "two"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize Decimal.new(2), :en, %{one: "one", two: "two"}
"two"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "ar", %{one: "one", few: "few", other: "other"}
"other"
-iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
+iex> Bonfire.Common.Localise.Cldr.Number.Ordinal.pluralize 1..10, "en", %{one: "one", few: "few", other: "other"}
"other"
diff --git a/Bonfire.Common.Localise.Cldr.Number.Symbol.html b/Bonfire.Common.Localise.Cldr.Number.Symbol.html
index b5da0a83452..fdc487eac32 100644
--- a/Bonfire.Common.Localise.Cldr.Number.Symbol.html
+++ b/Bonfire.Common.Localise.Cldr.Number.Symbol.html
@@ -372,9 +372,9 @@ number_symbols_for(locale \\ Bonfire.Common
Example:
-iex> Bonfire.Common.Localise.Cldr.Number.Symbol.number_symbols_for(:th)
-{:ok, %{
- latn: %Cldr.Number.Symbol{
+iex> Bonfire.Common.Localise.Cldr.Number.Symbol.number_symbols_for(:th)
+{:ok, %{
+ latn: %Cldr.Number.Symbol{
decimal: ".",
exponential: "E",
group: ",",
@@ -387,8 +387,8 @@ number_symbols_for(locale \\ Bonfire.Common
plus_sign: "+",
superscripting_exponent: "×",
time_separator: ":"
- },
- thai: %Cldr.Number.Symbol{
+ },
+ thai: %Cldr.Number.Symbol{
decimal: ".",
exponential: "E",
group: ",",
@@ -401,8 +401,8 @@ number_symbols_for(locale \\ Bonfire.Common
plus_sign: "+",
superscripting_exponent: "×",
time_separator: ":"
- }
- }}
+ }
+ }}
diff --git a/Bonfire.Common.Localise.Cldr.Number.System.html b/Bonfire.Common.Localise.Cldr.Number.System.html
index 9133e1b4436..c4a68fcca1f 100644
--- a/Bonfire.Common.Localise.Cldr.Number.System.html
+++ b/Bonfire.Common.Localise.Cldr.Number.System.html
@@ -311,23 +311,23 @@ number_system_for(locale, system_name)
Examples
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "th", :latn
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :default
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "he", :traditional
-{:ok, %{rules: "hebrew", type: :algorithmic}}
+{:ok, %{rules: "hebrew", type: :algorithmic}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :native
-{:ok, %{digits: "0123456789", type: :numeric}}
+{:ok, %{digits: "0123456789", type: :numeric}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_for "en", :finance
-{
+{
:error,
- {Cldr.UnknownNumberSystemError,
- "The number system :finance is unknown for the locale named :en. Valid number systems are %{default: :latn, native: :latn}"}
-}
+
{Cldr.UnknownNumberSystemError,
+ "The number system :finance is unknown for the locale named :en. Valid number systems are %{default: :latn, native: :latn}"}
+}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_names_for "en"
-{:ok, [:latn]}
+{:ok, [:latn]}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_system_names_for "zz"
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "en"
-{:ok, %{default: :latn, native: :latn}}
+{:ok, %{default: :latn, native: :latn}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "th"
-{:ok, %{default: :latn, native: :thai}}
+{:ok, %{default: :latn, native: :thai}}
iex> Bonfire.Common.Localise.Cldr.Number.System.number_systems_for "zz"
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
ex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:default, "en")
-{:ok, :latn}
+ex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:default, "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from("latn", "en")
-{:ok, :latn}
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from("latn", "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:native, "en")
-{:ok, :latn}
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:native, "en")
+{:ok, :latn}
-iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:nope, "en")
-{
+iex> Bonfire.Common.Localise.Cldr.Number.System.system_name_from(:nope, "en")
+{
:error,
- {Cldr.UnknownNumberSystemError, "The number system :nope is unknown"}
-}
Note that return value is not guaranteed to be a valid
+
{Cldr.UnknownNumberSystemError, "The number system :nope is unknown"}
+}
Note that return value is not guaranteed to be a valid number system for the given locale as demonstrated in the third example.
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123456, :hebr
-{:ok, "קכ״ג׳תנ״ו"}
+{:ok, "קכ״ג׳תנ״ו"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hans
-{:ok, "一百二十三"}
+{:ok, "一百二十三"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hant
-{:ok, "一百二十三"}
+{:ok, "一百二十三"}
iex> Bonfire.Common.Localise.Cldr.Number.System.to_system 123, :hansfin
-{:ok, "壹佰贰拾叁"}
+{:ok, "壹佰贰拾叁"}
To configure these transliteration pairs, add the to the use Cldr
configuration
-in a backend module:
defmodule MyApp.Cldr do
+in a backend module:defmodule MyApp.Cldr do
use Cldr,
- locale: ["en", "fr", "th"],
+ locale: ["en", "fr", "th"],
default_locale: "en",
- precompile_transliterations: [{:latn, :thai}, {:arab, :thai}]
-end
Where each tuple in the list configures one transliteration map. In this example, two maps are
+
precompile_transliterations: [{:latn, :thai}, {:arab, :thai}]
+end
Where each tuple in the list configures one transliteration map. In this example, two maps are
configured: from :latn
to :thai
and from :arab
to :thai
.
A list of configurable number systems is returned by Cldr.Number.System.numeric_systems/0
.
If a transliteration is requested between two number pairs that have not been configured for precompilation, a warning is logged.
iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556")
"123556"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123,556.000", "fr", :default)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123,556.000", "fr", :default)
"123 556,000"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :default)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :default)
"123556"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", "thai")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", "thai")
"๑๒๓๕๕๖"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :native)
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("123556", "th", :native)
"๑๒๓๕๕๖"
-iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("Some number is: 123556", "th", "thai")
+iex> Bonfire.Common.Localise.Cldr.Number.Transliterate.transliterate("Some number is: 123556", "th", "thai")
"Some number is: ๑๒๓๕๕๖"
diff --git a/Bonfire.Common.Localise.Cldr.Number.html b/Bonfire.Common.Localise.Cldr.Number.html
index 702daf6c423..5f54e8d4359 100644
--- a/Bonfire.Common.Localise.Cldr.Number.html
+++ b/Bonfire.Common.Localise.Cldr.Number.html
@@ -435,19 +435,19 @@ parse(string, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de")
-{:ok, 1000.34}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de")
+{:ok, 1000.34}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("-1_000_000.34")
-{:ok, -1000000.34}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("-1_000_000.34")
+{:ok, -1000000.34}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("1.000", locale: "de", number: :integer)
-{:ok, 1000}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("1.000", locale: "de", number: :integer)
+{:ok, 1000}
-iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de", number: :integer)
-{:error,
- {Cldr.Number.ParseError,
- "The string \"+1.000,34\" could not be parsed as a number"}}
+iex> Bonfire.Common.Localise.Cldr.Number.parse("+1.000,34", locale: "de", number: :integer)
+{:error,
+ {Cldr.Number.ParseError,
+ "The string \"+1.000,34\" could not be parsed as a number"}}
@@ -519,17 +519,17 @@ resolve_currencies(list, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 US dollars")
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 US dollars")
...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies
-[100, :USD]
+[100, :USD]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 eurosports")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(fuzzy: 0.75)
-[100, :EUR]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 eurosports")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(fuzzy: 0.75)
+[100, :EUR]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("100 dollars des États-Unis")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(locale: "fr")
-[100, :USD]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100 dollars des États-Unis")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_currencies(locale: "fr")
+[100, :USD]
@@ -606,19 +606,19 @@ resolve_currency(string, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("US dollars")
-[:USD]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("US dollars")
+[:USD]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("100 eurosports", fuzzy: 0.75)
-[:EUR]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("100 eurosports", fuzzy: 0.75)
+[:EUR]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("dollars des États-Unis", locale: "fr")
-[:USD]
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("dollars des États-Unis", locale: "fr")
+[:USD]
-iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("not a known currency", locale: "fr")
-{:error,
- {Cldr.UnknownCurrencyError,
- "The currency \"not a known currency\" is unknown or not supported"}}
+iex> Bonfire.Common.Localise.Cldr.Number.resolve_currency("not a known currency", locale: "fr")
+{:error,
+ {Cldr.UnknownCurrencyError,
+ "The currency \"not a known currency\" is unknown or not supported"}}
@@ -682,13 +682,13 @@ resolve_per(string, options \\ [])
Examples
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "11%"
-["11", :percent]
+["11", :percent]
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "% of linguists"
-[:percent, " of linguists"]
+[:percent, " of linguists"]
iex> Bonfire.Common.Localise.Cldr.Number.resolve_per "% of linguists %"
-[:percent, " of linguists ", :percent]
+ [:percent, " of linguists ", :percent]
iex> Bonfire.Common.Localise.Cldr.Number.scan("100%")
-...> |> Bonfire.Common.Localise.Cldr.Number.resolve_pers()
-[100, :percent]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("100%")
+...> |> Bonfire.Common.Localise.Cldr.Number.resolve_pers()
+[100, :percent]
iex> Bonfire.Common.Localise.Cldr.Number.scan("£1_000_000.34")
-["£", 1000000.34]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("£1_000_000.34")
+["£", 1000000.34]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("I want £1_000_000 dollars")
-["I want £", 1000000, " dollars"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("I want £1_000_000 dollars")
+["I want £", 1000000, " dollars"]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The prize is 23")
-["The prize is ", 23]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The prize is 23")
+["The prize is ", 23]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The lottery number is 23 for the next draw")
-["The lottery number is ", 23, " for the next draw"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The lottery number is 23 for the next draw")
+["The lottery number is ", 23, " for the next draw"]
-iex> Bonfire.Common.Localise.Cldr.Number.scan("The loss is -1.000 euros", locale: "de", number: :integer)
-["The loss is ", -1000, " euros"]
+iex> Bonfire.Common.Localise.Cldr.Number.scan("The loss is -1.000 euros", locale: "de", number: :integer)
+["The loss is ", -1000, " euros"]
iex> Bonfire.Common.Localise.Cldr.Number.to_approx_string 1234
-{:ok, "~1,234"}
+{:ok, "~1,234"}
iex> Bonfire.Common.Localise.Cldr.Number.to_at_least_string 1234
-{:ok, "1,234+"}
+{:ok, "1,234+"}
iex> Bonfire.Common.Localise.Cldr.Number.to_at_most_string 1234
-{:ok, "≤1,234"}
+{:ok, "≤1,234"}
iex> Bonfire.Common.Localise.Cldr.Number.to_range_string 1234..5678
-{:ok, "1,234–5,678"}
+{:ok, "1,234–5,678"}
Wrapping elements is particularly useful when formatting a number with a currency symbol and the requirement is to have different HTML formatting -applied to the symbol than the number. For example:
iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
+applied to the symbol than the number. For example:iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
...> string, :currency_symbol -> "<span class=\"symbol\">" <> string <> "</span>"
...> string, :number -> "<span class=\"number\">" <> string <> "</span>"
...> string, :currency_space -> "<span>" <> string <> "</span>"
...> string, _other -> string
-...> end)
-{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
It is also possible and recommended to use the Phoenix.HTML.Tag.content_tag/3
+
...> end)
+{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
It is also possible and recommended to use the Phoenix.HTML.Tag.content_tag/3
function if wrapping HTML tags since these will ensure HTML entities are
-correctly encoded. For example:
iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
-...> string, :currency_symbol -> Phoenix.HTML.Tag.content_tag(:span, string, class: "symbol")
-...> string, :number -> Phoenix.HTML.Tag.content_tag(:span, string, class: "number")
-...> string, :currency_space -> Phoenix.HTML.Tag.content_tag(:span, string)
+correctly encoded. For example:iex> Cldr.Number.to_string(100, format: :currency, currency: :USD, wrapper: fn
+...> string, :currency_symbol -> Phoenix.HTML.Tag.content_tag(:span, string, class: "symbol")
+...> string, :number -> Phoenix.HTML.Tag.content_tag(:span, string, class: "number")
+...> string, :currency_space -> Phoenix.HTML.Tag.content_tag(:span, string)
...> string, _other -> string
-...> end)
-{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
When formatting a number the format is parsed into format elements that might include
+
...> end)
+{:ok, "<span class=\"symbol\">$</span><span class=\"number\">100.00</span>"}
When formatting a number the format is parsed into format elements that might include a currency symbol, a literal string, inserted text between a currency symbol and the currency amount, a percent sign, the number itself and several other elements. In some cases it is helpful to be apply specific formatting to each element. @@ -1162,80 +1162,80 @@
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345
-{:ok, "12,345"}
+{:ok, "12,345"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, locale: "fr"
-{:ok, "12 345"}
+{:ok, "12 345"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es", minimum_grouping_digits: 1
-{:ok, "1.345,32 €"}
+{:ok, "1.345,32 €"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es"
-{:ok, "1345,32 €"}
+{:ok, "1345,32 €"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, locale: "fr", currency: "USD"
-{:ok, "12 345,00 $US"}
+{:ok, "12 345,00 $US"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: "#E0"
-{:ok, "1.2345E4"}
+{:ok, "1.2345E4"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB"
-{:ok, "THB 12,345.00"}
+{:ok, "THB 12,345.00"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string -12345, format: :accounting, currency: "THB"
-{:ok, "(THB 12,345.00)"}
+{:ok, "(THB 12,345.00)"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB",
...> locale: "th"
-{:ok, "฿12,345.00"}
+{:ok, "฿12,345.00"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 12345, format: :accounting, currency: "THB",
...> locale: "th", number_system: :native
-{:ok, "฿๑๒,๓๔๕.๐๐"}
+{:ok, "฿๑๒,๓๔๕.๐๐"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :long
-{:ok, "1 thousand"}
+{:ok, "1 thousand"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :long, currency: "USD"
-{:ok, "1,244 US dollars"}
+{:ok, "1,244 US dollars"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :short
-{:ok, "1K"}
+{:ok, "1K"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1244.30, format: :short, currency: "EUR"
-{:ok, "€1K"}
+{:ok, "€1K"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1234, format: :spellout
-{:ok, "one thousand two hundred thirty-four"}
+{:ok, "one thousand two hundred thirty-four"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1234, format: :spellout_verbose
-{:ok, "one thousand two hundred and thirty-four"}
+{:ok, "one thousand two hundred and thirty-four"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 1989, format: :spellout_year
-{:ok, "nineteen eighty-nine"}
+{:ok, "nineteen eighty-nine"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, format: :ordinal
-{:ok, "123rd"}
+{:ok, "123rd"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, format: :roman
-{:ok, "CXXIII"}
+{:ok, "CXXIII"}
iex> Bonfire.Common.Localise.Cldr.Number.to_string 123, locale: "th-u-nu-thai"
-{:ok, "๑๒๓"}
An error tuple {:error, reason}
will be returned if an error is detected.
-The two most likely causes of an error return are:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(12345, format: "0#")
- {:error, {Cldr.FormatCompileError,
- "Decimal format compiler: syntax error before: \"#\""}}
locale
and
+The two most likely causes of an error return are: iex> Bonfire.Common.Localise.Cldr.Number.to_string(12345, format: "0#")
+ {:error, {Cldr.FormatCompileError,
+ "Decimal format compiler: syntax error before: \"#\""}}
locale
and
number_system
. This happens typically when the number system is
:algorithmic
rather than the more common :numeric
. In this case the error
-return looks like: iex> Bonfire.Common.Localise.Cldr.Number.to_string(1234, locale: "he", number_system: "hebr", format: :percent)
- {:error, {Cldr.UnknownFormatError,
- "The locale :he with number system :hebr does not define a format :percent"}}
+return looks like: iex> Bonfire.Common.Localise.Cldr.Number.to_string(1234, locale: "he", number_system: "hebr", format: :percent)
+ {:error, {Cldr.UnknownFormatError,
+ "The locale :he with number system :hebr does not define a format :percent"}}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :latn
-{:ok, :latn}
+{:ok, :latn}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :default
-{:ok, :latn}
+{:ok, :latn}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "en", :unknown
-{:error,
- {Cldr.UnknownNumberSystemError, "The number system :unknown is unknown"}}
+{:error,
+ {Cldr.UnknownNumberSystemError, "The number system :unknown is unknown"}}
iex> Bonfire.Common.Localise.Cldr.Number.validate_number_system "zz", :default
-{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
+{:error, {Cldr.InvalidLanguageError, "The language \"zz\" is invalid"}}
Functions to implement the number system rule-based-number-format rules of CLDR.
These rules are defined only on the "und" locale and represent specialised number formatting.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.rule_sets(:und)
-...> |> Enum.sort()
-[
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.rule_sets(:und)
+...> |> Enum.sort()
+[
:armenian_lower,
:armenian_upper,
:cyrillic_lower,
@@ -155,9 +155,9 @@
:roman_upper,
:tamil,
:zz_default
-]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.roman_upper(123, :und)
-"CXXIII"
This particular call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :roman)
-{:ok, "CXXIII"}
+]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.NumberSystem.roman_upper(123, :und)
+"CXXIII"
This particular call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :roman)
+{:ok, "CXXIII"}
Functions to implement the ordinal rule-based-number-format rules of CLDR.
As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets(:en)
-[:digits_ordinal]
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets(:en)
+[:digits_ordinal]
-iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets("fr")
-...> |> Enum.sort()
-[
+iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.rule_sets("fr")
+...> |> Enum.sort()
+[
:digits_ordinal,
:digits_ordinal_feminine,
:digits_ordinal_feminine_plural,
:digits_ordinal_masculine,
:digits_ordinal_masculine_plural
-]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.digits_ordinal(123, :en)
-"123rd"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :ordinal)
-{:ok, "123rd"}
+]
A rule can then be invoked on an available rule_set. For example
iex> Bonfire.Common.Localise.Cldr.Rbnf.Ordinal.digits_ordinal(123, :en)
+"123rd"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :ordinal)
+{:ok, "123rd"}
Functions to implement the spellout rule-based-number-format rules of CLDR.
As CLDR notes, the data is incomplete or non-existent for many languages. It is considered complete for English however.
The standard public API for RBNF is via the Cldr.Number.to_string/2
function.
The functions on this module are defined at compile time based upon the RBNF rules -defined in the Unicode CLDR data repository. Available rules are identified by:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.rule_sets("en")
-...> |> Enum.sort()
-[
+defined in the Unicode CLDR data repository. Available rules are identified by:iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.rule_sets("en")
+...> |> Enum.sort()
+[
:spellout_cardinal,
:spellout_cardinal_verbose,
:spellout_numbering,
@@ -149,9 +149,9 @@
:spellout_numbering_year,
:spellout_ordinal,
:spellout_ordinal_verbose
-]
A rule can then be invoked on an available rule_set. For example:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.spellout_ordinal(123, "en")
-"one hundred twenty-third"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :spellout)
-{:ok, "one hundred twenty-three"}
+]
A rule can then be invoked on an available rule_set. For example:
iex> Bonfire.Common.Localise.Cldr.Rbnf.Spellout.spellout_ordinal(123, "en")
+"one hundred twenty-third"
This call is equivalent to the call through the public API of:
iex> Bonfire.Common.Localise.Cldr.Number.to_string(123, format: :spellout)
+{:ok, "one hundred twenty-three"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :short
-{:ok, "10 – 10 AM"}
+{:ok, "10 – 10 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :medium
-{:ok, "10:00 – 10:03 AM"}
+{:ok, "10:00 – 10:03 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00], format: :long
-{:ok, "10:00 – 10:03 AM"}
+{:ok, "10:00 – 10:03 AM"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00],
...> format: :long, style: :flex
-{:ok, "10:00 – 10:03 in the morning"}
+{:ok, "10:00 – 10:03 in the morning"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:00:00.0Z],
...> format: :long, style: :flex
-{:ok, "12:00 – 10:00 in the morning"}
+{:ok, "12:00 – 10:00 in the morning"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~U[2020-01-01 00:00:00.0Z], ~U[2020-01-01 10:00:00.0Z],
...> format: :long, style: :zone
-{:ok, "12:00 – 10:00 AM Etc/UTC"}
+{:ok, "12:00 – 10:00 AM Etc/UTC"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], ~T[10:03:00],
...> format: :long, style: :flex, locale: "th"
-{:ok, "10:00 – 10:03 ในตอนเช้า"}
+{:ok, "10:00 – 10:03 ในตอนเช้า"}
iex> Bonfire.Common.Localise.Cldr.Time.Interval.to_string ~T[10:00:00], nil
-{:ok, "10:00:00 AM –"}
+{:ok, "10:00:00 AM –"}
iex> Cldr.Time.to_string ~T[07:35:13.215217]
-{:ok, "7:35:13 AM"}
+{:ok, "7:35:13 AM"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :short
-{:ok, "7:35 AM"}
+{:ok, "7:35 AM"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :medium, locale: "fr"
-{:ok, "07:35:13"}
+{:ok, "07:35:13"}
iex> Cldr.Time.to_string ~T[07:35:13.215217], format: :medium
-{:ok, "7:35:13 AM"}
+{:ok, "7:35:13 AM"}
-iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
+iex> {:ok, datetime} = DateTime.from_naive(~N[2000-01-01 23:59:59.0], "Etc/UTC")
iex> Cldr.Time.to_string datetime, format: :long
-{:ok, "11:59:59 PM UTC"}
+{:ok, "11:59:59 PM UTC"}
iex> unit = Cldr.Unit.new!(1.83, :meter)
-iex> Bonfire.Common.Localise.Cldr.Unit.localize(unit, usage: :person_height, territory: :US)
-[
- Cldr.Unit.new!(:foot, 6, usage: :person_height),
- Cldr.Unit.new!(:inch, "0.04724409448818897637795275598", usage: :person_height)
-]
+iex> unit = Cldr.Unit.new!(1.83, :meter)
+iex> Bonfire.Common.Localise.Cldr.Unit.localize(unit, usage: :person_height, territory: :US)
+[
+ Cldr.Unit.new!(:foot, 6, usage: :person_height),
+ Cldr.Unit.new!(:inch, "0.04724409448818897637795275598", usage: :person_height)
+]
iex> Bonfire.Common.Localise.Cldr.Unit.parse "1kg"
-Cldr.Unit.new(1, :kilogram)
+Cldr.Unit.new(1, :kilogram)
iex> Bonfire.Common.Localise.Cldr.Unit.parse "1 tages", locale: "de"
-Cldr.Unit.new(1, :day)
+Cldr.Unit.new(1, :day)
iex> Bonfire.Common.Localise.Cldr.Unit.parse "1 tag", locale: "de"
-Cldr.Unit.new(1, :day)
+Cldr.Unit.new(1, :day)
-iex> Bonfire.Common.Localise.Cldr.Unit.parse("42 millispangels")
-{:error, {Cldr.UnknownUnitError, "Unknown unit was detected at \"spangels\""}}
+iex> Bonfire.Common.Localise.Cldr.Unit.parse("42 millispangels")
+{:error, {Cldr.UnknownUnitError, "Unknown unit was detected at \"spangels\""}}
iex> Bonfire.Common.Localise.Cldr.Unit.parse! "1kg"
-Cldr.Unit.new!(1, :kilogram)
+Cldr.Unit.new!(1, :kilogram)
iex> Bonfire.Common.Localise.Cldr.Unit.parse! "1 tages", locale: "de"
-Cldr.Unit.new!(1, :day)
+Cldr.Unit.new!(1, :day)
-iex> Bonfire.Common.Localise.Cldr.Unit.parse!("42 candela per lux")
-Cldr.Unit.new!(42, "candela per lux")
+iex> Bonfire.Common.Localise.Cldr.Unit.parse!("42 candela per lux")
+Cldr.Unit.new!(42, "candela per lux")
-iex> Bonfire.Common.Localise.Cldr.Unit.parse!("42 millispangels")
+iex> Bonfire.Common.Localise.Cldr.Unit.parse!("42 millispangels")
** (Cldr.UnknownUnitError) Unknown unit was detected at "spangels"
iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "kg"
-{:ok, :kilogram}
+{:ok, :kilogram}
iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "w"
-{:ok, :watt}
+{:ok, :watt}
iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "w", only: :duration
-{:ok, :week}
+{:ok, :week}
-iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "m", only: [:year, :month, :day]
-{:ok, :month}
+iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "m", only: [:year, :month, :day]
+{:ok, :month}
iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "tages", locale: "de"
-{:ok, :day}
+{:ok, :day}
iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name "tag", locale: "de"
-{:ok, :day}
+{:ok, :day}
-iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name("millispangels")
-{:error, {Cldr.UnknownUnitError, "Unknown unit was detected at \"spangels\""}}
+iex> Bonfire.Common.Localise.Cldr.Unit.parse_unit_name("millispangels")
+{:error, {Cldr.UnknownUnitError, "Unknown unit was detected at \"spangels\""}}
iex> meter = Cldr.Unit.new!(:meter, 1)
+iex> meter = Cldr.Unit.new!(:meter, 1)
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units meter, locale: "en-US", usage: :person_height
-{:ok, [:foot, :inch], []}
+{:ok, [:foot, :inch], []}
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units meter, locale: "en-US", usage: :person
-{:ok, [:inch], []}
+{:ok, [:inch], []}
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units meter, locale: "en-AU", usage: :person
-{:ok, [:centimeter], []}
+{:ok, [:centimeter], []}
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units meter, locale: "en-US", usage: :road
-{:ok, [:foot], [round_nearest: 1]}
+{:ok, [:foot], [round_nearest: 1]}
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units meter, locale: "en-AU", usage: :road
-{:ok, [:meter], [round_nearest: 1]}
+{:ok, [:meter], [round_nearest: 1]}
iex> meter = Cldr.Unit.new!(:meter, 2)
+iex> meter = Cldr.Unit.new!(:meter, 2)
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units! meter, locale: "en-US", usage: :person_height
-[:foot, :inch]
+[:foot, :inch]
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units! meter, locale: "en-AU", usage: :person
-[:centimeter]
+[:centimeter]
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units! meter, locale: "en-US", usage: :road
-[:foot]
+[:foot]
iex> Bonfire.Common.Localise.Cldr.Unit.preferred_units! meter, locale: "en-AU", usage: :road
-[:meter]
+[:meter]
iex> Bonfire.Common.Localise.Cldr.Unit.to_iolist Cldr.Unit.new!(:gallon, 123)
-{:ok, ["123", " gallons"]}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_iolist Cldr.Unit.new!(:gallon, 123)
+{:ok, ["123", " gallons"]}
iex> Bonfire.Common.Localise.Cldr.Unit.to_iolist! 123, unit: :gallon
-["123", " gallons"]
+["123", " gallons"]
iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 123)
-{:ok, "123 gallons"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 123)
+{:ok, "123 gallons"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1)
-{:ok, "1 gallon"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1)
+{:ok, "1 gallon"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "af"
-{:ok, "1 gelling"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "af"
+{:ok, "1 gelling"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "af-NA"
-{:ok, "1 gelling"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "af-NA"
+{:ok, "1 gelling"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "bs"
-{:ok, "1 galon"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1), locale: "bs"
+{:ok, "1 galon"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1234), format: :long
-{:ok, "1 thousand gallons"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1234), format: :long
+{:ok, "1 thousand gallons"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1234), format: :short
-{:ok, "1K gallons"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:gallon, 1234), format: :short
+{:ok, "1K gallons"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megahertz, 1234)
-{:ok, "1,234 megahertz"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megahertz, 1234)
+{:ok, "1,234 megahertz"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megahertz, 1234), style: :narrow
-{:ok, "1,234MHz"}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megahertz, 1234), style: :narrow
+{:ok, "1,234MHz"}
-iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megabyte, 1234), locale: "en", style: :unknown
-{:error, {Cldr.UnknownFormatError, "The unit style :unknown is not known."}}
+iex> Bonfire.Common.Localise.Cldr.Unit.to_string Cldr.Unit.new!(:megabyte, 1234), locale: "en", style: :unknown
+{:error, {Cldr.UnknownFormatError, "The unit style :unknown is not known."}}
iex> Bonfire.Common.Localise.Cldr.default_locale()
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.default_locale()
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en-001",
cldr_locale_name: :"en-001",
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en-001",
script: :Latn,
territory: :"001",
- transform: %{},
- language_variants: []
-}
+ transform: %{},
+ language_variants: []
+}
iex> Bonfire.Common.Localise.Cldr.default_territory()
+iex> Bonfire.Common.Localise.Cldr.default_territory()
:"001"
iex> Bonfire.Common.Localise.Cldr.ellipsis("And furthermore")
+iex> Bonfire.Common.Localise.Cldr.ellipsis("And furthermore")
"And furthermore…"
-iex> Bonfire.Common.Localise.Cldr.ellipsis(["And furthermore", "there is much to be done"], locale: :ja)
+iex> Bonfire.Common.Localise.Cldr.ellipsis(["And furthermore", "there is much to be done"], locale: :ja)
"And furthermore…there is much to be done"
-iex> Bonfire.Common.Localise.Cldr.ellipsis("And furthermore", format: :word)
+iex> Bonfire.Common.Localise.Cldr.ellipsis("And furthermore", format: :word)
"And furthermore …"
-iex> Bonfire.Common.Localise.Cldr.ellipsis(["And furthermore", "there is much to be done"], locale: :ja, format: :word)
+iex> Bonfire.Common.Localise.Cldr.ellipsis(["And furthermore", "there is much to be done"], locale: :ja, format: :word)
"And furthermore … there is much to be done"
@@ -709,23 +709,23 @@ get_locale()
Example
-iex> Bonfire.Common.Localise.Cldr.put_locale("pl")
-iex> Bonfire.Common.Localise.Cldr.get_locale()
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.put_locale("pl")
+iex> Bonfire.Common.Localise.Cldr.get_locale()
+%Cldr.LanguageTag{
backend: Elixir.Bonfire.Common.Localise.Cldr,
canonical_locale_name: "pl",
cldr_locale_name: :pl,
- extensions: %{},
+ extensions: %{},
language: "pl",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :pl,
territory: :PL,
requested_locale_name: "pl",
script: :Latn,
- transform: %{},
- language_variants: []
- }
+ transform: %{},
+ language_variants: []
+ }
@@ -812,10 +812,10 @@ known_gettext_locale_name(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name("en")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name("en")
"en"
-iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name("en-SA")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name("en-SA")
false
@@ -858,10 +858,10 @@ known_gettext_locale_name?(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("en")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("en")
true
-iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("!!")
+iex> Bonfire.Common.Localise.Cldr.known_gettext_locale_name?("!!")
false
@@ -935,10 +935,10 @@ known_locale_name(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_locale_name(:"en-AU")
+iex> Bonfire.Common.Localise.Cldr.known_locale_name(:"en-AU")
:"en-AU"
-iex> Bonfire.Common.Localise.Cldr.known_locale_name(:"en-SA")
+iex> Bonfire.Common.Localise.Cldr.known_locale_name(:"en-SA")
false
@@ -980,10 +980,10 @@ known_locale_name?(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:en)
+iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:en)
true
-iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:"!!")
+iex> Bonfire.Common.Localise.Cldr.known_locale_name?(:"!!")
false
@@ -1037,8 +1037,8 @@ known_number_system_types()
Example
-iex> Bonfire.Common.Localise.Cldr.known_number_system_types()
-[:default, :finance, :native, :traditional]
+iex> Bonfire.Common.Localise.Cldr.known_number_system_types()
+[:default, :finance, :native, :traditional]
@@ -1103,10 +1103,10 @@ known_rbnf_locale_name(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name(:en)
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name(:en)
:en
-iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name(:"en-SA")
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name(:"en-SA")
false
@@ -1149,10 +1149,10 @@ known_rbnf_locale_name?(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:en)
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:en)
true
-iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:"!!")
+iex> Bonfire.Common.Localise.Cldr.known_rbnf_locale_name?(:"!!")
false
@@ -1288,14 +1288,14 @@ put_gettext_locale(locale)
Examples
iex> import Cldr.LanguageTag.Sigil
-iex> Bonfire.Common.Localise.Cldr.put_gettext_locale(~l"en")
-{:ok, "en"}
+iex> Bonfire.Common.Localise.Cldr.put_gettext_locale(~l"en")
+{:ok, "en"}
iex> import Cldr.LanguageTag.Sigil
-iex> Bonfire.Common.Localise.Cldr.put_gettext_locale(~l"de")
-{:error,
- {Cldr.UnknownLocaleError,
- "Locale #Cldr.LanguageTag<de [validated]> does not map to a known gettext locale name"}}
+iex> Bonfire.Common.Localise.Cldr.put_gettext_locale(~l"de")
+{:error,
+ {Cldr.UnknownLocaleError,
+ "Locale #Cldr.LanguageTag<de [validated]> does not map to a known gettext locale name"}}
@@ -1339,29 +1339,29 @@ put_locale(locale_name)
Examples
-iex> Bonfire.Common.Localise.Cldr.put_locale("en")
-{:ok,
- %Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.put_locale("en")
+{:ok,
+ %Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en",
cldr_locale_name: :en,
- language_subtags: [],
- extensions: %{},
+ language_subtags: [],
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en",
script: :Latn,
territory: :US,
- transform: %{},
- language_variants: []
- }}
+ transform: %{},
+ language_variants: []
+ }}
-iex> Bonfire.Common.Localise.Cldr.put_locale("invalid-locale!")
-{:error, {Cldr.LanguageTag.ParseError,
- "Expected a BCP47 language tag. Could not parse the remaining \"!\" starting at position 15"}}
+iex> Bonfire.Common.Localise.Cldr.put_locale("invalid-locale!")
+{:error, {Cldr.LanguageTag.ParseError,
+ "Expected a BCP47 language tag. Could not parse the remaining \"!\" starting at position 15"}}
@@ -1410,10 +1410,10 @@ quote(string, options \\ [])
Examples
-iex> Bonfire.Common.Localise.Cldr.quote("Quoted String")
+iex> Bonfire.Common.Localise.Cldr.quote("Quoted String")
"“Quoted String”"
-iex> Bonfire.Common.Localise.Cldr.quote("Quoted String", locale: :ja)
+iex> Bonfire.Common.Localise.Cldr.quote("Quoted String", locale: :ja)
"「Quoted String」"
@@ -1544,47 +1544,47 @@ validate_locale(locale)
Examples
-iex> Bonfire.Common.Localise.Cldr.validate_locale(:en)
-{:ok,
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.validate_locale(:en)
+{:ok,
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en",
cldr_locale_name: :en,
- extensions: %{},
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en",
script: :Latn,
territory: :US,
- transform: %{},
- language_variants: []
-}}
+ transform: %{},
+ language_variants: []
+}}
-iex> Bonfire.Common.Localise.Cldr.validate_locale Bonfire.Common.Localise.Cldr.default_locale()
-{:ok,
-%Cldr.LanguageTag{
+iex> Bonfire.Common.Localise.Cldr.validate_locale Bonfire.Common.Localise.Cldr.default_locale()
+{:ok,
+%Cldr.LanguageTag{
backend: Bonfire.Common.Localise.Cldr,
canonical_locale_name: "en-001",
cldr_locale_name: :"en-001",
- extensions: %{},
+ extensions: %{},
gettext_locale_name: "en",
language: "en",
- locale: %{},
- private_use: [],
+ locale: %{},
+ private_use: [],
rbnf_locale_name: :en,
requested_locale_name: "en-001",
script: :Latn,
territory: :"001",
- transform: %{},
- language_variants: []
-}}
+ transform: %{},
+ language_variants: []
+}}
-iex> Bonfire.Common.Localise.Cldr.validate_locale("zzz")
-{:error, {Cldr.InvalidLanguageError, "The language \"zzz\" is invalid"}}
+iex> Bonfire.Common.Localise.Cldr.validate_locale("zzz")
+{:error, {Cldr.InvalidLanguageError, "The language \"zzz\" is invalid"}}
@@ -1654,23 +1654,23 @@ validate_number_system_type(number_system_t
Examples
-iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:default)
-{:ok, :default}
+iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:default)
+{:ok, :default}
-iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:traditional)
-{:ok, :traditional}
+iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:traditional)
+{:ok, :traditional}
-iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:latn)
-{
+iex> Bonfire.Common.Localise.Cldr.validate_number_system_type(:latn)
+{
:error,
- {Cldr.UnknownNumberSystemTypeError, "The number system type :latn is unknown"}
-}
+ {Cldr.UnknownNumberSystemTypeError, "The number system type :latn is unknown"}
+}
-iex> Bonfire.Common.Localise.Cldr.validate_number_system_type("bork")
-{
+iex> Bonfire.Common.Localise.Cldr.validate_number_system_type("bork")
+{
:error,
- {Cldr.UnknownNumberSystemTypeError, "The number system type \"bork\" is invalid"}
-}
+ {Cldr.UnknownNumberSystemTypeError, "The number system type \"bork\" is invalid"}
+}
diff --git a/Bonfire.Common.Localise.Gettext.Helpers.html b/Bonfire.Common.Localise.Gettext.Helpers.html
index b8d3ab953a4..f17d821e22b 100644
--- a/Bonfire.Common.Localise.Gettext.Helpers.html
+++ b/Bonfire.Common.Localise.Gettext.Helpers.html
@@ -143,9 +143,9 @@
# Simple translation
usage:
- <%= l("Hello") %>
- <%= l("Hello %{name}", name: "Bookchin") %>
- <%= l("Hi", [], "test context") %>
+ <%= l("Hello") %>
+ <%= l("Hello %{name}", name: "Bookchin") %>
+ <%= l("Hi", [], "test context") %>
output:
@@ -157,8 +157,8 @@
# Plural translation
usage:
- <%= lp("Hi friend", "Hi friends", 2) %>
- <%= lp("Hiya %{user_or_users}", "Hiyas %{user_or_users}", 1, [user_or_users: "Bookchin"], "test context") %>
+ <%= lp("Hi friend", "Hi friends", 2) %>
+ <%= lp("Hiya %{user_or_users}", "Hiyas %{user_or_users}", 1, [user_or_users: "Bookchin"], "test context") %>
output:
Hi friends
diff --git a/Bonfire.Common.Localise.Gettext.Plural.html b/Bonfire.Common.Localise.Gettext.Plural.html
index cee5552da75..e8d83cb5ff7 100644
--- a/Bonfire.Common.Localise.Gettext.Plural.html
+++ b/Bonfire.Common.Localise.Gettext.Plural.html
@@ -221,10 +221,10 @@ nplurals(locale_name)
Examples
-iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("pl")
+iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("pl")
4
-iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("en")
+iex> Bonfire.Common.Localise.Gettext.Plural.nplurals("en")
2
@@ -262,28 +262,28 @@ plural(locale, n)
Examples
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 1)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 1)
0
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 2)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 2)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 5)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 5)
2
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("pl", 112)
2
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 1)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 1)
0
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 2)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 2)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en", 112)
1
-iex> Bonfire.Common.Localise.Gettext.Plural.plural("en_GB", 112)
+iex> Bonfire.Common.Localise.Gettext.Plural.plural("en_GB", 112)
1
diff --git a/Bonfire.Common.Repo.Filter.html b/Bonfire.Common.Repo.Filter.html
index d8066ccd1cf..3e446234276 100644
--- a/Bonfire.Common.Repo.Filter.html
+++ b/Bonfire.Common.Repo.Filter.html
@@ -137,14 +137,14 @@
-query_filter
brings convenience and shortens the boilterplate of ecto queries
Common filters available include:
preload
- Preloads fields onto the query resultsstart_date
- Query for items inserted after this dateend_date
- Query for items inserted before this datebefore
- Get items with IDs before this valueafter
- Get items with IDs after this valueids
- Get items with a list of idsfirst
- Gets the first n itemslast
- Gets the last n itemslimit
- Gets the first n itemsoffset
- Offsets limit by n itemssearch
- Warning: This requires schemas using this to have a &by_search(query, val)
function
You are also able to filter on any natural field of a model, as well as use
- gte/gt
- lte/lt
- like/ilike
- is_nil/not(is_nil)
query_filter(User, %{name: %{ilike: "steve"}})
-query_filter(User, %{name: %{ilike: "steve"}}, :last_name, :asc)
-query_filter(User, %{name: %{age: %{gte: 18, lte: 30}}})
-query_filter(User, %{name: %{is_banned: %{!=: nil}}})
-query_filter(User, %{name: %{is_banned: %{==: nil}}})
-
-my_query = query_filter(User, %{name: "Billy"})
-query_filter(my_query, %{last_name: "Joe"})
+query_filter
brings convenience and shortens the boilterplate of ecto queries
Common filters available include:
preload
- Preloads fields onto the query resultsstart_date
- Query for items inserted after this dateend_date
- Query for items inserted before this datebefore
- Get items with IDs before this valueafter
- Get items with IDs after this valueids
- Get items with a list of idsfirst
- Gets the first n itemslast
- Gets the last n itemslimit
- Gets the first n itemsoffset
- Offsets limit by n itemssearch
- Warning: This requires schemas using this to have a &by_search(query, val)
function
You are also able to filter on any natural field of a model, as well as use
- gte/gt
- lte/lt
- like/ilike
- is_nil/not(is_nil)
query_filter(User, %{name: %{ilike: "steve"}})
+query_filter(User, %{name: %{ilike: "steve"}}, :last_name, :asc)
+query_filter(User, %{name: %{age: %{gte: 18, lte: 30}}})
+query_filter(User, %{name: %{is_banned: %{!=: nil}}})
+query_filter(User, %{name: %{is_banned: %{==: nil}}})
+
+my_query = query_filter(User, %{name: "Billy"})
+query_filter(my_query, %{last_name: "Joe"})
diff --git a/Bonfire.Common.Test.Interactive.html b/Bonfire.Common.Test.Interactive.html
index 336aa7b87d6..604f2de6d58 100644
--- a/Bonfire.Common.Test.Interactive.html
+++ b/Bonfire.Common.Test.Interactive.html
@@ -141,11 +141,11 @@
fcwatch | mix test --stale --listen-on-stdin
to watch for
code changes and run stale tests, but with more control and
without the starting time penalty.
Note that watching requires fswatch on your system.
-Eg on Mac run brew install fswatch
.
To use it, in your project's .iex
file add:
unless GenServer.whereis(Bonfire.Common.Test.Interactive) do
- {:ok, pid} = Bonfire.Common.Test.Interactive.start_link()
+Eg on Mac run brew install fswatch
.To use it, in your project's .iex
file add:
unless GenServer.whereis(Bonfire.Common.Test.Interactive) do
+ {:ok, pid} = Bonfire.Common.Test.Interactive.start_link()
# Process will not exit when the iex goes out
- Process.unlink(pid)
-end
+ Process.unlink(pid)
+end
import Bonfire.Common.Test.Interactive.Helpers
Then to call iex
and run tests just do:
MIX_ENV=test iex -S mix
The Bonfire.Common.Test.Interactive.Helpers
allows to call f
and s
and a
to run failed, stale and all tests respectively.
You can call w
to watch tests and uw
to unwatch.
diff --git a/Bonfire.Data.Assort.Ranked.html b/Bonfire.Data.Assort.Ranked.html
index 800da5cb544..c90eb845d41 100644
--- a/Bonfire.Data.Assort.Ranked.html
+++ b/Bonfire.Data.Assort.Ranked.html
@@ -137,15 +137,15 @@
-A reusable table to link child or related items and also rank sibling items.
Usage (for global ranking, otherwise you should specify scope):
{:ok, first} = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH48ZZD08ADBHQ260KYJHW"}) |> repo().insert
-second = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH0N3YPBS5MNNAEAEVV54J"}) |> repo().insert
+A reusable table to link child or related items and also rank sibling items.
Usage (for global ranking, otherwise you should specify scope):
{:ok, first} = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH48ZZD08ADBHQ260KYJHW"}) |> repo().insert
+second = Bonfire.Data.Assort.Ranked.changeset(%{item_id: "01FGTH0N3YPBS5MNNAEAEVV54J"}) |> repo().insert
import Ecto.Query
-Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
+Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
-first |> Bonfire.Data.Assort.Ranked.changeset(%{rank_set: :last}) |> repo().update
+first |> Bonfire.Data.Assort.Ranked.changeset(%{rank_set: :last}) |> repo().update
-Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
+Bonfire.Data.Assort.Ranked |> order_by(:rank) |> repo().all
diff --git a/Bonfire.Federate.ActivityPub.FederationModules.html b/Bonfire.Federate.ActivityPub.FederationModules.html
index 8ea93a74f57..f089fc3de39 100644
--- a/Bonfire.Federate.ActivityPub.FederationModules.html
+++ b/Bonfire.Federate.ActivityPub.FederationModules.html
@@ -139,12 +139,12 @@
A automatically-generated global list of federation modules which can queried by activity and/or object type.
To add a module to this list, you should declare @behaviour Bonfire.Federate.ActivityPub.FederationModules
in it and define a federation_module/0
function which returns a list of object and/or activity types which that module handles.
Example:
@behaviour Bonfire.Federate.ActivityPub.FederationModules
def federation_module,
- do: [
+ do: [
"Announce",
- {"Create", "Announce"},
- {"Undo", "Announce"},
- {"Delete", "Announce"}
- ]
You should also then implement these two functions:
- for outgoing federation:
ap_publish_activity(subject_struct, verb, object_struct)
- for incoming federation:
ap_receive_activity(subject_struct, activity_json, object_json)
+
{"Create", "Announce"},
+ {"Undo", "Announce"},
+ {"Delete", "Announce"}
+ ]
You should also then implement these two functions:
- for outgoing federation:
ap_publish_activity(subject_struct, verb, object_struct)
- for incoming federation:
ap_receive_activity(subject_struct, activity_json, object_json)
diff --git a/Bonfire.Files.ResponsiveImage.html b/Bonfire.Files.ResponsiveImage.html
index 79d4769b661..f3b1bcf5400 100644
--- a/Bonfire.Files.ResponsiveImage.html
+++ b/Bonfire.Files.ResponsiveImage.html
@@ -141,12 +141,12 @@
~H(<img src={compile_src("input.jpg", 300)} />)
or
-~H(<img srcset={compile_srcset("input.jpg", [300, 600, 900])} src={...} sizes="50vw" />)
+~H(<img srcset={compile_srcset("input.jpg", [300, 600, 900])} src={...} sizes="50vw" />)
or for paths only known at runtime:
~H(<img src={src(my_image, 300)} />)
or
-~H(<img srcset={srcset(my_image, [300, 600, 900])} src={...} sizes="50vw" />)
+~H(<img srcset={srcset(my_image, [300, 600, 900])} src={...} sizes="50vw" />)
diff --git a/Bonfire.Files.html b/Bonfire.Files.html
index e6c9e2b4278..ea0aa542278 100644
--- a/Bonfire.Files.html
+++ b/Bonfire.Files.html
@@ -141,10 +141,10 @@
your own - a Bonfire.Files.Definition
is an extension of Waffle.Definition
,
however the allowed_media_types/0
and max_file_size/0
callback are added,
with which you need to define what media types are accepted for these types of uploads.
-(You can also return :all
to accept all media types).
To use the uploader:
iex> {:ok, media} = Bonfire.Files.upload(MyUploader, context, %{path: "./150.png"})
+(You can also return :all
to accept all media types).To use the uploader:
iex> {:ok, media} = Bonfire.Files.upload(MyUploader, context, %{path: "./150.png"})
iex> media.media_type
"image/png"
-iex> Bonfire.Files.remote_url(MyUploader, media)
+iex> Bonfire.Files.remote_url(MyUploader, media)
"/uploads/my/01F3AY6JV30G06BY4DR9BTW5EH"
diff --git a/Bonfire.Me.Accounts.SecondFactors.html b/Bonfire.Me.Accounts.SecondFactors.html
index 5b94b7ebcca..46cebef207f 100644
--- a/Bonfire.Me.Accounts.SecondFactors.html
+++ b/Bonfire.Me.Accounts.SecondFactors.html
@@ -301,8 +301,8 @@ changeset(totp \\ %AuthSecondFactor{}, attr
Examples
-iex> changeset(%AuthSecondFactor{secret: <<...>>}, code: "123456")
-%Ecto.Changeset{data: %AuthSecondFactor{}}
+iex> changeset(%AuthSecondFactor{secret: <<...>>}, code: "123456")
+%Ecto.Changeset{data: %AuthSecondFactor{}}
diff --git a/Bonfire.UI.Common.SmartInputModule.html b/Bonfire.UI.Common.SmartInputModule.html
index 865ed9869c8..eba5228dcdb 100644
--- a/Bonfire.UI.Common.SmartInputModule.html
+++ b/Bonfire.UI.Common.SmartInputModule.html
@@ -138,9 +138,9 @@
Find a smart input module via the object type(s) it can create, or vice versa. Backed by a global cache of known smart input modules.
To add a module to this list, you should declare @behaviour Bonfire.UI.Common.SmartInputModule
in it and define a smart_input_module/0
function which returns a list of object types that it can create.
Example:
@behaviour Bonfire.UI.Common.SmartInputModule
-def smart_input_module, do: [:page, Bonfire.Pages.Page]
You can then open the smart input composer / object creator using that declared type, for example:
<Bonfire.UI.Common.SmartInputButtonLive
- create_object_type={:page}
- prompt={l("New page")}
+def smart_input_module, do: [:page, Bonfire.Pages.Page]
You can then open the smart input composer / object creator using that declared type, for example:
<Bonfire.UI.Common.SmartInputButtonLive
+ create_object_type={:page}
+ prompt={l("New page")}
icon="mdi:pencil"
/>
diff --git a/EctoSparkles.DataMigration.html b/EctoSparkles.DataMigration.html
index 58bc85e238d..66c95ddc476 100644
--- a/EctoSparkles.DataMigration.html
+++ b/EctoSparkles.DataMigration.html
@@ -137,36 +137,36 @@
-A behaviour implemented by our data migrations (generally backfills).
Based on A microframework for backfill migrations in Elixir's Ecto, in turn based on David Bernheisel's template for deterministic backfills.
A data migration using this behaviour may look like this (which you can put simply put in Ecto migrations, eg. priv/repo/migrations/priv/repo/migrations/20231019004944_data_onboarding_step.exs
):
defmodule MyApp.Repo.Migrations.BackfillOnboardingStep do
+A behaviour implemented by our data migrations (generally backfills).
Based on A microframework for backfill migrations in Elixir's Ecto, in turn based on David Bernheisel's template for deterministic backfills.
A data migration using this behaviour may look like this (which you can put simply put in Ecto migrations, eg. priv/repo/migrations/priv/repo/migrations/20231019004944_data_onboarding_step.exs
):
defmodule MyApp.Repo.Migrations.BackfillOnboardingStep do
alias EctoSparkles.DataMigration
use DataMigration
@impl DataMigration
- def base_query do
+ def base_query do
# NOTE: This works in cases where:
# 1. The data can be queried with a condition that not longer applies after the migration ran, so you can repeatedly query the data and update the data until the query result is empty. For example, if a column is currently null and will be updated to not be null, then you can query for the null records and pick up where you left off.
# 2. The migration is written in such a way that it can be ran several times on the same data without causing data loss or duplication (or crashing).
- from(u in "users", # Notice how we do not use Ecto schemas here.
- where: is_nil(u.onboarding_step),
- select: %{id: u.id}
- )
- end
+ from(u in "users", # Notice how we do not use Ecto schemas here.
+ where: is_nil(u.onboarding_step),
+ select: %{id: u.id}
+ )
+ end
@impl DataMigration
- def config do
- %DataMigration.Config{batch_size: 100, throttle_ms: 1_000, repo: MyApp.Repo}
- end
+ def config do
+ %DataMigration.Config{batch_size: 100, throttle_ms: 1_000, repo: MyApp.Repo}
+ end
@impl DataMigration
- def migrate(results) do
- Enum.each(results, fn %{id: user_id} ->
+ def migrate(results) do
+ Enum.each(results, fn %{id: user_id} ->
# hooks into a context module, which is more likely to be kept up to date as the app evolves, to avoid having to update old migrations
user_id
- |> MyApp.Users.set_onboarding_step!()
- end)
- end
-end
+ |> MyApp.Users.set_onboarding_step!()
+ end)
+ end
+end
diff --git a/EctoSparkles.SanitiseStrings.html b/EctoSparkles.SanitiseStrings.html
index 777581646c0..d5e61a9f42d 100644
--- a/EctoSparkles.SanitiseStrings.html
+++ b/EctoSparkles.SanitiseStrings.html
@@ -269,26 +269,26 @@ strip_all_tags(changeset, opts \\ [])
Examples
-iex> attrs = %{string_field: "<script>Bad</script>"}
+iex> attrs = %{string_field: "<script>Bad</script>"}
iex> result_changeset =
...> attrs
-...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.strip_all_tags()
+...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.strip_all_tags()
iex> result_changeset.changes
-%{string_field: "Bad"}
Fields can be exempted from sanitization via the :except
option.
iex> attrs = %{string_field: "<script>Bad</script>"}
+%{string_field: "Bad"}
Fields can be exempted from sanitization via the :except
option.
iex> attrs = %{string_field: "<script>Bad</script>"}
iex> result_changeset =
...> attrs
-...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.strip_all_tags(except: [:string_field])
+...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.strip_all_tags(except: [:string_field])
iex> result_changeset.changes
-%{string_field: "<script>Bad</script>"}
+
%{string_field: "<script>Bad</script>"}
You can also specify a specific scrubber (by passing a function as reference):
-
ies> attrs
...> |> FakeEctoSchema.changeset()
-...> |> EctoSparkles.SanitiseStrings.sanitise_strings(scrubber: HtmlSanitizeEx.Scrubber.html5/1)
+ies> attrs
...> |> FakeEctoSchema.changeset()
+...> |> EctoSparkles.SanitiseStrings.sanitise_strings(scrubber: HtmlSanitizeEx.Scrubber.html5/1)
diff --git a/EctoSparkles.html b/EctoSparkles.html
index f566b276267..7cf9718a698 100644
--- a/EctoSparkles.html
+++ b/EctoSparkles.html
@@ -222,11 +222,11 @@ join_preload(query, associations)
import Ecto.Query
Invoice
-|> join(:left, [i], assoc(i, :customer), as: :customer)
-|> join(:left, [i, c], assoc(c, :account), as: :account)
-|> join(:left, [i], assoc(i, :lines), as: :lines)
-|> preload([lines: v, customers: c, account: a], lines: v, customer: {c, [a: account]})
-|> Repo.all()
+
|> join(:left, [i], assoc(i, :customer), as: :customer)
+|> join(:left, [i, c], assoc(c, :account), as: :account)
+|> join(:left, [i], assoc(i, :lines), as: :lines)
+|> preload([lines: v, customers: c, account: a], lines: v, customer: {c, [a: account]})
+|> Repo.all()
@@ -234,9 +234,9 @@ join_preload(query, associations)
import EctoSparkles
Invoice
-|> join_preload([:customer, :account])
-|> join_preload([:lines])
-|> Repo.all()
+|> join_preload([:customer, :account])
+|> join_preload([:lines])
+|> Repo.all()
@@ -262,13 +262,13 @@ proload(query, qual \\ :left, associations)
-AKA join_preload++
. It's more powerful, but it does it with more (and different!) syntax.
e.g.
proload(query, activity: [
+AKA join_preload++
. It's more powerful, but it does it with more (and different!) syntax.
e.g.
proload(query, activity: [
:verb, :boost_count, :like_count, :replied,
# relations under object will have their aliases prefixed with object_, i.e.
# :object_message, :object_post, :object_post_content
# the original names will still be used for the associations.
- object: {"object_", [:message, :post, :post_content]}
-])
+ object: {"object_", [:message, :post, :post_content]}
+])
diff --git a/Exto.html b/Exto.html
index 44c8d563e0f..8a95be4577d 100644
--- a/Exto.html
+++ b/Exto.html
@@ -199,35 +199,35 @@ flex_schema(otp_app)
Adds additional associations dynamically from app config.
Reads config for the given OTP application, under the name of the
current module. Each key maps to an Ecto.Schema function:
belongs_to
field
has_many
has_one
many_to_many
Each of these keys should map to a keyword list where the key is the
-name of the field or association and the value is one of:
- A type
- A tuple of type and options (keyword list)
Example Schema:
defmodule My.Schema do
+name of the field or association and the value is one of:- A type
- A tuple of type and options (keyword list)
Example Schema:
defmodule My.Schema do
use Ecto.Schema
- import Exto, only: [flex_schema: 1]
+ import Exto, only: [flex_schema: 1]
- schema "my_table" do
+ schema "my_table" do
field :name, :string # just normal schema things
- flex_schema(:my_app) # boom! give me the stuff
- end
-end
Example configuration:
config :my_app, My.Schema,
- belongs_to: [
+ flex_schema(:my_app) # boom! give me the stuff
+ end
+end
Example configuration:
config :my_app, My.Schema,
+ belongs_to: [
foo: Foo, # belongs_to :foo, Foo
- bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
- ],
- field: [
+ bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
+ ],
+ field: [
foo: :string, # field :foo, :string
- bar: {:integer, default: 4}, # field :foo, :integer, default: 4
- ],
- has_one: [
+ bar: {:integer, default: 4}, # field :foo, :integer, default: 4
+ ],
+ has_one: [
foo: Foo, # has_one :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
- ]
- has_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
+ ]
+ has_many: [
foo: Foo, # has_many :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
- ]
- many_to_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
+ ]
+ many_to_many: [
foo: Foo, # many_to_many :foo, Foo
- bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
- ]
This one won't work very well because we define foo
and bar
5
+
bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
+ ]
This one won't work very well because we define foo
and bar
5
times each, but I think you get the point.
Reading of configuration is done during compile time. The relations
will be baked in during compilation, thus:
- Do not expect this to work in runtime config.
- You will need to rebuild all dependencies which use this macro
when you change their configuration.
diff --git a/Mix.Tasks.Bonfire.Account.New.html b/Mix.Tasks.Bonfire.Account.New.html
index e9606d5e5b0..069caaad71f 100644
--- a/Mix.Tasks.Bonfire.Account.New.html
+++ b/Mix.Tasks.Bonfire.Account.New.html
@@ -143,7 +143,7 @@
Usage
-mix bonfire.account.new [email@address]
You will be prompted for a password and an email if it was not provided.
+mix bonfire.account.new [email@address]
You will be prompted for a password and an email if it was not provided.
diff --git a/Mix.Tasks.Bonfire.Localise.Extract.html b/Mix.Tasks.Bonfire.Localise.Extract.html
index a911ff3c625..9d8a2fee7b6 100644
--- a/Mix.Tasks.Bonfire.Localise.Extract.html
+++ b/Mix.Tasks.Bonfire.Localise.Extract.html
@@ -137,7 +137,7 @@
-Extracts translations by recompiling the Elixir source code.
mix gettext.extract [OPTIONS]
Translations are extracted into POT (Portable Object Template) files (with a
+
Extracts translations by recompiling the Elixir source code.
mix gettext.extract [OPTIONS]
Translations are extracted into POT (Portable Object Template) files (with a
.pot
extension). The location of these files is determined by the :otp_app
and :priv
options given by Gettext modules when they call use Gettext
. One
POT file is generated for each translation domain.
It is possible to give the --merge
option to perform merging
diff --git a/Mix.Tasks.Bonfire.Secrets.html b/Mix.Tasks.Bonfire.Secrets.html
index 8ef0eb55cd8..d71bbc4c310 100644
--- a/Mix.Tasks.Bonfire.Secrets.html
+++ b/Mix.Tasks.Bonfire.Secrets.html
@@ -137,7 +137,7 @@
-Generates secrets and prints to the terminal.
mix bonfire.secrets [length]
By default, it generates keys 64 characters long.
+
Generates secrets and prints to the terminal.
mix bonfire.secrets [length]
By default, it generates keys 64 characters long.
The minimum value for length
is 32.
diff --git a/Needle.Mixin.html b/Needle.Mixin.html
index c0924aba9b6..4b80308a8d0 100644
--- a/Needle.Mixin.html
+++ b/Needle.Mixin.html
@@ -151,16 +151,16 @@
Declaring a mixin table type
-defmodule My.Mixin do
+defmodule My.Mixin do
use Needle.Mixin,
otp_app: :my_app,
source: "postgres_table_name"
- mixin_schema do
+ mixin_schema do
field :is_awesome, :boolean
- end
-end
+ end
+end
diff --git a/Needle.Pointable.html b/Needle.Pointable.html
index fd3991d1dc3..250bec67d7f 100644
--- a/Needle.Pointable.html
+++ b/Needle.Pointable.html
@@ -148,9 +148,9 @@
source: "my_table", # default name of table in database
table_id: "01EBTVSZJ6X02J01R1XWWPWGZW" # unique ULID to identify table
-pointable_schema do
+pointable_schema do
# ... fields go here, if any
-end
+
end
diff --git a/Needle.Virtual.html b/Needle.Virtual.html
index ba55300599b..bae17724488 100644
--- a/Needle.Virtual.html
+++ b/Needle.Virtual.html
@@ -151,9 +151,9 @@
source: "my_table", # default name of view in database
table_id: "01EBTVSZJ6X02J01R1XWWPWGZW" # valid ULID to identify virtual
-virtual_schema do
+virtual_schema do
# ... `has_one`, `has_many`, or *virtual* fields ONLY go here.
-end
defmodule MyApp.Repo do
+defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator
-end
+
end
defmodule MyApp.Repo do
+defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
use Paginator,
limit: 10, # sets the default limit to 10
maximum_limit: 100, # sets the maximum limit to 100
include_total_count: true, # include total count by default
total_count_primary_key_field: :uuid # sets the total_count_primary_key_field to uuid for calculate total_count
-end
Note that these values can be still be overriden when paginate/3
is called.
+
end
Note that these values can be still be overriden when paginate/3
is called.
If you wish to avoid use of macros or you wish to use a different name for -the pagination function you can define your own function like so:
defmodule MyApp.Repo do
+the pagination function you can define your own function like so:defmodule MyApp.Repo do
use Ecto.Repo, otp_app: :my_app
- def my_paginate_function(queryable, opts \ [], repo_opts \ []) do
- defaults = [limit: 10] # Default options of your choice here
- opts = Keyword.merge(defaults, opts)
- Paginator.paginate(queryable, opts, __MODULE__, repo_opts)
- end
-end
+ def my_paginate_function(queryable, opts \ [], repo_opts \ []) do
+ defaults = [limit: 10] # Default options of your choice here
+ opts = Keyword.merge(defaults, opts)
+ Paginator.paginate(queryable, opts, __MODULE__, repo_opts)
+ end
+end
@@ -317,36 +317,36 @@ query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id], select: p)
+query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id], select: p)
-Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
+
Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
query = from(p in Post, order_by: [asc: p.inserted_at, desc: p.id], select: p)
+query = from(p in Post, order_by: [asc: p.inserted_at, desc: p.id], select: p)
-Repo.paginate(query, cursor_fields: [inserted_at: :asc, id: :desc], limit: 50)
+
Repo.paginate(query, cursor_fields: [inserted_at: :asc, id: :desc], limit: 50)
from(
+from(
p in Post,
as: :posts,
- join: a in assoc(p, :author),
+ join: a in assoc(p, :author),
as: :author,
- preload: [author: a],
+ preload: [author: a],
select: p,
- order_by: [
- {:asc, a.name},
- {:asc, p.id}
- ]
-)
+ order_by: [
+ {:asc, a.name},
+ {:asc, p.id}
+ ]
+)
-Repo.paginate(query, cursor_fields: [{{:author, :name}, :asc}, id: :asc], limit: 50)
When sorting on columns in joined tables it is necessary to use named bindings. In
+
Repo.paginate(query, cursor_fields: [{{:author, :name}, :asc}, id: :asc], limit: 50)
When sorting on columns in joined tables it is necessary to use named bindings. In
this case we name it author
. In the cursor_fields
we refer to this named binding
and its column name.
To build the cursor Paginator uses the returned Ecto.Schema. When using a joined column the returned Ecto.Schema won't have the value of the joined column @@ -361,32 +361,32 @@
from(
+from(
p in Post,
as: :posts,
- join: a in assoc(p, :author),
+ join: a in assoc(p, :author),
as: :author,
- join: c in assoc(a, :company),
+ join: c in assoc(a, :company),
as: :company,
- preload: [author: a],
+ preload: [author: a],
select: p,
- order_by: [
- {:asc, a.name},
- {:asc, p.id}
- ]
-)
-
-Repo.paginate(query,
- cursor_fields: [{{:company, :name}, :asc}, id: :asc],
- fetch_cursor_value_fun: fn
- post, {{:company, name}, _} ->
+ order_by: [
+ {:asc, a.name},
+ {:asc, p.id}
+ ]
+)
+
+Repo.paginate(query,
+ cursor_fields: [{{:company, :name}, :asc}, id: :asc],
+ fetch_cursor_value_fun: fn
+ post, {{:company, name}, _} ->
post.author.company.name
post, field ->
- Paginator.default_fetch_cursor_value(post, field)
- end,
+ Paginator.default_fetch_cursor_value(post, field)
+ end,
limit: 50
-)
+)
@@ -441,10 +441,10 @@ iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1}, [:id])
+iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1}, [:id])
"g3QAAAABZAACaWRhAQ=="
-iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1, name: "Alice"}, [id: :asc, name: :desc])
+iex> Paginator.cursor_for_record(%Paginator.Customer{id: 1, name: "Alice"}, [id: :asc, name: :desc])
"g3QAAAACZAACaWRhAWQABG5hbWVtAAAABUFsaWNl"
@@ -483,10 +483,10 @@ default_fetch_cursor_value(schema, field)
Example
-iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1}, :id)
+iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1}, :id)
1
-iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1, address: %Paginator.Address{city: "London"}}, {:address, :city})
+iex> Paginator.default_fetch_cursor_value(%Paginator.Customer{id: 1, address: %Paginator.Address{city: "London"}}, {:address, :city})
"London"
diff --git a/Voodoo.html b/Voodoo.html
index ecc70a4c77a..ed7f57c90c6 100644
--- a/Voodoo.html
+++ b/Voodoo.html
@@ -206,14 +206,14 @@ def_reverse_router(name, opts)
Generates a reverse router function with the given name based upon a
compiled(!) phoenix router module.
Must be used outside of the router module, or else the router won't
-be compiled yet and we won't be able to look up the routes.
Generated function wraps the existing phoenix helpers.
defmodule MyAppWeb.Router do
+be compiled yet and we won't be able to look up the routes.Generated function wraps the existing phoenix helpers.
defmodule MyAppWeb.Router do
use MyAppWeb, :router
# ...
-end
-defmodule MyAppWeb.Router.Reverse do
- import Voodoo, only: [def_reverse_router: 2]
+end
+defmodule MyAppWeb.Router.Reverse do
+ import Voodoo, only: [def_reverse_router: 2]
def_reverse_router :path, for: MyAppWeb.Router
-end
+end
diff --git a/architecture.html b/architecture.html
index b4bc6ea8ddf..2258bb47f2c 100644
--- a/architecture.html
+++ b/architecture.html
@@ -164,9 +164,9 @@
Code Structure
-The code is broadly composed namespaces such as these, many of which are packaged as "extensions" which live in separate git repositories, which are included in the app by way of mix dependencies:
Bonfire.*
- Core application logic (very little code).Bonfire.*.*
- Bonfire extensions (eg Bonfire.Posts
) containing mostly context modules, APIs, and routesBonfire.Data.*
- Extensions containing database schemas and migrations Bonfire.UI.*
- UI component extensionsBonfire.*.*.LiveHandler
- Backend logic to handle events in the frontendBonfire.Editor.*
(pluggable text editors, eg. CKEditor for WYSIWYG markdown input)Bonfire.GraphQL.*
- Optional GraphQL APIBonfire.Federate.*
- Optional Federation hooksActivityPub
- ActivityPub S2S models, logic and various helper modules ActivityPub.Web
- ActivityPub S2S REST endpoints, activity ingestion and push federation facilities ValueFlows.*
- economic extensions implementing the ValueFlows vocabulary
Contexts are were we put any core logic. A context often is circumscribed to providing logic for a particular object type (e. g. Bonfire.Posts
implements Bonfire.Data.Social.Post
).
All Bonfire objects use an ULID as their primary key. We use the Needle
library (with extra logic in Bonfire.Common.Needles
) to reference any object by its primary key without knowing what type it is beforehand. This is very useful as it allows for example following or liking many different types of objects (as opposed to say only a user or a post) and this approach allows us to store the context of the like/follow by only storing its primary key (see Bonfire.Data.Social.Follow
) for an example.
Context modules usually have one/2
, many/2
, and many_paginated/1
functions for fetching objects, which in turn call a query/2
function. These take a keyword list as filters (and an optional opts
argument) allowing objects to be fetched by arbitrary criteria.
Examples:
Users.one(username: "bob") # Fetching by username
-Posts.many_paginated(by: "01E9TQP93S8XFSV2ZATX1FQ528") # List a page of posts by its author
-EconomicResources.many(deleted: true) # List any deleted resources
Context modules also have functions for creating, updating and deleting objects, as well as hooks for federating or indexing in the search engine.
Here is an incomplete sample of some of current extensions and modules:
Bonfire.Me.Accounts
(for managing and querying local user accounts)Bonfire.Me.Users
(for managing and querying both local and remote user identities and profiles)Bonfire.Boundaries
(for managing and querying circles, ACLs, permissions...)Bonfire.Social.FeedActivities
, Bonfire.Social.Feeds
and Bonfire.Social.Activities
(for managing and querying activities and feeds)Bonfire.Posts
and Bonfire.Social.PostContents
(for managing and querying posts)Bonfire.Social.Threads
(for managing and querying threads and comments)Bonfire.Social.Flags
(for managing and querying flags)Bonfire.Social.Graph.Follows
(for managing and querying follows)Bonfire.Classify
(for managing and querying categories, topics, and the like)Bonfire.Tag
(for managing and querying tags and mentions)Bonfire.Geolocate
(for managing and querying locations and geographical coordinates)Bonfire.Quantify
(for managing and querying units and measures)
Additional extensions, libraries, and modules
Bonfire.Common
and Bonfire.Common.Utils
(stuff that gets used everywhere)Bonfire.Application
(OTP application)Bonfire.Me.Characters
(a shared abstraction over users, organisations, categories, and other objects that need to have feeds and behave as an actor in ActivityPub land)Bonfire.Federate.ActivityPub
and ActivityPub
(ActivityPub integration)Bonfire.Search
(local search indexing and search API, powered by Meili)Bonfire.Mailer
, Bonfire.Me.Mails
, and Bamboo
(for rendering and sending emails)Bonfire.Files
, Waffle
, TreeMagic
and TwinkleStar
(for managing uploaded content)Bonfire.GraphQL
(GraphQL API abstractions)Queery
and Bonfire.Repo.Query
(Helpers for making queries on the database)Bonfire.Repo
(Ecto repository)Exto
(to extend DB schemas in config, especially useful for adding associations)AbsintheClient
(for querying the API from within the server)
+
The code is broadly composed namespaces such as these, many of which are packaged as "extensions" which live in separate git repositories, which are included in the app by way of mix dependencies:
Bonfire.*
- Core application logic (very little code).Bonfire.*.*
- Bonfire extensions (eg Bonfire.Posts
) containing mostly context modules, APIs, and routesBonfire.Data.*
- Extensions containing database schemas and migrations Bonfire.UI.*
- UI component extensionsBonfire.*.*.LiveHandler
- Backend logic to handle events in the frontendBonfire.Editor.*
(pluggable text editors, eg. CKEditor for WYSIWYG markdown input)Bonfire.GraphQL.*
- Optional GraphQL APIBonfire.Federate.*
- Optional Federation hooksActivityPub
- ActivityPub S2S models, logic and various helper modules ActivityPub.Web
- ActivityPub S2S REST endpoints, activity ingestion and push federation facilities ValueFlows.*
- economic extensions implementing the ValueFlows vocabulary
Contexts are were we put any core logic. A context often is circumscribed to providing logic for a particular object type (e. g. Bonfire.Posts
implements Bonfire.Data.Social.Post
).
All Bonfire objects use an ULID as their primary key. We use the Needle
library (with extra logic in Bonfire.Common.Needles
) to reference any object by its primary key without knowing what type it is beforehand. This is very useful as it allows for example following or liking many different types of objects (as opposed to say only a user or a post) and this approach allows us to store the context of the like/follow by only storing its primary key (see Bonfire.Data.Social.Follow
) for an example.
Context modules usually have one/2
, many/2
, and many_paginated/1
functions for fetching objects, which in turn call a query/2
function. These take a keyword list as filters (and an optional opts
argument) allowing objects to be fetched by arbitrary criteria.
Examples:
Users.one(username: "bob") # Fetching by username
+Posts.many_paginated(by: "01E9TQP93S8XFSV2ZATX1FQ528") # List a page of posts by its author
+EconomicResources.many(deleted: true) # List any deleted resources
Context modules also have functions for creating, updating and deleting objects, as well as hooks for federating or indexing in the search engine.
Here is an incomplete sample of some of current extensions and modules:
Bonfire.Me.Accounts
(for managing and querying local user accounts)Bonfire.Me.Users
(for managing and querying both local and remote user identities and profiles)Bonfire.Boundaries
(for managing and querying circles, ACLs, permissions...)Bonfire.Social.FeedActivities
, Bonfire.Social.Feeds
and Bonfire.Social.Activities
(for managing and querying activities and feeds)Bonfire.Posts
and Bonfire.Social.PostContents
(for managing and querying posts)Bonfire.Social.Threads
(for managing and querying threads and comments)Bonfire.Social.Flags
(for managing and querying flags)Bonfire.Social.Graph.Follows
(for managing and querying follows)Bonfire.Classify
(for managing and querying categories, topics, and the like)Bonfire.Tag
(for managing and querying tags and mentions)Bonfire.Geolocate
(for managing and querying locations and geographical coordinates)Bonfire.Quantify
(for managing and querying units and measures)
Additional extensions, libraries, and modules
Bonfire.Common
and Bonfire.Common.Utils
(stuff that gets used everywhere)Bonfire.Application
(OTP application)Bonfire.Me.Characters
(a shared abstraction over users, organisations, categories, and other objects that need to have feeds and behave as an actor in ActivityPub land)Bonfire.Federate.ActivityPub
and ActivityPub
(ActivityPub integration)Bonfire.Search
(local search indexing and search API, powered by Meili)Bonfire.Mailer
, Bonfire.Me.Mails
, and Bamboo
(for rendering and sending emails)Bonfire.Files
, Waffle
, TreeMagic
and TwinkleStar
(for managing uploaded content)Bonfire.GraphQL
(GraphQL API abstractions)Queery
and Bonfire.Repo.Query
(Helpers for making queries on the database)Bonfire.Repo
(Ecto repository)Exto
(to extend DB schemas in config, especially useful for adding associations)AbsintheClient
(for querying the API from within the server)
diff --git a/bonfire-flavoured-elixir.html b/bonfire-flavoured-elixir.html
index 41a201b0548..1cd2eef4e76 100644
--- a/bonfire-flavoured-elixir.html
+++ b/bonfire-flavoured-elixir.html
@@ -141,33 +141,33 @@
Arrows
The Elixir |> ("pipe") operator is one of the things that seems to get people excited about elixir. Probably in part because you then don't have to keep coming up with function names. Unfortunately it's kind of limiting.
-The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.
Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
+The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
use ExUnit.Case
use Arrows
- def double(x), do: x * 2
- def double_fst(x, _), do: x * 2
- def double_snd(_, x), do: x * 2
- def add_snd_thd(_, x, y), do: x + y
-
- test "|>" do
- assert 4 == (2 |> double)
- assert 4 == (2 |> double())
- assert 4 == (2 |> double(...))
- assert 8 == (2 |> double(double(...)))
- assert 4 == (2 |> double_fst(1))
- assert 4 == (2 |> double_fst(..., 1))
- assert 8 == (2 |> double_fst(double(...), 1))
- assert 4 == (2 |> double_snd(1, ...))
- assert 8 == (2 |> double_snd(1, double(...)))
- assert 3 == (2 |> add_snd_thd(1, ..., 1))
- assert 4 == (2 |> add_snd_thd(1, ..., ...))
- assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
- for x <- [:yes, 2, nil, false] do
- assert {:ok, x} == (x |> {:ok, ...})
- end
- end
-end
A few little extra features you might notice here:
- You can move the parameter into a subexpression, as in
2 |> double_fst(double(...), 1)
where double will be called before the parameter is passed to double_fst
. - You can use
...
multiple times, substituting it in multiple places. - The right hand side need not even be a function call, you can use any expression with
...
.
+
def double(x), do: x * 2
+ def double_fst(x, _), do: x * 2
+ def double_snd(_, x), do: x * 2
+ def add_snd_thd(_, x, y), do: x + y
+
+ test "|>" do
+ assert 4 == (2 |> double)
+ assert 4 == (2 |> double())
+ assert 4 == (2 |> double(...))
+ assert 8 == (2 |> double(double(...)))
+ assert 4 == (2 |> double_fst(1))
+ assert 4 == (2 |> double_fst(..., 1))
+ assert 8 == (2 |> double_fst(double(...), 1))
+ assert 4 == (2 |> double_snd(1, ...))
+ assert 8 == (2 |> double_snd(1, double(...)))
+ assert 3 == (2 |> add_snd_thd(1, ..., 1))
+ assert 4 == (2 |> add_snd_thd(1, ..., ...))
+ assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
+ for x <- [:yes, 2, nil, false] do
+ assert {:ok, x} == (x |> {:ok, ...})
+ end
+ end
+end
A few little extra features you might notice here:
- You can move the parameter into a subexpression, as in
2 |> double_fst(double(...), 1)
where double will be called before the parameter is passed to double_fst
. - You can use
...
multiple times, substituting it in multiple places. - The right hand side need not even be a function call, you can use any expression with
...
.
@@ -181,14 +181,14 @@
Untangle
provides replacements for the macros in Elixir's Logger
module and the IO.inspect
function to output code location information. The first argument will be inspect
ed and the second (where provided) will be used as a label:
iex(1)> import Untangle
Untangle
-iex(2)> debug(:no, "the answer is") # log at debug
-11:19:09.915 [debug] [iex:2] the answer is: :no
+iex(2)> debug(:no, "the answer is") # log at debug
+11:19:09.915 [debug] [iex:2] the answer is: :no
:no
-iex(3)> dump(%{a: :map}, "it") # inspect something on stdout
-[iex:3] it: %{a: :map}
-%{a: :map}
When used in a code file, the location information becomes slightly more useful, e.g.:
[lib/test_untangle.ex:15@Test.Untangle.example/2] Here's an empty list: []
You may also notice from the iex output that it returns its first argument. This makes it ideal for
-inserting into a pipeline for debugging purposes:
do_something()
-|> debug("output of do_something/0")
When you are done debugging something, the location of the debug statement is already in the output so you know where to remove it or comment it out! Bliss!
You will find the codebase uses this a lot, though the debugs are frequently commented out. Just uncomment the ones that would help you with a particular debugging task and you're off.
+
iex(3)> dump(%{a: :map}, "it") # inspect something on stdout
+[iex:3] it: %{a: :map}
+%{a: :map}
When used in a code file, the location information becomes slightly more useful, e.g.:
[lib/test_untangle.ex:15@Test.Untangle.example/2] Here's an empty list: []
You may also notice from the iex output that it returns its first argument. This makes it ideal for
+inserting into a pipeline for debugging purposes:
do_something()
+|> debug("output of do_something/0")
When you are done debugging something, the location of the debug statement is already in the output so you know where to remove it or comment it out! Bliss!
You will find the codebase uses this a lot, though the debugs are frequently commented out. Just uncomment the ones that would help you with a particular debugging task and you're off.
diff --git a/bonfire_umbrella.epub b/bonfire_umbrella.epub
index fca9b4bbb78..b542fa1a0e6 100644
Binary files a/bonfire_umbrella.epub and b/bonfire_umbrella.epub differ
diff --git a/database.html b/database.html
index 29d6967d657..162a63a3d3f 100644
--- a/database.html
+++ b/database.html
@@ -153,26 +153,26 @@
Mixins - storing data about objects
Mixins are tables which contain extra information on behalf of objects. Each object can choose to
-record or not record information for each mixin. Sample mixins include:
- user profile (containing a name, location and summary)
- post content (containing the title, summary, and/or html body of a post or message)
- created (containing the id of the object creator)
In this way, they are reusable across different object types. One mixin may (or may not) be used by any number of objects. This is mostly driven by the type of the object we are storing, but can also be driven by user input.
Mixins are just tables too! The only requirement is they have a ULID
primary key which references Needle.Pointer
. The developer of the mixin is free to put whatever other fields they want in the table, so long as they have that primary-key-as-reference (which will be automatically added for you by the mixin_schema
macro).
Here is a sample mixin definition for a user profile:
defmodule Bonfire.Data.Social.Profile do
+record or not record information for each mixin. Sample mixins include:- user profile (containing a name, location and summary)
- post content (containing the title, summary, and/or html body of a post or message)
- created (containing the id of the object creator)
In this way, they are reusable across different object types. One mixin may (or may not) be used by any number of objects. This is mostly driven by the type of the object we are storing, but can also be driven by user input.
Mixins are just tables too! The only requirement is they have a ULID
primary key which references Needle.Pointer
. The developer of the mixin is free to put whatever other fields they want in the table, so long as they have that primary-key-as-reference (which will be automatically added for you by the mixin_schema
macro).
Here is a sample mixin definition for a user profile:
defmodule Bonfire.Data.Social.Profile do
use Needle.Mixin,
otp_app: :bonfire_data_social,
source: "bonfire_data_social_profile"
- mixin_schema do
+ mixin_schema do
field :name, :string
field :summary, :string
field :website, :string
field :location, :string
- end
-end
Aside from use
ing Needle.Mixin
instead of Ecto.Schema
and calling mixin_schema
instead of
+
end
+end
Aside from use
ing Needle.Mixin
instead of Ecto.Schema
and calling mixin_schema
instead of
schema
, pretty similar to a standard Ecto schema, right?
The arguments to use Needle.Mixin
are:
otp_app
: the OTP app name to use when loading dynamic configuration, e.g. the current extension or app (required)source
: the underlying table name to use in the database
We will cover dynamic configuration later. For now, you can use the OTP app that includes the module.
Multimixins
-Multimixins are like mixins, except that where an object may have 0 or 1 of a particular mixins, an object may have any number of a particular multimixin.
For this to work, a multimixin must have a compound primary key which must contain an id
column referencing Needle.Pointer
and at least one other field which will collectively be unique.
An example multimixin is used for publishing an item to feeds:
defmodule Bonfire.Data.Social.FeedPublish do
+Multimixins are like mixins, except that where an object may have 0 or 1 of a particular mixins, an object may have any number of a particular multimixin.
For this to work, a multimixin must have a compound primary key which must contain an id
column referencing Needle.Pointer
and at least one other field which will collectively be unique.
An example multimixin is used for publishing an item to feeds:
defmodule Bonfire.Data.Social.FeedPublish do
use Needle.Mixin,
otp_app: :bonfire_data_social,
@@ -180,10 +180,10 @@
alias Needle.Pointer
- mixin_schema do
+ mixin_schema do
belongs_to :feed, Pointer, primary_key: true
- end
-end
Notice that this looks very similar to defining a mixin. Indeed, the only difference is the primary_key: true
in this line, which adds a second field to the compound primary key.
+
end
+end
Notice that this looks very similar to defining a mixin. Indeed, the only difference is the primary_key: true
in this line, which adds a second field to the compound primary key.
This results in ecto recording a compound primary key of (id, feed_id)
for the schema (the id is added for you as with regular mixins).
@@ -196,26 +196,26 @@
Picking a table id
-
The first step to declaring a type is picking a unique table ID in ULID format. You could just generate one at the terminal, but since these IDs are special, we tend to assign a synthetic ULID that are readable as words so they stand out in debug output.
For example, the ID for the Feed
table is: 1TFEEDS0NTHES0V1S0FM0RTA1S
, which can be read as "It feeds on the souls of mortals". Feel free to have a little fun coming up with them, it makes debug output a little more cheery! The rules are:
- The alphabet is Crockford's Base32.
- They must be 26 characters in length.
- The first character must be a digit in the range 0-7.
To help you with this, the Needle.ULID.synthesise!/1
method takes an alphanumeric binary and tries to return you it transliterated into a valid ULID. Example usage:
iex(1)> Needle.ULID.synthesise!("itfeedsonthesouls")
+The first step to declaring a type is picking a unique table ID in ULID format. You could just generate one at the terminal, but since these IDs are special, we tend to assign a synthetic ULID that are readable as words so they stand out in debug output.
For example, the ID for the Feed
table is: 1TFEEDS0NTHES0V1S0FM0RTA1S
, which can be read as "It feeds on the souls of mortals". Feel free to have a little fun coming up with them, it makes debug output a little more cheery! The rules are:
- The alphabet is Crockford's Base32.
- They must be 26 characters in length.
- The first character must be a digit in the range 0-7.
To help you with this, the Needle.ULID.synthesise!/1
method takes an alphanumeric binary and tries to return you it transliterated into a valid ULID. Example usage:
iex(1)> Needle.ULID.synthesise!("itfeedsonthesouls")
-11:20:28.299 [error] Too short, need 9 chars.
+11:20:28.299 [error] Too short, need 9 chars.
:ok
-iex(2)> Needle.ULID.synthesise!("itfeedsonthesoulsofmortalsandothers")
+iex(2)> Needle.ULID.synthesise!("itfeedsonthesoulsofmortalsandothers")
-11:20:31.819 [warn] Too long, chopping off last 9 chars
+11:20:31.819 [warn] Too long, chopping off last 9 chars
"1TFEEDS0NTHES0V1S0FM0RTA1S"
-iex(3)> Needle.ULID.synthesise!("itfeedsonthesoulsofmortals")
+iex(3)> Needle.ULID.synthesise!("itfeedsonthesoulsofmortals")
"1TFEEDS0NTHES0V1S0FM0RTA1S"
-iex(4)> Needle.ULID.synthesise!("gtfeedsonthesoulsofmortals")
+iex(4)> Needle.ULID.synthesise!("gtfeedsonthesoulsofmortals")
-11:21:03.268 [warn] First character must be a digit in the range 0-7, replacing with 7
+11:21:03.268 [warn] First character must be a digit in the range 0-7, replacing with 7
"7TFEEDS0NTHES0V1S0FM0RTA1S"
Virtuals
-Virtuals are the simplest and most common type of object. Here's a definition of block:
defmodule Bonfire.Data.Social.Block do
+Virtuals are the simplest and most common type of object. Here's a definition of block:
defmodule Bonfire.Data.Social.Block do
use Needle.Virtual,
otp_app: :bonfire_data_social,
@@ -224,26 +224,26 @@
alias Bonfire.Data.Edges.Edge
- virtual_schema do
+ virtual_schema do
has_one :edge, Edge, foreign_key: :id
- end
-end
It should look quite similar to a mixin definition, except that we use
Needle.Virtual
this time (passing an additional table_id
argument) and we call the virtual_schema
macro.
The primary limitation of a virtual is that you cannot put extra fields into one. This also means that belongs_to
is not generally permitted because it results in adding a field. has_one
and has_many
work just fine as they do not cause the creation of fields in the schema.
This is not usually a problem, as extra fields can be put into mixins or multimixins as appropriate.
Under the hood, a virtual has a view (in this example, called bonfire_data_social_block
). It looks like a table with just an id, but it's populated with all the ids of blocks that are not deleted. When the view is inserted into, a record is created in the pointers
table for you transparently. When you delete from the view, the corresponding pointers
entry is marked deleted for you.
+
end
+end
It should look quite similar to a mixin definition, except that we use
Needle.Virtual
this time (passing an additional table_id
argument) and we call the virtual_schema
macro.
The primary limitation of a virtual is that you cannot put extra fields into one. This also means that belongs_to
is not generally permitted because it results in adding a field. has_one
and has_many
work just fine as they do not cause the creation of fields in the schema.
This is not usually a problem, as extra fields can be put into mixins or multimixins as appropriate.
Under the hood, a virtual has a view (in this example, called bonfire_data_social_block
). It looks like a table with just an id, but it's populated with all the ids of blocks that are not deleted. When the view is inserted into, a record is created in the pointers
table for you transparently. When you delete from the view, the corresponding pointers
entry is marked deleted for you.
Pointables
-The other, lesser used, type of object is called the Pointable. The major difference is that unlike the simple case of virtuals, pointables are not backed by views, but by tables.
When a record is inserted into a pointable table, a copy is made in the pointers
table for you transparently. When you delete from the table, the the corresponding pointers
entry is marked deleted for you. In these ways, they behave very much like virtuals. By having a table, however, we are free to add new fields.
Pointables pay for this flexibility by being slightly more expensive than virtuals:
- Records must be inserted into/deleted from two tables (the pointable's table and the
pointers
table). - The pointable table needs its own primary key index.
Here is a definition of a pointable type (indicating an ActivityPub activity whose type we don't recognise, stored as a JSON blob):
defmodule Bonfire.Data.Social.APActivity do
+The other, lesser used, type of object is called the Pointable. The major difference is that unlike the simple case of virtuals, pointables are not backed by views, but by tables.
When a record is inserted into a pointable table, a copy is made in the pointers
table for you transparently. When you delete from the table, the the corresponding pointers
entry is marked deleted for you. In these ways, they behave very much like virtuals. By having a table, however, we are free to add new fields.
Pointables pay for this flexibility by being slightly more expensive than virtuals:
- Records must be inserted into/deleted from two tables (the pointable's table and the
pointers
table). - The pointable table needs its own primary key index.
Here is a definition of a pointable type (indicating an ActivityPub activity whose type we don't recognise, stored as a JSON blob):
defmodule Bonfire.Data.Social.APActivity do
use Needle.Pointable,
otp_app: :bonfire_data_social,
table_id: "30NF1REAPACTTAB1ENVMBER0NE",
source: "bonfire_data_social_apactivity"
- pointable_schema do
+ pointable_schema do
field :json, :map
- end
-end
The choice of using a pointable instead of a virtual combined with one or more mixins is ultimately up to you.
+
end
+end
The choice of using a pointable instead of a virtual combined with one or more mixins is ultimately up to you.
@@ -255,37 +255,37 @@
Virtuals
-
Most virtuals are incredibly simple to migrate for:
defmodule Bonfire.Data.Social.Post.Migration do
+Most virtuals are incredibly simple to migrate for:
defmodule Bonfire.Data.Social.Post.Migration do
import Needle.Migration
alias Bonfire.Data.Social.Post
- def migrate_post(), do: migrate_virtual(Post)
+ def migrate_post(), do: migrate_virtual(Post)
-end
If you need to do more work, it can be a little trickier. Here's an example for block
, which also creates a unique index on another table:
defmodule Bonfire.Data.Social.Block.Migration do
+end
If you need to do more work, it can be a little trickier. Here's an example for block
, which also creates a unique index on another table:
defmodule Bonfire.Data.Social.Block.Migration do
import Ecto.Migration
import Needle.Migration
import Bonfire.Data.Edges.Edge.Migration
alias Bonfire.Data.Social.Block
- def migrate_block_view(), do: migrate_virtual(Block)
+ def migrate_block_view(), do: migrate_virtual(Block)
- def migrate_block_unique_index(), do: migrate_type_unique_index(Block)
+ def migrate_block_unique_index(), do: migrate_type_unique_index(Block)
- def migrate_block(dir \\ direction())
+ def migrate_block(dir \\ direction())
- def migrate_block(:up) do
- migrate_block_view()
- migrate_block_unique_index()
- end
+ def migrate_block(:up) do
+ migrate_block_view()
+ migrate_block_unique_index()
+ end
- def migrate_block(:down) do
- migrate_block_unique_index()
- migrate_block_view()
- end
+ def migrate_block(:down) do
+ migrate_block_unique_index()
+ migrate_block_view()
+ end
-end
Notice how we have to write our up
and down
versions separately to get the correct ordering of operations.
+
end
Notice how we have to write our up
and down
versions separately to get the correct ordering of operations.
@@ -293,156 +293,156 @@
As of now, pointables are a little trickier to define flexibly than virtuals because we want to
preserve the ability for the user to define extra fields in config. There are some questions about
-how useful this is in practice, so we might go for a simpler option in future.
Example:
defmodule Bonfire.Data.Social.APActivity.Migration do
+how useful this is in practice, so we might go for a simpler option in future.Example:
defmodule Bonfire.Data.Social.APActivity.Migration do
@moduledoc false
use Ecto.Migration
import Needle.Migration
alias Bonfire.Data.Social.APActivity
- defp make_apactivity_table(exprs) do
- quote do
+ defp make_apactivity_table(exprs) do
+ quote do
require Needle.Migration
- Needle.Migration.create_pointable_table(Bonfire.Data.Social.APActivity) do
+ Needle.Migration.create_pointable_table(Bonfire.Data.Social.APActivity) do
Ecto.Migration.add :json, :jsonb
- unquote_splicing(exprs)
- end
- end
- end
-
- defmacro create_apactivity_table, do: make_apactivity_table([])
- defmacro create_apactivity_table([do: body]), do: make_apactivity_table(body)
-
- def drop_apactivity_table(), do: drop_pointable_table(APActivity)
-
- defp maa(:up), do: make_apactivity_table([])
- defp maa(:down) do
- quote do: Bonfire.Data.Social.APActivity.Migration.drop_apactivity_table()
- end
-
- defmacro migrate_apactivity() do
- quote do
- if Ecto.Migration.direction() == :up,
- do: unquote(maa(:up)),
- else: unquote(maa(:down))
- end
- end
-
-end
+
unquote_splicing(exprs)
+ end
+ end
+ end
+
+ defmacro create_apactivity_table, do: make_apactivity_table([])
+ defmacro create_apactivity_table([do: body]), do: make_apactivity_table(body)
+
+ def drop_apactivity_table(), do: drop_pointable_table(APActivity)
+
+ defp maa(:up), do: make_apactivity_table([])
+ defp maa(:down) do
+ quote do: Bonfire.Data.Social.APActivity.Migration.drop_apactivity_table()
+ end
+
+ defmacro migrate_apactivity() do
+ quote do
+ if Ecto.Migration.direction() == :up,
+ do: unquote(maa(:up)),
+ else: unquote(maa(:down))
+ end
+ end
+
+end
Mixins
-Mixins look much like pointables:
defmodule Bonfire.Data.Social.Profile.Migration do
+Mixins look much like pointables:
defmodule Bonfire.Data.Social.Profile.Migration do
import Needle.Migration
alias Bonfire.Data.Social.Profile
# create_profile_table/{0,1}
- defp make_profile_table(exprs) do
- quote do
+ defp make_profile_table(exprs) do
+ quote do
require Needle.Migration
- Needle.Migration.create_mixin_table(Bonfire.Data.Social.Profile) do
+ Needle.Migration.create_mixin_table(Bonfire.Data.Social.Profile) do
Ecto.Migration.add :name, :text
Ecto.Migration.add :summary, :text
Ecto.Migration.add :website, :text
Ecto.Migration.add :location, :text
- Ecto.Migration.add :icon_id, strong_pointer(Bonfire.Files.Media)
- Ecto.Migration.add :image_id, strong_pointer(Bonfire.Files.Media)
- unquote_splicing(exprs)
- end
- end
- end
+ Ecto.Migration.add :icon_id, strong_pointer(Bonfire.Files.Media)
+ Ecto.Migration.add :image_id, strong_pointer(Bonfire.Files.Media)
+ unquote_splicing(exprs)
+ end
+ end
+ end
- defmacro create_profile_table(), do: make_profile_table([])
- defmacro create_profile_table([do: {_, _, body}]), do: make_profile_table(body)
+ defmacro create_profile_table(), do: make_profile_table([])
+ defmacro create_profile_table([do: {_, _, body}]), do: make_profile_table(body)
# drop_profile_table/0
- def drop_profile_table(), do: drop_mixin_table(Profile)
+ def drop_profile_table(), do: drop_mixin_table(Profile)
# migrate_profile/{0,1}
- defp mp(:up), do: make_profile_table([])
+ defp mp(:up), do: make_profile_table([])
- defp mp(:down) do
- quote do
- Bonfire.Data.Social.Profile.Migration.drop_profile_table()
- end
- end
+ defp mp(:down) do
+ quote do
+ Bonfire.Data.Social.Profile.Migration.drop_profile_table()
+ end
+ end
- defmacro migrate_profile() do
- quote do
- if Ecto.Migration.direction() == :up,
- do: unquote(mp(:up)),
- else: unquote(mp(:down))
- end
- end
+ defmacro migrate_profile() do
+ quote do
+ if Ecto.Migration.direction() == :up,
+ do: unquote(mp(:up)),
+ else: unquote(mp(:down))
+ end
+ end
-end
+
end
Multimixins
-Similar to mixins:
defmodule Bonfire.Data.Social.FeedPublish.Migration do
+Similar to mixins:
defmodule Bonfire.Data.Social.FeedPublish.Migration do
import Ecto.Migration
import Needle.Migration
alias Bonfire.Data.Social.FeedPublish
- @feed_publish_table FeedPublish.__schema__(:source)
+ @feed_publish_table FeedPublish.__schema__(:source)
# create_feed_publish_table/{0,1}
- defp make_feed_publish_table(exprs) do
- quote do
+ defp make_feed_publish_table(exprs) do
+ quote do
require Needle.Migration
- Needle.Migration.create_mixin_table(Bonfire.Data.Social.FeedPublish) do
+ Needle.Migration.create_mixin_table(Bonfire.Data.Social.FeedPublish) do
Ecto.Migration.add :feed_id,
- Needle.Migration.strong_pointer(), primary_key: true
- unquote_splicing(exprs)
- end
- end
- end
-
- defmacro create_feed_publish_table(), do: make_feed_publish_table([])
- defmacro create_feed_publish_table([do: {_, _, body}]), do: make_feed_publish_table(body)
-
- def drop_feed_publish_table(), do: drop_pointable_table(FeedPublish)
-
- def migrate_feed_publish_feed_index(dir \\ direction(), opts \\ [])
- def migrate_feed_publish_feed_index(:up, opts),
- do: create_if_not_exists(index(@feed_publish_table, [:feed_id], opts))
- def migrate_feed_publish_feed_index(:down, opts),
- do: drop_if_exists(index(@feed_publish_table, [:feed_id], opts))
-
- defp mf(:up) do
- quote do
- Bonfire.Data.Social.FeedPublish.Migration.create_feed_publish_table()
- Bonfire.Data.Social.FeedPublish.Migration.migrate_feed_publish_feed_index()
- end
- end
-
- defp mf(:down) do
- quote do
- Bonfire.Data.Social.FeedPublish.Migration.migrate_feed_publish_feed_index()
- Bonfire.Data.Social.FeedPublish.Migration.drop_feed_publish_table()
- end
- end
-
- defmacro migrate_feed_publish() do
- quote do
- if Ecto.Migration.direction() == :up,
- do: unquote(mf(:up)),
- else: unquote(mf(:down))
- end
- end
-
- defmacro migrate_feed_publish(dir), do: mf(dir)
-
-end
+
Needle.Migration.strong_pointer(), primary_key: true
+ unquote_splicing(exprs)
+ end
+ end
+ end
+
+ defmacro create_feed_publish_table(), do: make_feed_publish_table([])
+ defmacro create_feed_publish_table([do: {_, _, body}]), do: make_feed_publish_table(body)
+
+ def drop_feed_publish_table(), do: drop_pointable_table(FeedPublish)
+
+ def migrate_feed_publish_feed_index(dir \\ direction(), opts \\ [])
+ def migrate_feed_publish_feed_index(:up, opts),
+ do: create_if_not_exists(index(@feed_publish_table, [:feed_id], opts))
+ def migrate_feed_publish_feed_index(:down, opts),
+ do: drop_if_exists(index(@feed_publish_table, [:feed_id], opts))
+
+ defp mf(:up) do
+ quote do
+ Bonfire.Data.Social.FeedPublish.Migration.create_feed_publish_table()
+ Bonfire.Data.Social.FeedPublish.Migration.migrate_feed_publish_feed_index()
+ end
+ end
+
+ defp mf(:down) do
+ quote do
+ Bonfire.Data.Social.FeedPublish.Migration.migrate_feed_publish_feed_index()
+ Bonfire.Data.Social.FeedPublish.Migration.drop_feed_publish_table()
+ end
+ end
+
+ defmacro migrate_feed_publish() do
+ quote do
+ if Ecto.Migration.direction() == :up,
+ do: unquote(mf(:up)),
+ else: unquote(mf(:down))
+ end
+ end
+
+ defmacro migrate_feed_publish(dir), do: mf(dir)
+
+end
diff --git a/deploy.html b/deploy.html
index 9f6df2dd9c2..b54024d3fe9 100644
--- a/deploy.html
+++ b/deploy.html
@@ -184,13 +184,13 @@
Config keys you should pay special attention to:
-
The app needs these environment variables to be configured in order to work.
FLAVOUR
should reflect your chosen flavourHOSTNAME
(your domain name, eg: bonfire.example.com
)PUBLIC_PORT
(usually 443)MAIL_DOMAIN
and MAIL_KEY
and related keys to configure transactional email, for example set MAIL_BACKEND=mailgun
and sign up at Mailgun and then configure the domain name and key (you may also need to set MAIL_BASE_URI
if your domain is not setup in EU, as the default MAIL_BASE_URI
is set as https://api.eu.mailgun.net/v3
). - SMTP is supported as well, through the following env vars
MAIL_SERVER (smtp domain of the mail server)
-MAIL_DOMAIN (the bit after the @ in your email)
+The app needs these environment variables to be configured in order to work.
FLAVOUR
should reflect your chosen flavourHOSTNAME
(your domain name, eg: bonfire.example.com
)PUBLIC_PORT
(usually 443)MAIL_DOMAIN
and MAIL_KEY
and related keys to configure transactional email, for example set MAIL_BACKEND=mailgun
and sign up at Mailgun and then configure the domain name and key (you may also need to set MAIL_BASE_URI
if your domain is not setup in EU, as the default MAIL_BASE_URI
is set as https://api.eu.mailgun.net/v3
). - SMTP is supported as well, through the following env vars
MAIL_SERVER (smtp domain of the mail server)
+MAIL_DOMAIN (the bit after the @ in your email)
MAIL_USER
MAIL_PASSWORD
MAIL_FROM
-MAIL_PORT (optional)
-MAIL_SSL (optional)
UPLOADS_S3_BUCKET
and the related API key and secret for uploads. WARNING: If you want to store uploads in an object storage rather than directly on your server (which you probably want, to not run out of space), you need to configure that up front, otherwise URLs will break if you change it later. See config/runtime.exs
for extra variables to set if you're not using the default service and region (which is Scaleway Paris).
+
MAIL_PORT (optional)
+MAIL_SSL (optional)
UPLOADS_S3_BUCKET
and the related API key and secret for uploads. WARNING: If you want to store uploads in an object storage rather than directly on your server (which you probably want, to not run out of space), you need to configure that up front, otherwise URLs will break if you change it later. See config/runtime.exs
for extra variables to set if you're not using the default service and region (which is Scaleway Paris).
@@ -377,14 +377,14 @@ Dependencies
- Postgres (or Postgis) version 12 or newer
- <
Troubleshooting
-
Some common issues that may arise during deployment and our suggestions for resolving them.
WebSocket connections not establishing behind a reverse proxy
If you are running Bonfire behind your own reverse proxy (e.g. nginx), you might experience issues with WebSocket connections not establishing. WebSocket connections require specific configuration to work, in nginx the following configuration is necessary for websockets to work:
location /live/websocket {
+Some common issues that may arise during deployment and our suggestions for resolving them.
WebSocket connections not establishing behind a reverse proxy
If you are running Bonfire behind your own reverse proxy (e.g. nginx), you might experience issues with WebSocket connections not establishing. WebSocket connections require specific configuration to work, in nginx the following configuration is necessary for websockets to work:
location /live/websocket {
proxy_pass http://127.0.0.1:4000;
# these configurations are necessary to proxy WebSocket requests
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
-}
+}
diff --git a/extension-activity_pub.html b/extension-activity_pub.html
index c36b366ef14..a69bd9472bf 100644
--- a/extension-activity_pub.html
+++ b/extension-activity_pub.html
@@ -140,49 +140,49 @@
Installation
-- Add this library to your dependencies in
mix.exs
defp deps do
- [...]
- {:activity_pub, git: "https://github.com/bonfire-networks/activity_pub.git", branch: "stable"} # branch can "stable", or "develop" for the bleeding edge
-end
- Create an adapter module. To start, one created at
-
lib/my_app/adapter.ex
might look like
defmodule MyApp.Adapter do
+- Add this library to your dependencies in
mix.exs
defp deps do
+ [...]
+ {:activity_pub, git: "https://github.com/bonfire-networks/activity_pub.git", branch: "stable"} # branch can "stable", or "develop" for the bleeding edge
+end
- Create an adapter module. To start, one created at
+
lib/my_app/adapter.ex
might look like
defmodule MyApp.Adapter do
@moduledoc """
Adapter functions delegated from the `ActivityPub` Library
"""
@behaviour ActivityPub.Federator.Adapter
-end
Note that, due to the defined @behavior
, Elixir will warn you that
+
end
Note that, due to the defined @behavior
, Elixir will warn you that
the required functions
base_url/0
get_actor_by_id/1
get_actor_by_username/1
get_follower_local_ids/1
get_following_local_ids/1
get_redirect_url/1
handle_activity/1
maybe_create_remote_actor/1
maybe_publish_object/2
update_local_actor/2
update_remote_actor/1
have not yet been implemented though you will be able to start your
app. Defining these allows ActivityPub
to handle ActivityPub HTTP
and database calls and operations. An example of an implemented
adaptor can be found
here.
Then set it in config
config :activity_pub, :adapter, MyApp.Adapter
- Set your application repo in config
config :activity_pub, :repo, MyApp.Repo
Create a new ecto migration and call ActivityPub.Migration.up/0
from it
Inject AP routes to your router by adding use ActivityPub.Web.Router
to your app's router module
Copy the default AP config to your app's confix.exs
config :activity_pub, :mrf_simple,
- media_removal: [],
- media_nsfw: [],
- report_removal: [],
- accept: [],
- avatar_removal: [],
- banner_removal: []
+ media_removal: [],
+ media_nsfw: [],
+ report_removal: [],
+ accept: [],
+ avatar_removal: [],
+ banner_removal: []
config :activity_pub, :instance,
hostname: "example.com",
- federation_publisher_modules: [ActivityPub.Federator.APPublisher],
+ federation_publisher_modules: [ActivityPub.Federator.APPublisher],
federation_reachability_timeout_days: 7,
federating: true,
- rewrite_policy: []
+ rewrite_policy: []
config :activity_pub, :http,
proxy_url: nil,
user_agent: "Your app name",
send_user_agent: true,
- adapter: [
- ssl_options: [
+ adapter: [
+ ssl_options: [
# Workaround for remote server certificate chain issues
partial_chain: &:hackney_connect.partial_chain/1,
# We don't support TLS v1.3 yet
- versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
- ]
- ]
Change the hostname value in the instance config block to your instance's hostname
If you don't already have Oban set up, follow the Oban installation intructions and add the AP queues:
config :my_app, Oban, queues: [federator_incoming: 50, federator_outgoing: 50, remote_fetcher: 20]
Now you should be able to compile and run your app and move over to integration.
+ versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"]
+ ]
+ ]Change the hostname value in the instance config block to your instance's hostname
If you don't already have Oban set up, follow the Oban installation intructions and add the AP queues:
config :my_app, Oban, queues: [federator_incoming: 50, federator_outgoing: 50, remote_fetcher: 20]
Now you should be able to compile and run your app and move over to integration.
diff --git a/extension-arrows.html b/extension-arrows.html
index be0cf5d260b..29978b0984d 100644
--- a/extension-arrows.html
+++ b/extension-arrows.html
@@ -140,48 +140,48 @@
Installation
-
The package can be installed by adding arrows
to your list of dependencies in mix.exs
: -->
def deps do
- [
- {:arrows, "~> 0.1.0"}
- ]
-end
Or via git:
def deps do
- [
- {:arrows, git: "https://github.com/bonfire-networks/arrows", branch: "main"}
- ]
-end
+
The package can be installed by adding arrows
to your list of dependencies in mix.exs
: -->
def deps do
+ [
+ {:arrows, "~> 0.1.0"}
+ ]
+end
Or via git:
def deps do
+ [
+ {:arrows, git: "https://github.com/bonfire-networks/arrows", branch: "main"}
+ ]
+end
Documentation
The Elixir |> ("pipe") operator is one of the things that seems to get people excited about elixir. Probably in part because you then don't have to keep coming up with function names. Unfortunately it's kind of limiting.
-The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.
Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
+The moment you need to pipe a parameter into a position that isn't the first one, it breaks down and you have to drop out of the pipeline format or write a secondary function to handle it.Not any more! By simply inserting ...
where you would like the value to be inserted, Arrows
will override where it is placed. This allows you to keep on piping while accommodating that function with the annoying argument order. Arrows
was inspired by an existing library. Here is part of the test suite in lieu of examples:
defmodule ArrowsTest do
use ExUnit.Case
use Arrows
- def double(x), do: x * 2
- def double_fst(x, _), do: x * 2
- def double_snd(_, x), do: x * 2
- def add_snd_thd(_, x, y), do: x + y
-
- test "|>" do
- assert 4 == (2 |> double)
- assert 4 == (2 |> double())
- assert 4 == (2 |> double(...))
- assert 8 == (2 |> double(double(...)))
- assert 4 == (2 |> double_fst(1))
- assert 4 == (2 |> double_fst(..., 1))
- assert 8 == (2 |> double_fst(double(...), 1))
- assert 4 == (2 |> double_snd(1, ...))
- assert 8 == (2 |> double_snd(1, double(...)))
- assert 3 == (2 |> add_snd_thd(1, ..., 1))
- assert 4 == (2 |> add_snd_thd(1, ..., ...))
- assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
- for x <- [:yes, 2, nil, false] do
- assert {:ok, x} == (x |> {:ok, ...})
- end
- end
-end
A few little extra features you might notice here:
- You can move the parameter into a subexpression, as in
2 |> double_fst(double(...), 1)
where
+
def double(x), do: x * 2
+ def double_fst(x, _), do: x * 2
+ def double_snd(_, x), do: x * 2
+ def add_snd_thd(_, x, y), do: x + y
+
+ test "|>" do
+ assert 4 == (2 |> double)
+ assert 4 == (2 |> double())
+ assert 4 == (2 |> double(...))
+ assert 8 == (2 |> double(double(...)))
+ assert 4 == (2 |> double_fst(1))
+ assert 4 == (2 |> double_fst(..., 1))
+ assert 8 == (2 |> double_fst(double(...), 1))
+ assert 4 == (2 |> double_snd(1, ...))
+ assert 8 == (2 |> double_snd(1, double(...)))
+ assert 3 == (2 |> add_snd_thd(1, ..., 1))
+ assert 4 == (2 |> add_snd_thd(1, ..., ...))
+ assert 6 == (2 |> add_snd_thd(1, ..., double(...)))
+ for x <- [:yes, 2, nil, false] do
+ assert {:ok, x} == (x |> {:ok, ...})
+ end
+ end
+end
A few little extra features you might notice here:
- You can move the parameter into a subexpression, as in
2 |> double_fst(double(...), 1)
where
double will be called before the parameter is passed to double_fst
. - You can use
...
multiple times, substituting it in multiple places. - The right hand side need not even be a function call, you can use any expression with
...
.
diff --git a/extension-bonfire_data_activity_pub.html b/extension-bonfire_data_activity_pub.html
index 77b6b15c6eb..7f4f8fdfb17 100644
--- a/extension-bonfire_data_activity_pub.html
+++ b/extension-bonfire_data_activity_pub.html
@@ -140,7 +140,7 @@
Copyright and License
-Copyright (c) 2020 James Laver, bonfire_data_activity_pub Contributors
+Copyright (c) 2020 James Laver, bonfire_data_activity_pub Contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/extension-bonfire_data_assort.html b/extension-bonfire_data_assort.html
index 1898b7dadc8..8f1f6732c05 100644
--- a/extension-bonfire_data_assort.html
+++ b/extension-bonfire_data_assort.html
@@ -140,7 +140,7 @@
Copyright and License
-Copyright (c) 2020 Bonfire Contributors
+Copyright (c) 2020 Bonfire Contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/extension-bonfire_data_identity.html b/extension-bonfire_data_identity.html
index 8abfb3b8e73..a51e0848bc9 100644
--- a/extension-bonfire_data_identity.html
+++ b/extension-bonfire_data_identity.html
@@ -140,7 +140,7 @@
Copyright and License
-Copyright (c) 2020 James Laver, bonfire_data_identity Contributors
+Copyright (c) 2020 James Laver, bonfire_data_identity Contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/extension-bonfire_data_shared_user.html b/extension-bonfire_data_shared_user.html
index 6accd2642d2..316e1d8f1da 100644
--- a/extension-bonfire_data_shared_user.html
+++ b/extension-bonfire_data_shared_user.html
@@ -140,7 +140,7 @@
Copyright and License
-Copyright (c) 2020 Bonfire Contributors
+Copyright (c) 2020 Bonfire Contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/extension-bonfire_data_social.html b/extension-bonfire_data_social.html
index d3e22c62ab0..02950611f07 100644
--- a/extension-bonfire_data_social.html
+++ b/extension-bonfire_data_social.html
@@ -140,7 +140,7 @@
Copyright and License
-Copyright (c) 2020 James Laver, bonfire_data_social Contributors
+Copyright (c) 2020 James Laver, bonfire_data_social Contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/extension-ecto_sparkles.html b/extension-ecto_sparkles.html
index 8d834e8c2b2..c696ae2cfb5 100644
--- a/extension-ecto_sparkles.html
+++ b/extension-ecto_sparkles.html
@@ -147,25 +147,25 @@
Examples using standard Ecto
query
- |> join(:left, [o, activity: activity], assoc(:object), as: :object)
- |> preload([l, activity: activity, object: object], activity: {activity, [object: object]})
Ecto requires calling three different functions for this operation: Query.join/4
, Query.assoc/3
and Query.preload/2
.
Here's another example:
Invoice
- |> join(:left, [i], assoc(i, :customer), as: :customer)
- |> join(:left, [i], assoc(i, :lines), as: :lines)
- |> preload([lines: v, customers: c], lines: v, customer: c)
+ |> join(:left, [o, activity: activity], assoc(:object), as: :object)
+ |> preload([l, activity: activity, object: object], activity: {activity, [object: object]})
Ecto requires calling three different functions for this operation: Query.join/4
, Query.assoc/3
and Query.preload/2
.
Here's another example:
Invoice
+ |> join(:left, [i], assoc(i, :customer), as: :customer)
+ |> join(:left, [i], assoc(i, :lines), as: :lines)
+ |> preload([lines: v, customers: c], lines: v, customer: c)
Example using proload
-With proload
, you can accomplish this with just one line of code:
proload(query, activity: [:object])
And for the other example:
proload(Invoice, [:customer, :lines])
As a bonus, it automatically makes use of reusable_join
so calling it multiple times with the same association has no ill effects.
+
With proload
, you can accomplish this with just one line of code:
proload(query, activity: [:object])
And for the other example:
proload(Invoice, [:customer, :lines])
As a bonus, it automatically makes use of reusable_join
so calling it multiple times with the same association has no ill effects.
Example using join_preload
-join_preload
is proload
's sister macro with a slightly different syntax:
join_preload(query, [:activity, :object])
and:
Invoice
- |> join_preload(:customer)
- |> join_preload(:lines)
+
join_preload
is proload
's sister macro with a slightly different syntax:
join_preload(query, [:activity, :object])
and:
Invoice
+ |> join_preload(:customer)
+ |> join_preload(:lines)
@@ -186,8 +186,8 @@
Creating reusable joins
query
-|> reusable_join(:left, [t1], t2 in "other_table", on: t1.id == t2.id, as: :other_a)
-|> reusable_join(:left, [t1], t2 in "other_table", on: t1.id == t2.id, as: :other_b)
+|> reusable_join(:left, [t1], t2 in "other_table", on: t1.id == t2.id, as: :other_a)
+|> reusable_join(:left, [t1], t2 in "other_table", on: t1.id == t2.id, as: :other_b)
diff --git a/extension-exto.html b/extension-exto.html
index ea8bc1391c0..2462a0b522d 100644
--- a/extension-exto.html
+++ b/extension-exto.html
@@ -141,35 +141,35 @@
Usage
-
Example Schema:
defmodule My.Schema do
+Example Schema:
defmodule My.Schema do
use Ecto.Schema
- import Exto, only: [flex_schema: 1]
+ import Exto, only: [flex_schema: 1]
- schema "my_table" do
+ schema "my_table" do
field :name, :string # just normal schema things
- flex_schema(:my_app) # boom! give me the stuff
- end
-end
Example configuration
config :my_app, My.Schema,
- belongs_to: [
+ flex_schema(:my_app) # boom! give me the stuff
+ end
+end
Example configuration
config :my_app, My.Schema,
+ belongs_to: [
foo: Foo, # belongs_to :foo, Foo
- bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
- ],
- field: [
+ bar: {Bar, type: :integer}, # belongs_to :bar, Bar, type: :integer
+ ],
+ field: [
foo: :string, # field :foo, :string
- bar: {:integer, default: 4}, # field :foo, :integer, default: 4
- ],
- has_one: [
+ bar: {:integer, default: 4}, # field :foo, :integer, default: 4
+ ],
+ has_one: [
foo: Foo, # has_one :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
- ]
- has_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_one :bar, Bar, foreign_key: :the_bar_id
+ ]
+ has_many: [
foo: Foo, # has_many :foo, Foo
- bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
- ]
- many_to_many: [
+ bar: {Bar, foreign_key: :the_bar_id}, # has_many :bar, Bar, foreign_key: :the_bar_id
+ ]
+ many_to_many: [
foo: Foo, # many_to_many :foo, Foo
- bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
- ]
This one won't work very well because we define foo
and bar
5
+
bar: {Bar, join_through: FooBar}, # many_to_many :bar, Bar, :join_through: FooBar
+ ]
This one won't work very well because we define foo
and bar
5
times each, but I think you get the point.
Reading of configuration is done during compile time. The relations
will be baked in during compilation, thus:
- Do not expect this to work in runtime config.
- You will need to rebuild all dependencies which use this macro
when you change their configuration.
diff --git a/extension-grumble.html b/extension-grumble.html
index 378b1935fa6..757ed90a906 100644
--- a/extension-grumble.html
+++ b/extension-grumble.html
@@ -149,26 +149,26 @@
Usage
-Add to your deps:
{:grumble, "~> 0.1.0"}
Simple example:
import Grumble
+Add to your deps:
{:grumble, "~> 0.1.0"}
Simple example:
import Grumble
alias Grumble.PP
-IO.puts(PP.to_string(
- query(
- params: [community_id: type!(:string)],
- fields: [
- field(
+IO.puts(PP.to_string(
+ query(
+ params: [community_id: type!(:string)],
+ fields: [
+ field(
:community,
- args: [community_id: var(:community_id)],
- fields: [:id, :name]
- )
- ]
- )
-))
Output:
query($communityId: String!) {
- community(communityId: $communityId) {
+ args: [community_id: var(:community_id)],
+ fields: [:id, :name]
+ )
+ ]
+ )
+))
Output:
query($communityId: String!) {
+ community(communityId: $communityId) {
name
id
- }
-}
+
}
+}
diff --git a/extension-needle.html b/extension-needle.html
index 86f283ef827..3f2cb4f9ac7 100644
--- a/extension-needle.html
+++ b/extension-needle.html
@@ -159,19 +159,19 @@
Aside from the hex dependency, you will also need to write a simple
migration to set up the database before you can start writing your
-regular migrations:
defmodule MyApp.Repo.Migrations.InitPointers do
+regular migrations:defmodule MyApp.Repo.Migrations.InitPointers do
@moduledoc false
use Ecto.Migration
import Needle.Migration
- def up(), do: inits(:up)
- def down(), do: inits(:down)
+ def up(), do: inits(:up)
+ def down(), do: inits(:down)
- defp inits(dir) do
- init_pointers_ulid_extra(dir) # this one is optional but recommended
- init_pointers(dir) # this one is not optional
- end
-end
+
defp inits(dir) do
+ init_pointers_ulid_extra(dir) # this one is optional but recommended
+ init_pointers(dir) # this one is not optional
+ end
+end
@@ -182,37 +182,37 @@
Crockford's Base32.
They should be easy to identify in a printout and might be silly.
There is a helper function, synthesise!/1
in Needle.ULID
to
assist with this process - give it a 26-character long binary of ascii
-alphanumerics and it will give you the closest ULID that matches back.
Let's look at a simple schema:
defmodule MyApp.Greeting do
+alphanumerics and it will give you the closest ULID that matches back.Let's look at a simple schema:
defmodule MyApp.Greeting do
use Needle.Pointable,
otp_app: :my_app,
source: "myapp_greeting",
table_id: "GREET1NGSFR0MD0CEXAMP1E000"
- pointable_schema do
+ pointable_schema do
field :greeting, :string
- end
-end
To declare a pointable schema, we start by using Needle.Pointable
,
+
end
+end
To declare a pointable schema, we start by using Needle.Pointable
,
providing the name of our otp application, the source table's name in
the database and our chosen sentinel ULID.
We then call pointable_schema
and define any fields we wish to put
directly in the table. For the most part, pointable_schema
is like
Ecto's schema
macro, except you do not provide the table name and
let it handle the primary key.
If for some reason you wished to turn autogeneration off, you could
pass autogenerate: false
to the options provided when using
-Needle.Pointable
.
Now let's define the migration for our schema:
defmodule MyApp.Repo.Migrations.Greeting do
+Needle.Pointable
.Now let's define the migration for our schema:
defmodule MyApp.Repo.Migrations.Greeting do
@moduledoc false
use Ecto.Migration
import Needle.Migration
- def up() do
- create_pointable_table(:greeting, "GREET1NGSFR0MD0CEXAMP1E000") do
+ def up() do
+ create_pointable_table(:greeting, "GREET1NGSFR0MD0CEXAMP1E000") do
add :greeting, :text, null: false
- end
- end
+ end
+ end
- def down() do
- drop_pointable_table(:greeting, "GREET1NGSFR0MD0CEXAMP1E000")
- end
-end
As you can see, it's pretty similar to defining a regular migration,
+
def down() do
+ drop_pointable_table(:greeting, "GREET1NGSFR0MD0CEXAMP1E000")
+ end
+end
As you can see, it's pretty similar to defining a regular migration,
except you use create_pointable_table
and
drop_pointable_table
. Notice that our sentinel ULID makes an
appearance again here. It's very important that these match what we
@@ -225,16 +225,16 @@
Ecto does not know anything about our scheme, so unless we
specifically want something to reference one of the pointed tables, we
typically belongs_to
with Needle.Pointer
. The table in which we
-do this does not itself need to be pointable.
defmodule MyApp.Foo do
+do this does not itself need to be pointable.defmodule MyApp.Foo do
use Ecto.Schema
alias Needle.Pointer
# regular ecto table, not pointable!
- schema "hello" do
+ schema "hello" do
belongs_to :pointer, Pointer # who knows what it points to?
- end
-end
You may choose to reference a specific schema rather than Pointer if it
+
end
+end
You may choose to reference a specific schema rather than Pointer if it
will only point to a single table. If you do this, you must ensure
that the referenced record exists in that table in the normal
way. There may be some performance benefit, we didn't benchmark it.
The migration is slightly more complex, we have to decide what type of
@@ -242,18 +242,18 @@
points to is deleted.
- A weak pointer is nullable and is nilified when the object it points
to is deleted.
- An unbreakable pointer will raise when you attempt to delete the
object it points to.
Type Nullable? On Delete Strong No Cascade Weak Yes Set Null Unbreakable No Raise
In this case we will use a strong pointer, because we want it to be
-deleted if the pointed object is deleted.
defmodule MyApp.Repo.Migrations.Hello do
+deleted if the pointed object is deleted.defmodule MyApp.Repo.Migrations.Hello do
@moduledoc false
use Ecto.Migration
import Needle.Migration
- def change() do
- create_if_not_exists table(:hello) do
- add :pointer, strong_pointer(), null: false
+ def change() do
+ create_if_not_exists table(:hello) do
+ add :pointer, strong_pointer(), null: false
add :greeting, :text, null: false
- end
- end
-end
If you are pointing to a specific table instead of pointer,
+
end
+ end
+end
If you are pointing to a specific table instead of pointer,
strong_pointer/1
allows you to pass the name of that module
(strong_pointer/0
calls this with Needle.Pointer
).
@@ -281,38 +281,38 @@
know which table they are to work with them! The solution to this is
what we are calling 'mixin tables' for convenience.
A mixin table has a Pointer
primary key along with any other fields
you wish to store in this mixin. By moving fields out to mixin tables,
-you gain knowledge of the table name to which you need to join.
An example mixin schema:
defmodule My.Creator do
+you gain knowledge of the table name to which you need to join.An example mixin schema:
defmodule My.Creator do
use Needle.Mixin,
otp_app: :my_app,
source: "creator"
- mixin_schema do
+ mixin_schema do
belongs_to :creator, My.User
- end
-end
Mixin tables are not themselves pointable, so there is no need to
-specify a table id as when defining a pointable schema.
The migration for this is slightly more complicated:
defmodule My.Creator.Migration do
+ end
+end
Mixin tables are not themselves pointable, so there is no need to
+specify a table id as when defining a pointable schema.
The migration for this is slightly more complicated:
defmodule My.Creator.Migration do
import Ecto.Migration
import Needle.Migration
- defp creator_table(), do: My.Creator.__schema__(:source)
- defp user_table(), do: My.User.__schema__(:source)
+ defp creator_table(), do: My.Creator.__schema__(:source)
+ defp user_table(), do: My.User.__schema__(:source)
- def migrate_creator(index_opts \\ []),
- do: migrate_creator(index_opts, direction())
+ def migrate_creator(index_opts \\ []),
+ do: migrate_creator(index_opts, direction())
- defp migrate_creator(index_opts, :up) do
- create_mixin_table(creator_table()) do
- add :creator_id, strong_pointer(user_table()), null: false
- end
- create_if_not_exists(unique_index(creator_table(), [:creator_id], index_opts))
- end
+ defp migrate_creator(index_opts, :up) do
+ create_mixin_table(creator_table()) do
+ add :creator_id, strong_pointer(user_table()), null: false
+ end
+ create_if_not_exists(unique_index(creator_table(), [:creator_id], index_opts))
+ end
- defp migrate_creator(index_opts, :down) do
- drop_if_exists(unique_index(creator_table(), [:creator_id], index_opts))
- drop_mixin_table(creator_table())
- end
-end
+
defp migrate_creator(index_opts, :down) do
+ drop_if_exists(unique_index(creator_table(), [:creator_id], index_opts))
+ drop_mixin_table(creator_table())
+ end
+end
diff --git a/extension-needle_ulid.html b/extension-needle_ulid.html
index c9721e8420e..f576da24cab 100644
--- a/extension-needle_ulid.html
+++ b/extension-needle_ulid.html
@@ -143,7 +143,7 @@
Installation
-{:needle_ulid, git: "https://github.com/bonfire-networks/needle_ulid", branch: "main"}
+{:needle_ulid, git: "https://github.com/bonfire-networks/needle_ulid", branch: "main"}
diff --git a/extension-paginator.html b/extension-paginator.html
index 147a65f90f4..d92c2f23a63 100644
--- a/extension-paginator.html
+++ b/extension-paginator.html
@@ -171,17 +171,17 @@
Getting started
-defmodule MyApp.Repo do
+defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
use Paginator
-end
+end
-query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
+query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
-page = MyApp.Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
+page = MyApp.Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
# `page.edges` contains all the entries for this page.
# `page.page_info` contains the meta-data associated with this page (cursors, limit, total count)
@@ -190,42 +190,42 @@
Install
-Add paginator
to your list of dependencies in mix.exs
:
def deps do
- [{:paginator, "~> 1.0.4"}]
-end
+
Add paginator
to your list of dependencies in mix.exs
:
def deps do
+ [{:paginator, "~> 1.0.4"}]
+end
Usage
-Add Paginator
to your repo.
defmodule MyApp.Repo do
+Add Paginator
to your repo.
defmodule MyApp.Repo do
use Ecto.Repo,
otp_app: :my_app,
adapter: Ecto.Adapters.Postgres
use Paginator
- end
Use the paginate
function to paginate your queries.
query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
+ end
Use the paginate
function to paginate your queries.
query = from(p in Post, order_by: [asc: p.inserted_at, asc: p.id])
# return the first 50 posts
- %{edges: edges, page_info: page_info} = Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
+ %{edges: edges, page_info: page_info} = Repo.paginate(query, cursor_fields: [:inserted_at, :id], limit: 50)
# assign the `after` cursor to a variable
cursor_after = page_info.end_cursor
# return the next 50 posts
- %{edges: edges, page_info: page_info} = Repo.paginate(query, after: cursor_after, cursor_fields: [{:inserted_at, :asc}, {:id, :asc}], limit: 50)
+ %{edges: edges, page_info: page_info} = Repo.paginate(query, after: cursor_after, cursor_fields: [{:inserted_at, :asc}, {:id, :asc}], limit: 50)
# assign the `before` cursor to a variable
cursor_before = page_info.start_cursor
# return the previous 50 posts (if no post was created in between it should be the same list as in our first call to `paginate`)
- %{edges: edges, page_info: page_info} = Repo.paginate(query, before: cursor_before, cursor_fields: [:inserted_at, :id], limit: 50)
+ %{edges: edges, page_info: page_info} = Repo.paginate(query, before: cursor_before, cursor_fields: [:inserted_at, :id], limit: 50)
# return total count
# NOTE: this will issue a separate `SELECT COUNT(*) FROM table` query to the database.
- %{edges: edges, page_info: page_info} = Repo.paginate(query, include_total_count: true, cursor_fields: [:inserted_at, :id], limit: 50)
+ %{edges: edges, page_info: page_info} = Repo.paginate(query, include_total_count: true, cursor_fields: [:inserted_at, :id], limit: 50)
- IO.puts "total count: #{page_info.total_count}"
+
IO.puts "total count: #{page_info.total_count}"
@@ -248,7 +248,7 @@
# If your cursor fields are: [:inserted_at, :id]
# Add the following in a migration
-create index("posts", [:inserted_at, :id])
+
create index("posts", [:inserted_at, :id])
diff --git a/extension-zest.html b/extension-zest.html
index d4b06d47de8..0938249d85b 100644
--- a/extension-zest.html
+++ b/extension-zest.html
@@ -140,39 +140,39 @@
Usage
-
Installation:
{:zest, "~> 0.1.2"}
Example (taken from our test suite):
defmodule MyTest do
+Installation:
{:zest, "~> 0.1.2"}
Example (taken from our test suite):
defmodule MyTest do
use ExUnit.Case
import Zest
- test "scope fails spectacularly" do
- scope [this: %{is: :a}, test: :case] do
- scope [error: :this_should_not_show] do
- end
- scope [the: :order, must: :be_correct] do
- scope [to: :pass], assert(true == false)
- end
- end
- end
-
-end
Output:
Zest Context:
-* this: %{is: :a}
+ test "scope fails spectacularly" do
+ scope [this: %{is: :a}, test: :case] do
+ scope [error: :this_should_not_show] do
+ end
+ scope [the: :order, must: :be_correct] do
+ scope [to: :pass], assert(true == false)
+ end
+ end
+ end
+
+end
Output:
Zest Context:
+* this: %{is: :a}
* test: :case
* the: :order
* must: :be_correct
* to: :pass
- 1) test scope fails spectacularly (ZestTest)
+ 1) test scope fails spectacularly (ZestTest)
test/zest_test.exs:7
Assertion with == failed
code: assert true == false
left: true
right: false
stacktrace:
- (zest 0.1.0) lib/zest.ex:52: Zest.in_scope/2
- (zest 0.1.0) lib/zest.ex:47: anonymous fn/1 in Zest.in_scope/2
- (zest 0.1.0) lib/zest.ex:113: Zest.intercept/2
- test/zest_test.exs:8: (test)
+
(zest 0.1.0) lib/zest.ex:52: Zest.in_scope/2
+ (zest 0.1.0) lib/zest.ex:47: anonymous fn/1 in Zest.in_scope/2
+ (zest 0.1.0) lib/zest.ex:113: Zest.intercept/2
+ test/zest_test.exs:8: (test)
diff --git a/graphql.html b/graphql.html
index 00baca2a79f..ae9faa67539 100644
--- a/graphql.html
+++ b/graphql.html
@@ -150,10 +150,10 @@
}
Let's break this apart:
query {}
is how you retrieve information from GraphQL.greetings
is a field
within the query.greetings
takes a limit
argument, a positive integer.greetings
has two fields, greeting
and to
.to
has one field
, name
.
This query is asking for a list of (up to) 10 greetings and the people
they are for. Notice that the result of both greetings
and to
are
map/object structures with their own fields and that if the type has
-multiple fields, we can select more than one field.
Here is some possible data we could get returned
%{greetings: [
- %{greeting: "hello", to: %{ name: "dear reader"}}, # english
- %{greeting: "hallo", to: %{ name: "beste lezer"}}, # dutch
- ]}
Where is the magic? Typically an object type will reside in its own
+multiple fields, we can select more than one field.
Here is some possible data we could get returned
%{greetings: [
+ %{greeting: "hello", to: %{ name: "dear reader"}}, # english
+ %{greeting: "hallo", to: %{ name: "beste lezer"}}, # dutch
+ ]}
Where is the magic? Typically an object type will reside in its own
table in the database, so this query is actually querying two tables
in one go. In fact, given a supporting schema, you can nest queries
arbitrarily and the backend will figure out how to run them.
The fact that you can represent arbitrarily complex queries puts quite
@@ -165,59 +165,59 @@
Absinthe Introduction
Every field
is filled by a resolver. Let's take our existing query
-and define a schema for it in Absinthe's query DSL:
defmodule MyApp.Schema do
+and define a schema for it in Absinthe's query DSL:defmodule MyApp.Schema do
# the schema macro language
use Absinthe.Schema.Notation
# where we will actually resolve the fields
alias MyApp.Resolver
# Our user object is pretty simple, just a name
- object :user do
- field :name, non_null(:string)
- end
+ object :user do
+ field :name, non_null(:string)
+ end
# This one is slightly more complicated, we have that nested `to`
- object :greeting do
+ object :greeting do
# the easy one
- field :greeting, non_null(:string)
+ field :greeting, non_null(:string)
# the hard one. `edge` is the term for when we cross an object boundary.
- field :to, non_null(:user), do: resolve(&Resolver.to_edge/3)
- end
+ field :to, non_null(:user), do: resolve(&Resolver.to_edge/3)
+ end
# something to put our top level queries in, because they're just fields too!
- object :queries do
- field :greetings, non_null(list_of(non_null(:string))) do
+ object :queries do
+ field :greetings, non_null(list_of(non_null(:string))) do
arg :limit, :integer # optional
resolve &Resolver.greetings/2 # we need to manually process this one
- end
- end
+ end
+ end
-end
There are a couple of interesting things about this:
- Sprinklings of
not_null
to require that values be present (if you
+
end
There are a couple of interesting things about this:
- Sprinklings of
not_null
to require that values be present (if you
don't return them, absinthe will get upset). - Only two fields have explicit resolvers. Anything else will default
to a map key lookup (which is more often than not what you want).
greeting.to_edge
has a /3
resolver and queries.greetings
a
/2
resolver.
To understand the last one (and partially the middle one), we must
understand how resolution works and what a parent is. The best way of
-doing that is probably to look at the resolver code:
defmodule MyApp.Resolver do
+doing that is probably to look at the resolver code:defmodule MyApp.Resolver do
# For purposes of this, we will just fake the data out
- defp greetings_data() do
- [ %{greeting: "hello", to: %{ name: "dear reader"}}, # english
- %{greeting: "hallo", to: %{ name: "beste lezer"}}, # dutch
- ]
- end
+ defp greetings_data() do
+ [ %{greeting: "hello", to: %{ name: "dear reader"}}, # english
+ %{greeting: "hallo", to: %{ name: "beste lezer"}}, # dutch
+ ]
+ end
# the /2 resolver takes only arguments (which in this case is just limit)
# and an info (which we'll explain later)
- def greetings(%{limit: limit}, _info) when is_integer(limit) and limit > 0 do
- {:ok, Enum.take(greetings_data(), limit)} # absinthe expects an ok/error tuple
- end
- def greetings(_args, _info), do: {:ok, greetings_data()} # no limit
+ def greetings(%{limit: limit}, _info) when is_integer(limit) and limit > 0 do
+ {:ok, Enum.take(greetings_data(), limit)} # absinthe expects an ok/error tuple
+ end
+ def greetings(_args, _info), do: {:ok, greetings_data()} # no limit
# the /3 resolver takes an additional parent argument in first position.
# `parent` here will be the `greeting` we are resolving `to` for.
- def to_edge(parent, args, info), do: Map.get(parent, :to)
+ def to_edge(parent, args, info), do: Map.get(parent, :to)
-end
The keen-eyed amongst you may have noticed I said the default resolver
+
end
The keen-eyed amongst you may have noticed I said the default resolver
is a map lookup and our to_edge/3
is a map lookup too, so
technically we didn't need to write it. But then you wouldn't have an
example of a /3
resolver! In most of the app, these will be querying
diff --git a/hacking.html b/hacking.html
index 0ff02b3a459..3e4deef1cab 100644
--- a/hacking.html
+++ b/hacking.html
@@ -284,7 +284,7 @@
Example:
** (DBConnection.ConnectionError) tcp recv: closed (the connection was closed by the pool, possibly due to a timeout or because the pool has been terminated)
In this case, the seeds were unable to complete because a query took too long to execute on your machine. You can configure the timeout to be larger in the dev
environment:
- Open
config/dev.exs
in your editor. - Find the database configuration (search for
Bonfire.Common.Repo
). - Add
timeout: 60_000
to the list of options:
config :bonfire, Bonfire.Common.Repo,
timeout: 60_000,
- [...]
+ [...]
diff --git a/mrf.html b/mrf.html
index 3afe807da5a..08f33c19f62 100644
--- a/mrf.html
+++ b/mrf.html
@@ -142,7 +142,7 @@
Using SimplePolicy
SimplePolicy
is capable of handling most common admin tasks.
To use SimplePolicy
, you must enable it. Do so by adding the following to your :instance
config object, so that it looks like this:
config :bonfire, :instance,
- [...]
+ [...]
rewrite_policy: ActivityPub.MRF.SimplePolicy
Once SimplePolicy
is enabled, you can configure various groups in the :mrf_simple
config object. These groups are:
media_removal
: Servers in this group will have media stripped from incoming messages.media_nsfw
: Servers in this group will have the #nsfw tag and sensitive setting injected into incoming messages which contain media.reject
: Servers in this group will have their messages rejected.report_removal
: Servers in this group will have their reports (flags) rejected.
Servers should be configured as lists.
@@ -150,13 +150,13 @@
Example
This example will enable SimplePolicy
, block media from illegalporn.biz
, mark media as NSFW from porn.biz
and porn.business
, reject messages from spam.com
and block reports (flags) from troll.mob
:
config :activity_pub, :instance,
- rewrite_policy: [ActivityPub.MRF.SimplePolicy]
+ rewrite_policy: [ActivityPub.MRF.SimplePolicy]
config :activity_pub, :mrf_simple,
- media_removal: ["illegalporn.biz"],
- media_nsfw: ["porn.biz", "porn.business"],
- reject: ["spam.com"],
- report_removal: ["troll.mob"]
+ media_removal: ["illegalporn.biz"],
+ media_nsfw: ["porn.biz", "porn.business"],
+ reject: ["spam.com"],
+ report_removal: ["troll.mob"]
@@ -171,18 +171,18 @@
As discussed above, the MRF system is a modular system that supports pluggable policies. This means that an admin may write a custom MRF policy in Elixir or any other language that runs on the Erlang VM, by specifying the module name in the rewrite_policy
config setting.
For example, here is a sample policy module which rewrites all messages to "new message content":
# This is a sample MRF policy which rewrites all Notes to have "new message
# content."
-defmodule Site.RewritePolicy do
+defmodule Site.RewritePolicy do
@behavior ActivityPub.MRF
# Catch messages which contain Note objects with actual data to filter.
# Capture the object as `object`, the message content as `content` and the
# entire activity itself as `activity`.
@impl true
- def filter(%{"type" => "Create", "object" => %{"type" => "Note", "content" => content} = object} = message)
- when is_binary(content) do
+ def filter(%{"type" => "Create", "object" => %{"type" => "Note", "content" => content} = object} = message)
+ when is_binary(content) do
# Subject / CW is stored as summary instead of `name` like other AS2 objects
# because of Mastodon doing it that way.
- summary = object["summary"]
+ summary = object["summary"]
# edits go here.
content = "new message content"
@@ -190,21 +190,21 @@
# Assemble the mutated object.
object =
object
- |> Map.put("content", content)
- |> Map.put("summary", summary)
+ |> Map.put("content", content)
+ |> Map.put("summary", summary)
# Assemble the mutated activity.
- {:ok, Map.put(activity, "object", object)}
- end
+ {:ok, Map.put(activity, "object", object)}
+ end
# Let all other messages through without modifying them.
@impl true
- def filter(message), do: {:ok, message}
-end
If you save this file as lib/site/mrf/rewrite_policy.ex
, it will be included when you next rebuild Bonfire. You can enable it in the configuration like so:
config :activity_pub, :instance,
- rewrite_policy: [
+ def filter(message), do: {:ok, message}
+end
If you save this file as lib/site/mrf/rewrite_policy.ex
, it will be included when you next rebuild Bonfire. You can enable it in the configuration like so:
config :activity_pub, :instance,
+ rewrite_policy: [
ActivityPub.MRF.SimplePolicy,
Site.RewritePolicy
- ]
+ ]