Hello,
I am trying to build a web-app prototype with Hanami 2.0 and as part of that I am trying to utilize ROM Repositories. Below shown is the relevant code snippet for a question I have:
# startup_template/slices/admin/repository.rb
# auto_register: false
# frozen_string_literal: true
require 'rom-repository'
module Admin
class Repository < ROM::Repository
end
end
# startup_template/slices/admin/repositories/doctor_repository.rb
module Admin
module Repositories
class DoctorRepository < ::Admin::Repository
commands :create, update: :by_pk, delete: :by_pk
end
end
end
I was trying to use that repository from hanami console but I encountered an error. Please see below the console output.
startup_template$ HANAMI_ENV=test bundle exec hanami console
startup_template[test]> Admin::Repositories::DoctorRepository.new
KeyError: key not found: :container
from /home/jignesh/.rvm/gems/ruby-3.1.2@startup-template-hanami-2-0/gems/rom-repository-5.3.0/lib/rom/repository/class_interface.rb:53:in 'fetch'
startup_template[test]>
Checking the source code at rom/class_interface.rb at v5.3.0 · rom-rb/rom · GitHub
the error is being raised by options.fetch(:container)
and the solution is to pass ROM container to Admin::Repositories::DoctorRepository.new
which works as can be seen in console output shown below:
startup_template[test]> Hanami.app.start(:persistence)
=> StartupTemplate::Container
startup_template[test]> rom_container = container['persistence.rom']
startup_template[test]> Admin::Repositories::DoctorRepository.new(rom_container)
=> #<Admin::Repositories::DoctorRepository struct_namespace=ROM::Struct auto_struct=true>
startup_template[test]>
But I was trying to override the class method new
in my base class Admin::Repository
so as to do something like following
module Admin
class Repository < ROM::Repository
def self.new
rom_container = Hanami.app['persistence.rom']
super(rom_container)
end
end
end
but the overridden new
method doesn’t get invoked and I always end up seeing the following error
KeyError: key not found: :container
from /home/jignesh/.rvm/gems/ruby-3.1.2@startup-template-hanami-2-0/gems/rom-repository-5.3.0/lib/rom/repository/class_interface.rb:53:in 'fetch'
implying the new method defined at rom/class_interface.rb at v5.3.0 · rom-rb/rom · GitHub
is getting invoked.
I tried simulating the class and module structure in a standalone ruby script like
module ROM
class Repository
module ClassInterface
def new(opts={})
opt_1 = opts.fetch(:opt_1)
puts ">>>>>>> ROM::Repository::ClassInterface new"
end
end
end
end
module ROM
class Repository
extend ClassInterface
end
end
module Admin
class Repository < ROM::Repository
def self.new
puts ">>>>> Admin::Repository new"
super
end
end
end
module Admin
module Repositories
class DoctorRepository < ::Admin::Repository
end
end
end
Admin::Repositories::DoctorRepository.new
and running that script the overridden version of new
method does get invoked as can be seen in the output below
jignesh@j-home-pc:~/Desktop$ ruby test-3.rb
>>>>> Admin::Repository new
test-3.rb:5:in `fetch': key not found: :opt_1 (KeyError)
from test-3.rb:5:in `new'
from test-3.rb:25:in `new'
from test-3.rb:39:in `<main>'
So is there something special going on with the inheritance in my Hanami-based classes I shown above which is preventing the overridden new method in Admin::Repository
from getting invoked or the behaviour is being caused in the manner ROM Repository related classes are defined?
Thanks.