trashyEx

trashyEx

Ecto: many_to_many timestamps

Hello,

How do I use correctly the many_to_many association with timestamps?

I suppose it uses insert_all (or update_all) under the put_assoc and it is the reason it doesn’t provide inserted_at and modified_at.

The schemas:

defmodule A.User do
  use Ecto.Schema
  import Ecto.Changeset

  alias A.Product

  schema "users" do
    field :name, :string

    many_to_many :products, Product, join_through: "users_products"

    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

defmodule A.Product do
  use Ecto.Schema
  import Ecto.Changeset


  schema "products" do
    field :name, :string

    timestamps()
  end

  @doc false
  def changeset(product, attrs) do
    product
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

defmodule A.UserProduct do
  use Ecto.Schema
  import Ecto.Changeset

  alias A.User
  alias A.Product

  schema "users_products" do
    belongs_to :user, User
    belongs_to :product, Product

    timestamps()
  end

  @doc false
  def changeset(user_product, attrs) do
    user_product
    |> cast(attrs, [])
    |> validate_required([])
  end
end

The users_products migration:

  def change do
    create table(:users_products) do
      add :user_id, references(:users, on_delete: :nothing)
      add :product_id, references(:products, on_delete: :nothing)

      timestamps()
    end

    create unique_index(:users_products, [:user_id, :product_id])
    create index(:users_products, [:user_id])
    create index(:users_products, [:product_id])
  end

The association:

IO.puts("querying")
product = from q in Product,
  where: q.name == ^product_name
product = Repo.one(product)
IO.inspect(product, label: "product:")

IO.puts("querying")
user = from q in User,
  where: q.name == ^user_name,
  preload: :products
user = Repo.one(user)
IO.inspect(user, label: "user:")

if product != nil and user != nil do
  cs = Ecto.Changeset.change(user)
  cs = Ecto.Changeset.put_assoc(cs, :products, [product | user.products])
  IO.inspect(cs, label: "assoc put")
  Repo.update!(cs)
end

The error:

[debug] QUERY OK db=0.2ms queue=0.1ms
begin []
[debug] QUERY ERROR db=9.2ms
INSERT INTO "users_products" ("product_id","user_id") VALUES ($1,$2) [1, 1]
[debug] QUERY OK db=0.1ms
rollback []
** (Postgrex.Error) ERROR 23502 (not_null_violation): null value in column "inserted_at" violates not-null constraint

    table: users_products
    column: inserted_at

Failing row contains (4, 1, 1, null, null).

I am up with other ways to achieve this. I don’t mind to use more explicit forms, but I need flexibility to add/remove/modify the associations, for example something like:

# Check if exists
up = from q in UserProduct,
  where: q.user == ^user.id and q.product == ^product.id
up = Repo.one(up)
IO.inspect(up, label: "user_product")
# Create an association
up = Products.create_user_product(%{"user_id" => 1, "product_id" => 2})
Repo.insert!(up)

But it says UserProduct contains virtual fields (belongs_to), and I don’t know if it is natural to change it to field when they don’t belong in UserProduct but User and Product.

Most Liked

idi527

idi527

Maybe try replacing it with

many_to_many :products, Product, join_through: A.UserProduct

Where Next?

Popular in Questions Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
clayschick
I'm trying to create a simple query to select distinct values from a column. If I only use select and distinct I get back a list of uniqu...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement