【问题标题】:Rails Autocomplete works locally but not on Heroku, probably MySQL / Postgre issueRails Autocomplete 在本地工作,但不能在 Heroku 上工作,可能是 MySQL / Postgre 问题
【发布时间】:2012-01-28 21:13:57
【问题描述】:

我正在使用 rails3-jquery-autocomplete gem 在我的 rails 3 应用程序的表单中自动完成字段(产品)。用户可以键入产品名称或产品代码,它们都是产品表中的字符串列。 在本地一切正常,但在 heroku 上,ajax 请求因标准 500 heroku 错误而崩溃:

We're sorry, but something went wrong (500)

我认为这可能是 postgre / sql 问题 - 我在本地使用 mysql 进行开发,但 heroku 在 postgre sql 数据库上运行,并且我在通过 ajax 自动完成请求调用的函数中执行以下查询:

  def get_autocomplete_items(parameters)
    items = Product.select("DISTINCT CONCAT_WS(' ', product_code, title, id) AS full_name, product_code, title, id").where(["CONCAT_WS(' ', product_code, title) LIKE ?", "%#{parameters[:term]}%"])
  end

在本地,这将返回一个 json 格式的数组,包括所有匹配的 produc_ids 和名称:

[{"id":"9","label":"xt-pnt-dress_45 - Catherine Malandrino","value":"xt-pnt-dress_45 - Catherine Malandrino"}, ... ]

如果有人知道如何更改符合 heroku 或任何其他想法的查询,我将不胜感激。谢谢。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 postgresql autocomplete heroku


    【解决方案1】:

    Heroku 使用PostgreSQL 8.3 for shared databases and 9.0 for dedicated databasesversion 8.3version 9.0 都没有 concat_ws 函数,该函数仅在 version 9.1+ 中可用。

    您可以手动连接字符串:

    items = Product.select("DISTINCT product_code || ' ' || title || ' ' || id AS full_name, product_code, title, id").where(["product_code || ' ' || title LIKE ?", "%#{parameters[:term]}%"])
    

    只要product_codetitleid 都不为 NULL,这将起作用。如果您可能有 NULL,那么您可以将它们包装成 COALESCE(例如 COALESCE(product_code || ' ', ''))以将它们变成空字符串。

    或者,您可以在 Ruby 中处理 full_name

    def full_name
        [product_code, title, id].reject(&:blank?).join(' ')
    end
    

    并为 LIKE 生成单独的列或使用 LIKE 检查两个列:

    where('product_code LIKE ? OR title LIKE ?', "%#{parameters[:term]}%", "%#{parameters[:term]}%")
    where('produce_code LIKE :pat OR title LIKE :pat', :pat => "%#{parameters[:term]}%")
    

    此外,您应该知道 MySQL 的 LIKE 不区分大小写,但 PostgreSQL 的则不区分大小写,因此您可能希望将所有内容小写以避免混淆:

    where('LOWER(product_code) LIKE :pat OR LOWER(title) LIKE :pat', :pat => "%#{parameters[:term].downcase}%")
    

    由于|| is a logical-OR in MySQL,在Ruby 中加入三个字符串(即def full_name)并使用单独的小写LIKE 检查product_codetitle 可能是最简洁的可移植解决方案。

    将您的开发环境切换到 PostgreSQL 也是一个好主意,将版本与您的部署环境相匹配也是一个好主意。还有其他一些差异会导致麻烦。

    【讨论】:

    • 感谢您提供详细的答案 - 它不仅有效,而且还提供了有关该主题的大量背景信息以及一些最佳实践技巧 - 超级棒!
    • 我所强调的一件事是,如果我创建一个连接字符串标题和产品代码的虚拟属性,例如'full_name' 我想搜索它,我得到一个 'ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'full_name' in 'where 子句': SELECT products.* FROM products WHERE (LOWER(full_name ) LIKE '%ib%')' 错误..
    • @frank:另一种选择是将您的可搜索列连接在一起(此处将使用before_save 回调),然后您就可以搜索那堆。
    猜你喜欢
    • 2012-04-01
    • 1970-01-01
    • 2012-06-18
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 2014-01-14
    • 1970-01-01
    相关资源
    最近更新 更多