4

根据这个问题的公认答案,您应该能够使用实例方法的返回值作为反对参数......

class Car < ActiveRecord::Base
  include PgSearch
  multisearchable :against => [:name, manufacturer_name]
  belongs_to :manufacturer

  def manufacturer_name
   manufacturer.name
  end
end

但是,当我尝试在具有上述模型、db 等创建的干净应用程序中执行此操作(以排除实际应用程序中的冲突代码)时,我得到一个未定义的局部变量或方法错误 - 我错过了什么?

4

1 回答 1

3

好的,简短的故事是链接帖子中提供的代码不能也不能工作,因为它看起来好像您不能以这种方式引用方法(实例或其他方式) - 这是有道理的:该类需要按顺序编译使该方法可用,但不能,因为它需要所述方法才能进行编译。

为了实现我最初尝试的目标(不覆盖 pg_search),我采取了以下步骤:

首先,反对声明应该使用一个符号来代替原来的方法调用。

multisearchable :against => [:name, :manufacturer_name]

完成后,当保存对象时,将使用该manufacturer_name方法创建/更新 PgSearch::Document。但是,如果您尝试重建搜索索引并出现以下错误,这将中断:

ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column cars.manufacturer_name does not exist
  LINE 5: ...sce("cars".name::text, '') || ' ' || coalesce("cars"...
                                                           ^
: INSERT INTO "pg_search_documents" (searchable_type, searchable_id, content, created_at, updated_at)
  SELECT 'Car' AS searchable_type,
         "cars".id AS searchable_id,
         (
           coalesce("cars".name::text, '') || ' ' || coalesce("cars".manufacturer_name::text, '')
         ) AS content,
         '2014-01-29 14:08:00.190767' AS created_at,
         '2014-01-29 14:08:00.190767' AS updated_at
  FROM "cars"

要解决此问题,请覆盖 Multisearch 模块添加的 rebuild_pg_search_documents 类方法,以构建动态 SQL 插入查询,而不是回复现有的纯 SQLINSERT INTO table_name (columns) SELECT etc查询:

def self.rebuild_pg_search_documents
  cars = Car.all

  query_str = 'INSERT INTO pg_search_documents (searchable_type, searchable_id, content, created_at, updated_at) VALUES'

  cars.each do |car|
    query_str += "('Car', #{car.id}, '#{car.name} #{car.manufacturer_name}', NOW(), NOW())"

    query_str += ', ' unless car == cars.last
  end

  query_str += ';'

  connection.execute query_str
end

希望这会对其他人有所帮助。

于 2014-01-29T03:23:15.540 回答