Skip to content

Instantly share code, notes, and snippets.

@Faheetah
Last active May 1, 2021 22:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Faheetah/c8b14237bebfe7612abd5d8a224caa64 to your computer and use it in GitHub Desktop.
Save Faheetah/c8b14237bebfe7612abd5d8a224caa64 to your computer and use it in GitHub Desktop.
Elixir Phoenix TLDR

Generate an App

Requires phx.new, install with mix archive.install hex phx_new

mix phx.new app

Common flags:

  • --no-gettext
  • --no-html
  • --no-webpack
  • --no-ecto
  • --no-dashboard

Dependencies

Find Available Package and Versions

# find packages matching "postgres"
mix hex.search postgres
# get package information, including available versions and config for current version
# i.e. Config: {:postgrex, "~> 0.15.9"}
mix hex.info postgrex

Popular Packages for Phoenix:

  • phx_gen_auth code generator for authentication scaffold, includes registration and password resets
  • pow authentication and user management library
  • bamboo email library
  • waffle file upload library with support for ImageMagick and S3 buckets
  • absinthe GraphQL library

Generators

Schema

A schema is a single data mapper for an Ecto repository. This only generates the schema file and the migration for the schema. Use --no-migration to skip generating a migration.

Generates lib/app/foo/bar.ex and a related migration

mix phx.gen.schema Foo.Bar foo_bars name:string

Context

A context includes a schema along with an API boundary, by default with standard CRUD operations.

Generates lib/app/foos/bar.ex, lib/app/foos.ex, and a related migration

mix phx.gen.context Foos Bar bars name:string

HTML

Generate everything in the context along with lib/app_web/controllers/bar_controller.ex, lib/app_web/views/bar_view.ex, and template files in lib/app_web/templates/ as well as tests/app_web/bar_controller_test.exs

mix phx.gen.html Foos Bar bars name:string

JSON

Generate everything in the context along with lib/app_web/controllers/bar_controller.ex, lib/app_web/views/bar_view.ex, as well as tests/app_web/bar_controller_test.exs. The first invocation will also create lib/app_web/controllers/fallback_controller.ex and lib/app_web/views/changeset_view.ex for default behaviors and helper functions, such as handling JSON responses for errors.

mix phx.gen.json Foos Bar bars name:string

Generate HTML/JSON using existing context

Adding --no-context to phx.gen.html or phx.gen.json will generate only the controller, view, templates, and controller test This can be handy in cases that a context exists and a front end needs to be bolted on.

Schemas

Fields

  • :integer
  • :float
  • :decimal
  • :boolean
  • :map
  • :string
  • :array
  • :references
  • :text
  • :date
  • :time
  • :time_usec
  • :naive_datetime
  • :naive_datetime_usec
  • :utc_datetime
  • :utc_datetime_usec
  • :uuid
  • :binary
  • :datetime (alias for :naive_datetime)

Field modifiers

Migration generator

  • :unique

Schema

  • redact: true
  • default: "default value"
  • virtual: true

Example usage of :references

mix phx.gen.context Foos Bar foo_bars name:string
mix phx.gen.context Fazs Baz faz_bazs name:string foo_bar_id:references:foo_bars

Here foo_bars and foo_bazs reference the two table names. foo_bar_id specifies the column name used to track the relation, which shouldbe the table name, singular, with a suffix of _id. By default, the relation will not work and requires wiring up the two modules. Note: may need to use foreign_key if Ecto has issues resolving the column.

lib/foos/bar.ex

  schema "foo_bars" do
    field :name, :string
    has_one :faz_baz, Baz, foreign_key: :foo_bar_id # add this, can also use has_many

    timestamps()
  end

Specify the has_one relation. Can use has_many with :faz_bazs, Baz

lib/fazs/baz.ex

  schema "faz_bazs" do
    field :name, :string
    belongs_to :foo_bar, Bar # change this from field :bar_id, :integer

    timestamps()
  end
  
  @doc false
  def changeset(baz, attrs) do
    baz
    |> cast(attrs, [:name, :foo_bar_id]) # change thisto add :foo_bar_id
    |> validate_required([:name])
  end

To include the relation, include the ID directly

Fazs.create_baz(%{name: "faz", foo_bar_id: 1}

Self referencing table

Given a table of Foos.Bar, to reference the table itself:

    belongs_to :parent, Foos.Bar
    has_many :children, Foos.Bar, foreign_key: :parent_id

Warning: this does not prevent circular dependencies

Selecting relational data

Get relations in either direction from within a query

Foos.Bar |> preload(:faz_baz) |> Repo.get!(1)
Fazs.Baz |> preload(:foo_bar) |> Repo.get!(1)

Preload relations after getting results

Fazs.list_faz_bazs() |> Repo.preload([:foo_bar])
bars = Foos.list_foo_bars()
bars |> Repo.preload([:faz_baz])

Getting relational data during inserts is the same way

%Fazs.Baz{} 
|> Fazs.Baz.changeset(%{name: "baz", foo_bar_id: 1}) 
|> Repo.insert!() |> Repo.preload(:foo_bar)

Selecting with a query

Repo.all(from b in Foos.Bar, where: b.id == 1, preload: [:faz_baz])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment