ruby-rdf / spira

Spira is a framework for viewing RDF data as model objects
http://rubygems.org/gems/spira
The Unlicense
58 stars 36 forks source link

Spira.repository unavailable in Rails controller #29

Open kardeiz opened 10 years ago

kardeiz commented 10 years ago

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?

abrisse commented 10 years ago

@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 ?

cordawyn commented 10 years ago

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.

Hampei commented 9 years ago

@abrisse I would like to have a global_repository, since I'm using it as a single readonly dataset for my app.

mike-burns commented 6 years ago

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
kardeiz commented 6 years ago

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