I’m evaluating using ROM instead of Sequel for a new project, and I have run into a problem: we have specifications and targets. Each specification can have many targets, and each target can have many specifications.
To model that, I am using a specifications_targets table, which worked great in pure Sequel.
But when I am trying to associate an existing specification to an existing target, the only code that I have gotten to work so far seems way to complicated for what I am trying to achieve:
require "rom"
require "rom-changeset"
require "rom-sql"
require "rom-repository"
require "logger"
rom = ROM.container(:sql, "sqlite::memory") do |config|
config.gateways[:default].use_logger(Logger.new($stdout))
config.default.create_table(:specifications) do
primary_key :id
column :name, String, null: false
end
config.default.create_table(:targets) do
primary_key :id
column :title, String, null: false
end
config.default.create_table(:specifications_targets) do
foreign_key :specification_id, :specifications
foreign_key :target_id, :targets
end
config.relation(:specifications_targets) do
schema(infer: true) do
associations do
belongs_to :specification
belongs_to :target
end
end
end
config.relation(:specifications) do
schema(infer: true) do
associations do
has_many :specifications_targets
has_many :targets, through: :specifications_targets
end
end
end
config.relation(:targets) do
schema(infer: true) do
associations do
has_many :specifications_targets
has_many :specifications, through: :specifications_targets
end
end
end
end
specifications = rom.relations[:specifications]
targets = rom.relations[:targets]
spec1 = specifications.changeset(:create, name: "Spec 1").commit
target1 = targets.changeset(:create, title: "Target 1").associate(spec1, :specifications).commit
spec2 = specifications.changeset(:create, name: "Spec 2").commit
specifications.by_pk(2).changeset(:update, spec2).associate(target1, :targets).commit
Is there a way to just associate an existing entry to another existing entry, without a basically no-op changeset in between?
Also, how would I go about unassociating an entry?
I guess I could use the specifications_targets relation directly, but that seems more cumbersome than I would expect from an abstraction layer.