elt547
Can I fake a polymorphic association with a virtual schema field?
So I’ve opted for the “easy method” of polymorphic associations, where you have a column for each possible polymorphic type. That’s the database implementation, but now I’m wondering what to do on the schema implementation.
The table looks something like this:
Table inbox_items {
id int [pk]
profile_id int [ref: <> profiles.id]
post_id int [ref: < posts.id]
poll_id int [ref: < posts.id]
comment_id int [ref: < comments.id]
}
Is there a way for me to add a virtual field to the schema so that I can cast to and from the correct column? That way I could just create it like %InboxItem{association: %Post{}} and it would know to save the id to the post_id column. Similarly can I make it able to respond to something like Repo.preload(inbox_item, :association) so I can fill the virtual field when loading?
Most Liked
elt547
Yeah, it’s the first method shown in the guide. It’s really just one workaround or another, because the polymorphic association is what I need more or less. Do you have any alternative suggestions? I tried the many-to-many method and it was a nightmare, and the guides are remarkably incomplete on the subject.
I read a few blog posts but they all recommended against the more complex approaches. I had implemented the many-to-many and it was awful, and I considered table inheritance in postgres but was advised against it.
Actually almost my entire domain has these kinds of relationships. I really shouldn’t be using a relational db but I really wanted to use elixir, and I have limited graph db experience so I don’t want to deal with more learning since I’m on a time crunch to get my mvp shipped.
MRdotB
https://mrdotb.com/posts/ecto-exclusive-belongs-to-aka-arc/
What about exclusive belongs to. You make your inbox_items hold fk for all your other models
MRdotB
# you want to left_join and preload the fields
query =
from(
item in InboxItem,
left_join: post in assoc(item, :post),
left_join: poll in assoc(item, :poll),
left_join: comment in assoc(item, :comment),
preload: [
post: post,
poll: poll,
comment:comment
]
)
items = Repo.all(query, opts)
# I don't think it will be possible to set the virtual_field in the ecto query
# You can do something like below to set it but I think this part should be done
# in the view
Enum.map(items, fn item ->
model =
cond do
is_binary(item.post_id) ->
item.post
is_binary(item.poll_id) ->
item.comment
is_binary(item.comment_id) ->
item.comment
end
# add the model to the virtual field manually
%{item | virtual_field: model}
end)
Last Post!
Kurisu
Hypothetically speaking, if we can write a query that preload the good association by finding the one that is not nil, could we use something like :
select_merge: %{virtual_field: preload_querry()}
I have no idea of how to write that hypotheticall preload_querry though…
Popular in Questions
Other popular topics
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
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









