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
Maybe try replacing it with
many_to_many :products, Product, join_through: A.UserProduct
3
Popular in Questions
can someone please explain to me how Enum.reduce works with maps
New
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
The Elixir Typespec docs show the following syntax for keyword lists in typespecs:
# ...
| [key: type] # keyword lists...
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set?
Thanks.
New
Hello, I get Persian date from my client and convert it to normal calendar like this:
def jalali_string_to_miladi_english_number(persi...
New
Hi,
I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar.
I p...
New
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
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
Other popular topics
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch.
This project took far...
New
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Hey all,
I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
Hi everyone,
One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
Hello everybody,
usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
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...
New
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









