Last active
December 3, 2020 03:11
-
-
Save izelnakri/f65e6807ed233e60efa074c276b48b45 to your computer and use it in GitHub Desktop.
Without pipes(|>) certain APIs will not get built or used. Application code below is very easy to read/follow/maintain and write.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Ecto composable queries: | |
| // iex> Movie \ | |
| // ...> |> where([m], m.id < 2) \ | |
| // ...> |> select([m], {m.title}) \ | |
| // ...> |> Repo.all | |
| // [{"Pirates of Silicon Valley"}] | |
| // In JavaScript with |> most likely would be: | |
| Movie | |
| |> where('m', 'm.id < 2') // 'm' because there could be multiple model references on |> sql joins() | |
| |> select('m', 'm.title') | |
| |> Repo.all | |
| // returns: ['Pirates of Silicon Valley'] or Promise to await, or elixir like error handling with tuple: [boolean, returnValue] | |
| // Today without |>: | |
| Repo.all(select(where(Movie, 'm', 'm.id < 2'), 'm', 'm.title'))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Ecto composable changesets/validations: | |
| defmodule Email do | |
| def changeset(struct, params \\ %{}) do | |
| struct | |
| |> cast(params, [:address]) | |
| |> validate_required([:address]) | |
| |> validate_format(:address, ~r/@/) | |
| |> validate_length(:address, max: 75) | |
| |> unique_constraint(:address) | |
| |> foreign_key_constraint(:person_id) | |
| end | |
| def user_registration_changeset(struct, params \\ %{}) do | |
| struct | |
| |> cast(params, [:person_id]) | |
| |> changeset(params) | |
| |> validate_required([:person_id]) | |
| |> generate_confirmation_token() | |
| end | |
| # .... | |
| end | |
| # in Elixir following would return a special Changeset object(struct) that has error, misses "person_id": | |
| Email.user_registration_changeset(%Email{}, %{"adress" => "someone@example.com"}) | |
| Email.changeset(%Email{}, %{"address" => "someone@example.com"}) # returns a valid Changeset with no errors. | |
| Email.user_registration_changeset(%Email{}, %{}) # returns a Changeset with all "address" and "person_id" errors | |
| # For example, to insert or update a record to DB: | |
| case Email.changeset(%Email{}, %{"address" => "someone@example.com"}) |> Repo.insert do | |
| {:ok, email} -> serialize(email) |> to_json | |
| {:error, changeset} -> format_error_to_json(changeset) | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Ecto composable changesets/validations | |
| // without pipes(|>) this very nice API below is near impossible to use effectively: | |
| import { | |
| cast, validateRequired, validateFormat, validateLength, uniqueConstraint, foreignKeyConstraint | |
| } from 'ecto'; | |
| interface ChangesetError { | |
| [anyProperty: string]: string[]; // string of error messages | |
| } | |
| interface Changeset { | |
| valid: boolean; | |
| action: void | string; // more likely set after Repo.insert() / Repo.update() / Repo.delete() call | |
| changes: object; // more like js object, holds only the changed properties with previous values of the model. | |
| errors: ChangesetError[]; | |
| data: void | object; // data to insert/update/delete | |
| } | |
| export default class Email { | |
| static changeset(oldInstance: Email, paramsToCastValidate: object): Changeset { | |
| return oldInstance | |
| |> cast(paramsToCastValidate, ['address']) | |
| |> validateRequired(['address']) | |
| |> validateFormat('address', /@/) | |
| |> validateLength('address', { min: 3, max: 75 }) | |
| |> uniqueConstraint('address') | |
| |> foreignKeyConstraint('person_id') | |
| } | |
| static userRegistrationChangeset(oldInstance: Email, paramsToCastValidate: object): Changeset { | |
| return oldInstance | |
| |> cast(paramsToCastValidate, ['person_id']) | |
| |> changeset(paramsToCastValidate) | |
| |> validateRequired(['person_id']) | |
| |> this.generateConfirmationToken() | |
| } | |
| // ... with static generateConfirmationToken() {} uses cast(changeset, ['confirmation_token'], generatedToken) inside | |
| } | |
| Email.userRegistrationChangeset(new Email(), { adress: 'someone@example.com' }) | |
| // -> Changeset{ valid: false, action: null, changes: { address: null }, errors: [{ person_id: ['is required'] }], data: { address: 'someone@example.com' } } | |
| Email.changeset(new Email(), { address: 'someone@example.com' }) // returns a valid Changeset with no errors. | |
| // -> Changeset{ valid: true, action: null, changes: { address: null }, errors: [], data: { address: 'someone@example.com' } } | |
| Email.userRegistrationChangeset(new Email(), {}) // returns a Changeset with all "address" and "person_id" errors | |
| // -> Changeset{ valid: false, action: null, changes: { address: null }, | |
| // errors: [{ address: ['is required', 'should have correct format', 'should be min. 3 characters', 'already exists'] }, { person_id: ['is_required] }], | |
| // data: { address: 'someone@example.com' } } | |
| // For example, to insert or update a record to DB: | |
| try { | |
| Email.changeset(new Email(), { address: 'someone@example.com' }) | |
| |> Repo.insert // or maybe with await, Repo can find the table from the email.constructor.name | |
| } catch(error: Changeset) { | |
| // do smt with the Changeset | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment