Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Manipulando registros

05_manipulando_registros.livemd

Manipulando registros

Manipulando registros

Definindo changesets

Módulo que permite filtrar, desserializar e validar dados externos para um struct do Elixir.

Criando nossos primeiros changesets

defmodule EctoExample.University.Schemas.College do
  use Ecto.Schema

  import Ecto.Changeset

  alias EctoExample.University.Schemas.Enrollment

  schema "colleges" do
    field(:college_name, :string)
    field(:state, :string)
    field(:price, :decimal)

    has_many(:enrollments, Enrollment)

    timestamps()
  end

  def changeset(college, params) do
    college
    |> cast(params, [:college_name, :state, :price])
    |> validate_required([:college_name, :state, :price])
    |> validate_number(:price, greater_than_or_equal_to: 0)
  end
end
defmodule EctoExample.University.Schemas.Student do
  use Ecto.Schema

  import Ecto.Changeset

  alias EctoExample.University.Schemas.Enrollment

  schema "students" do
    field(:student_name, :string)
    field(:grade, :decimal)
    field(:high_school_size, :integer)
    has_many(:enrollments, Enrollment)

    timestamps()
  end

  def changeset(student, params) do
    student
    |> cast(params, [:student_name, :grade, :high_school_size])
    |> validate_required([:student_name, :grade, :high_school_size])
    |> validate_number(:high_school_size, greater_than: 0)
  end
end
defmodule EctoExample.University.Schemas.Enrollment do
  use Ecto.Schema

  import Ecto.Changeset

  alias EctoExample.University.Schemas.College
  alias EctoExample.University.Schemas.Student

  schema "enrollments" do
    field(:course, :string)
    field(:accepted, :boolean)
    field(:applied_at, :naive_datetime_usec)
    field(:accepted_at, :naive_datetime_usec)
    field(:rejected_at, :naive_datetime_usec)

    belongs_to(:college, College)
    belongs_to(:student, Student)

    timestamps()
  end

  def creation_changeset(enrollment, params) do
    enrollment
    |> cast(params, [:id, :course, :applied_at, :college_id, :student_id])
    |> validate_required([:course, :applied_at, :college_id, :student_id])
    |> foreign_key_constraint(:college_id)
    |> foreign_key_constraint(:student_id)
  end

  def acceptance_changeset(enrollment, params) do
    enrollment
    |> cast(params, [:accepted, :accepted_at])
    |> validate_required([:accepted, :accepted_at])
  end

  def rejection_changeset(enrollment, params) do
    enrollment
    |> cast(params, [:accepted, :rejected_at])
    |> validate_required([:accepted, :rejected_at])
  end
end

Inserindo registros

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

%Student{} |> Student.changeset(%{}) |> Repo.insert()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

%Student{} |> Student.changeset(%{}) |> Repo.insert!()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

%Student{}
|> Student.changeset(%{student_name: "Amy", grade: 3.9, high_school_size: 1000})
|> Repo.insert()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.College

%College{} |> College.changeset(%{}) |> Repo.insert()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.College

%College{}
|> College.changeset(%{"college_name" => "Stanford", "state" => "CA", "price" => 15000.00})
|> Repo.insert()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student
alias EctoExample.University.Schemas.College
alias EctoExample.University.Schemas.Enrollment

{:ok, student} =
  %Student{}
  |> Student.changeset(%{student_name: "Amy", grade: 3.9, high_school_size: 1000})
  |> Repo.insert()

{:ok, college} =
  %College{}
  |> College.changeset(%{college_name: "Stanford", state: "CA", price: 15000.00})
  |> Repo.insert()

%Enrollment{}
|> Enrollment.creation_changeset(%{
  course: "CS",
  student_id: 0,
  college_id: 0,
  applied_at: NaiveDateTime.utc_now()
})
|> Repo.insert()
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student
alias EctoExample.University.Schemas.College
alias EctoExample.University.Schemas.Enrollment

{:ok, student} =
  %Student{}
  |> Student.changeset(%{student_name: "Amy", grade: 3.9, high_school_size: 1000})
  |> Repo.insert()

{:ok, college} =
  %College{}
  |> College.changeset(%{college_name: "Stanford", state: "CA", price: 15000.00})
  |> Repo.insert()

%Enrollment{}
|> Enrollment.creation_changeset(%{
  course: "CS",
  student_id: student.id,
  college_id: college.id,
  applied_at: NaiveDateTime.utc_now()
})
|> Repo.insert()

Atualizando registros

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student
alias EctoExample.University.Schemas.College
alias EctoExample.University.Schemas.Enrollment

{:ok, student} =
  %Student{}
  |> Student.changeset(%{student_name: "Amy", grade: 3.9, high_school_size: 1000})
  |> Repo.insert()

{:ok, college} =
  %College{}
  |> College.changeset(%{college_name: "Stanford", state: "CA", price: 15000.00})
  |> Repo.insert()

{:ok, application} =
  %Enrollment{}
  |> Enrollment.creation_changeset(%{
    course: "CS",
    student_id: student.id,
    college_id: college.id,
    applied_at: NaiveDateTime.utc_now()
  })
  |> Repo.insert()

Enrollment.acceptance_changeset(application, %{
  accepted: true,
  accepted_at: NaiveDateTime.utc_now()
})
|> Repo.update()

Enrollment.rejection_changeset(application, %{
  accepted: false,
  rejected_at: NaiveDateTime.utc_now()
})
|> Repo.update()

Deletando registros

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

{:ok, student} =
  %Student{}
  |> Student.changeset(%{student_name: "Amy", grade: 3.9, high_school_size: 1000})
  |> Repo.insert()

Repo.delete(student)

Manipulando registros em lotes

Inserindo registros

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)

students = [
  %{
    id: 10,
    student_name: "John",
    grade: 3.9,
    high_school_size: 1000,
    inserted_at: now,
    updated_at: now
  },
  %{
    id: 11,
    student_name: "Joey",
    grade: 5,
    high_school_size: 100,
    inserted_at: now,
    updated_at: now
  }
]

Repo.insert_all(Student, students,
  on_conflict: :nothing,
  conflict_target: [:id]
)
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)

students = [
  %{
    id: 10,
    student_name: "John",
    grade: 3.9,
    high_school_size: 1000,
    inserted_at: now,
    updated_at: now
  },
  %{
    id: 11,
    student_name: "Joey",
    grade: 5,
    high_school_size: 100,
    inserted_at: now,
    updated_at: now
  }
]

Repo.insert_all(Student, students, on_conflict: :nothing, conflict_target: [:id])

Atualizando registros

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

Repo.update_all(Student, set: [high_school_size: 1000])

Deletando registros

defmodule EctoExample.University.Schemas.Student do
  use Ecto.Schema

  import Ecto.Changeset

  alias EctoExample.University.Schemas.Enrollment

  schema "students" do
    field(:student_name, :string)
    field(:grade, :decimal)
    field(:high_school_size, :integer)
    has_many(:enrollments, Enrollment, on_delete: :delete_all)

    timestamps()
  end

  def changeset(student, params) do
    student
    |> cast(params, [:student_name, :grade, :high_school_size])
    |> validate_required([:student_name, :grade, :high_school_size])
    |> validate_number(:high_school_size, greater_than: 0)
  end
end
defmodule EctoExample.University.Schemas.College do
  use Ecto.Schema

  import Ecto.Changeset

  alias EctoExample.University.Schemas.Enrollment

  schema "colleges" do
    field(:college_name, :string)
    field(:state, :string)
    field(:price, :decimal)

    has_many(:enrollments, Enrollment, on_delete: :delete_all)

    timestamps()
  end

  def changeset(college, params) do
    college
    |> cast(params, [:college_name, :state, :price])
    |> validate_required([:college_name, :state, :price])
    |> validate_number(:price, greater_than_or_equal_to: 0)
  end
end
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student
alias EctoExample.University.Schemas.Enrollment

Repo.delete_all(Enrollment)
Repo.delete_all(Student)

Multi

alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

{:ok, college} =
  %College{}
  |> College.changeset(%{college_name: "Stanford", state: "CA", price: 15000.00})
  |> Repo.insert()

Repo.transaction(fn ->
  case %Student{}
       |> Student.changeset(%{student_name: "Amy", grade: "6.0", high_school_size: 1000})
       |> Repo.insert() do
    {:ok, student} ->
      if Decimal.cmp(student.grade, 5) == :lt do
        Repo.rollback({:validate_student_grade, {student, :invalid_student_grade}})
      else
        %Enrollment{}
        |> Enrollment.creation_changeset(%{
          course: "CS",
          student_id: student.id,
          college_id: college.id,
          applied_at: NaiveDateTime.utc_now()
        })
        |> Repo.insert()
      end
  end
end)
alias EctoExample.University.Repo
alias EctoExample.University.Schemas.Student

{:ok, college} =
  %College{}
  |> College.changeset(%{college_name: "Stanford", state: "CA", price: 15000.00})
  |> Repo.insert()

multi =
  Ecto.Multi.new()
  |> Ecto.Multi.run(:create_student, fn _, _ ->
    %Student{}
    |> Student.changeset(%{student_name: "Amy", grade: "6.0", high_school_size: 1000})
    |> Repo.insert()
  end)
  |> Ecto.Multi.run(:validate_student_grade, fn _repo, %{create_student: student} ->
    if Decimal.cmp(student.grade, 5) == :lt do
      {:error, :invalid_student_grade}
    else
      {:ok, :valid_student_grade}
    end
  end)
  |> Ecto.Multi.run(:create_application, fn _repo, %{create_student: student} ->
    %Enrollment{}
    |> Enrollment.creation_changeset(%{
      course: "CS",
      student_id: student.id,
      college_id: college.id,
      applied_at: NaiveDateTime.utc_now()
    })
    |> Repo.insert()
  end)

Repo.transaction(multi)

Referências: