I was just working on upserting records and was surprised to see that upsert in rom-sql does not support multiple records at once. My assumption was that the command would support multiple entities at once like the other commands. (ROM::SQL::Relation::Writing#upsert seems to imply that multiple values are supported, but I think the PostgreSQL command module changes the behavior.)
My solution was multi_insert with the insert_conflict options (for PostgreSQL). Is this the proper approach, or did I miss the way to do this more simply with a changeset or relation command?
module Repositories
class TickerValues < ::ROM::Repository[:ticker_values]
def upsert(values)
ticker_values.dataset.insert_conflict(
constraint: :idx_ticker_values_uniq,
update: {
value: :excluded__value,
updated_at: :excluded__updated_at
}
).multi_insert(values)
end
end
end
P.S. I discovered that rom-sql is not compatible with Sequel 5+ because in this instance the update hash syntax specified in the example above does not work beyond Sequel 4. Will Sequel 5 support be released before ROM 5.0?
I discovered that rom-sql is not compatible with Sequel 5+ because in this instance the update hash syntax specified in the example above does not work beyond Sequel 4
AFAIK itâs not an issue with ROM, symbol splitting is disabled by default in Sequel 5. You can enable it manually, or use the preferred method like this:
I use bulk upsert via the command interface. It works almost fine except that bulk upserts generate multiple inserts statements (I use ROM via hanami-model which is locked on rom v3.3, I havenât tried it with more recent rom versions yet).
Thanks for the info @smaximov. Iâm going to work on my first Hanami project shortly and was going to use ROM directly instead of hanami-model. Any benefits to using the model?
I didnât use bare ROM much but I think itâs more mature at the moment. hanami-model is just a thin wrapper around ROM anyway. And if you want to use new ROM features, you are out of luck.
Another argument in favor of using ROM directly: hanami-modelâs associations story is far from complete and it doesnât allow to leverage ROM for features it doesnât yet support. This a problem Iâve stumbled upon today (copy-pasted from the Hanami Gitter):
Consider the problem: given the following table definition:
create table users (
id bigserial primary key,
email text not null unique,
ref_id bigint references users(id), -- referral user ID
);
suppose I want to fetch the email of the user with ID = 42 along with the email of their referral:
select users.id as id,
users.email as email,
referrals.id as ref_id,
referrals.email as ref_email
from users
join users as referrals on users.ref_id = referrals.id
where users.id = 42;
But I canât make it work to return columns of the aliased relation (referrals), because hanami-modelâs select doesnât accept Sequal expressions:
...
.select(Sequel[:referrals][:id].as(:ref_id))
causes the following error: âNoMethodError: undefined method âprimary_key?â for #Sequel::SQL::AliasedExpression:0x00007fdb03b8cff0â. It seems like select accepts either Symbols or ROM attributes. But I canât build ROM attributes for the referrals relation, users.as(:referrals)[:id].as(:ref_id) causes âROM::MapperMissingError: referralsâ, because the relation is not registered and it cannot be registered because hanami-model doesnât yet support it.
I donât know, maybe it can be solved using hanami-model at the moment, but itâs far from obvious in that way.
From what I can tell, Hanami tends to build its own opinionated abstraction on top of things like ROM rather than add a thin layer on top and then let you get at the ROM internals directly for more sophisticated work. I much prefer a thin layer that makes ROM fit more naturally into whatever a framework like Hanami wants to facilitate, but not try to recreate their own classes for all concepts. I was looking at the internals of Hanami and it looks like all Hanami and itâs not immediately obvious that ROM is under the hood. That approach makes it harder to maintain Hanami (to mirror ROM things) and harder to extend (accessing internals of Hanami such as ROM).
Iâm going to use ROM since I donât see a benefit of being bound to Hanamiâs models. I can imagine that I might end up with some sort of abstraction later to get my ROM implementation to work better with Hanami, but will see â still getting my head around ROM.
After playing with hanami-model for some time, I have chosen the same path, i.e. working with ROM directly. I have created a mini project that shows how to integrate Hanami with ROM. There are some issues you have to be aware of (e.g. hanami withouth hanami-model and ROM both define the same rake db:migrate task).