spira
spira copied to clipboard
Spira.repository unavailable in Rails controller
I'm getting the following error when I try to reference a Spira::Base
in a Rails (3.2.14) controller:
Spira::NoRepositoryError
I'm using the current master
version of this gem. I'm currently setting the repository in an initializer. Presumably this error is related to the new repository threadsafe feature, as I can access Spira.repository
and my Spira::Base
objects just fine from Rails console.
I can get around this by doing (in my controller):
before_filter do
Spira.repository ||= RDF::DataObjects::Repository.new('sqlite3:test.db')
end
but I don't want to have to do this. Is there some way to make the repository play nice with Rails controllers, or is there a better/recommended place to define my repository where this won't be an issue?
@kardeiz sorry for the late response.
Indeed the threadsafe feature makes the initialization useless since each request creates a new thread. It is very practical when filling RDF repositories in a multithread env.
Since you only use a single repository in your case, I could add a new way to set it, like:
Spira.global_repository = RDF::DataObjects::Repository.new('sqlite3:test.db')
Spira.repository will have precedence on Spira.global_repository on the queries. This way we still can work on another repositories in a specific thread.
@cordawyn, @gkellogg : are you okay with this approach ?
I think we should try and follow Rails approach to persistent DB connections (or even reuse their database connection pool and related classes and architecture, if possible). I'll have to look it up in the Rails code though -- it's been some time since I dug into the Rails core that deep. But off the top of my head, the before_filter
solution doesn't sound that bad, considering the "stateless" nature of HTTP.
Anyway, I'll update you on my findings in a couple of days, I guess.
@abrisse I would like to have a global_repository, since I'm using it as a single readonly dataset for my app.
Workaround: load it in a middleware:
lib/spira_repo_injector.rb
:
require 'spira'
require 'sparql'
class SpiraRepoInjector
def initialize(app)
@app = app
end
def call(env)
Spira.repository = RDF::DataObjects::Repository.new('sqlite3:test.db')
@app.call(env)
end
end
config/application.rb
:
require "./lib/spira_repo_injector"
module MyApp
class Application < Rails::Application
config.middleware.unshift SpiraRepoInjector
end
end
My original issue is almost 5 years old, and I no longer use this library. But what benefit is there to putting this in a middleware? It calls Repository.new
for every single request, even when the action may not require connecting to Spira.repository
. I don't know everything involved with Repository.new
, but it probably makes a database connection and other potentially costly calls. At least with :before_filter
one can control which controllers load the Spira repository.
But shouldn't connection pooling be handled upstream, probably in the specific database adapters in RDF::DataObjects::Repository
?
In any case, if I were still using this library, I would be tempted to just monkey patch Spira
:
module Spira
class << self
def repository; @repository; end
def repository=(v); @repository = v; end
end
end