-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Hi! I really like how Memento casts table results into the Memento.Table module's struct, though I've run into a couple situations where I need to sacrifice distinct struct fields to take advantage of partial key-matching. For example, I have some ordered_set Tables that look a bit like this:
defmodule MyApp.Message do
use Memento.Table,
# where :room_id_and_sent_at is stored as a tuple, {room_id, sent_at}
attributes: [:room_id_and_sent_at, :content, :sender],
type: :ordered_set
endIf I want to query messages in a particular room by sent_at, I've learned that by grouping those two columns into a tuple, I can write a match spec that limits the search space to a particular constant room ID like this:
match_head =
MyApp.Message.__info__().query_base
|> put_elem(1, {"some_room_id", :_})
match_spec = [{match_head, [], [:"$_"]}]
Memento.transaction!(fn -> Memento.Query.select_raw(MyApp.Message, match_spec) end)The downside is that, what could be separate :room_id and :sent_at fields on the struct, have to be combined into one field, and accessing them becomes a bit of a pain. I think the DX could be improved, though I wanted to see if you have thoughts on what that might look like. One idea I had was to adjust the :attributes option in use Memento.Table to take a nested list, like this:
defmodule MyApp.Message do
use Memento.Table,
attributes: [[:room_id, :sent_at], :content, :sender],
type: :ordered_set
endI believe that would give Query.Data.load/1 + dump/1 enough context to know how to "nest" those fields in the records, and "unnest" them when casting to the struct.
Another path might be to define a @behaviour for Memento.Table with optional encode/decode callbacks that would take the place of Query.Data.load/1 + dump/1 if the user implements them. I like this option less because users have to do more work, though it's more flexible and could accommodate many use-cases (e.g. calculating "virtual fields" from the record data to add to the struct might be neat)