Casecommons / pg_search

pg_search builds ActiveRecord named scopes that take advantage of PostgreSQL’s full text search
http://www.casebook.net
MIT License
1.31k stars 370 forks source link

ActiveRecord::StatementInvalid: PG::Error: ERROR: relation "pg_search_documents" does not exist #95

Open uberllama opened 11 years ago

uberllama commented 11 years ago

Its been a long day, so I may be missing something completely obvious, but I ran into this very strange error today.

I have two models named User and Document that both have search scopes. A user has many documents.

I wanted to add a method to user to get all documents available in his network. It looked something like this:

user.rb

include PgSearch

has_many :documents

  pg_search_scope :search,
    :against => [:name],
    :using => {
      :tsearch => {
        :dictionary => "english",
        :prefix => true,
        :any_word => true
      }
    }

def network_documents
  Document.where(:user_id => followings.collect(&:followed_user_id))
end

So that I can call something like:

current_user.network_documents

Normal enough right? However, any time I try to add a method to the User or Document model that refers to Document, I get the error listed in the issue subject along with a stack trace that looks like this:


LINE 5:              WHERE a.attrelid = '"pg_search_documents"'::reg...
                                        ^
:             SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
              FROM pg_attribute a LEFT JOIN pg_attrdef d
                ON a.attrelid = d.adrelid AND a.attnum = d.adnum
             WHERE a.attrelid = '"pg_search_documents"'::regclass
               AND a.attnum > 0 AND NOT a.attisdropped
             ORDER BY a.attnum

    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `async_exec'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `exec_no_cache'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:662:in `block in exec_query'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activesupport-3.2.12/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:661:in `exec_query'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:1278:in `column_definitions'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/postgresql_adapter.rb:857:in `columns'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/connection_adapters/schema_cache.rb:12:in `block in initialize'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/model_schema.rb:228:in `yield'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/model_schema.rb:228:in `default'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/model_schema.rb:228:in `columns'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/model_schema.rb:237:in `columns_hash'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/locking/optimistic.rb:129:in `locking_enabled?'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/relation.rb:170:in `exec_queries'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/relation.rb:160:in `block in to_a'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/explain.rb:33:in `logging_query_plan'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/relation.rb:159:in `to_a'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/relation/finder_methods.rb:159:in `all'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/activerecord-3.2.12/lib/active_record/querying.rb:5:in `all'
    from /Users/uberllama/Documents/webdev/littleblimp/taughtit/app/models/user.rb:71:in `foo'
    from (irb):21
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.12/lib/rails/commands/console.rb:47:in `start'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.12/lib/rails/commands/console.rb:8:in `start'
    from /Users/uberllama/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.12/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'

If I remove the include and search scope, everything runs fine as expected. I tried adding the method as a class method to the Document class with the same result.

What the hell am I missing? Cheers.

uberllama commented 11 years ago

I tried doing the same thing with my Comment model and didn't encounter any issues, which leads me to believe there's a reserved term issue with models named "Document" and pg_search.

uberllama commented 11 years ago

Finally had time to open up the lib and there it is, Document as an un-namespaced class. Would there be any chance of either namespacing this under PgSearch or renaming it to something like SearchDocument?

inertialbit commented 11 years ago

I am pretty sure that the included AR document class is already name spaced as PgSearch::Document.

Do you get the same error if you try to access your own Document class from the top-level? e.g.

class User < ActiveRecord::Base
  include PgSearch

  def network_documents
    ::Document.where(...) # note the 2 colons in front
  end
end
uberllama commented 11 years ago

It is name spaced, but as soon as you include PgSearch the name spacing is rendered moot. I've submitted pull request 96 that renames the class to something less generic, to avoid any possibility of conflict.

inertialbit commented 11 years ago

Ok. But renaming PgSearch::Document to PgSearch::SearchDocument will work until someone has a model named SearchDocument in a similar scenario to your Document. In other words there is still possibility for conflict unless one uses an absolute reference to the constant. So prefixing :: to Document should give you the behavior you're after unless there is something else going on.

uberllama commented 11 years ago

You're right, but that is a more specific, less likely scenario, especially in an environment where pg_search is being used. We could go as far as naming it PGSearchDocument to be sure. I've been involved in a lot of projects involving file uploading/management and there's almost always an AR model named Document. This is actually the first time I've run into a class name conflict from a gem, so not sure if there's a different solution to including PgSearch and exposing its own Document class.

nertzy commented 11 years ago

Copying over comment from #96 that is also relevant here:

I'd rather work towards removing the need for an Active Record model to live in PgSearch at all. I don't want to break existing code that might assume the PgSearch::Document class is there.

Let's move toward a generator that generates models that the developer chooses the name for, and remove the idea of a single "Document" class once and for all.

There's a discussion going on over at #92 towards this.

lucaspiller commented 8 years ago

I've also been hit by this a few times, as the issue is still present three years later. It would be great to see a fix for this.

BojanOro commented 6 years ago

After spending a good three hours trying to track down why this was happening to me, I'd also like to chip in and say this should rename into something a bit less generic.