【问题标题】:ransack using ransacker for integer to_char使用 ransacker 对整数 to_char 进行洗劫
【发布时间】:2014-08-05 05:10:19
【问题描述】:

我正在尝试使用 ransacker 方法将我的字段之一从整数转换为字符串

ransacker :invoice_no do
  Arel.sql("to_char(invoice_no, '9999999')")
end

我正在使用 PostgeSQL 9.1,并且我已经在 psql 中手动测试过,如下所示,效果很好

select to_char(invoice_no, '9999999') AS invoice_no from invoices;

我在尝试使用 :invoice_no_cont 搜索 ransack 时遇到的错误是

  Invoice Load (1.3ms)  SELECT "invoices".* FROM "invoices" WHERE "invoices"."ledger_id" = 2 AND (to_char(invoice_no, '9999999') ILIKE 0) ORDER BY invoice_no desc LIMIT 10 OFFSET 0
PG::UndefinedFunction: ERROR:  operator does not exist: text ~~* integer
LINE 1: ...edger_id" = 2 AND (to_char(invoice_no, '9999999') ILIKE 0) O...
                                                             ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT  "invoices".* FROM "invoices"  WHERE "invoices"."ledger_id" = 2 AND (to_char(invoice_no, '9999999') ILIKE 0) ORDER BY invoice_no desc LIMIT 10 OFFSET 0
  Rendered invoices/index.json.rabl (3.6ms)
Completed 500 Internal Server Error in 12.3ms

ActiveRecord::StatementInvalid - PG::UndefinedFunction: ERROR:  operator does not exist: text ~~* integer
LINE 1: ...edger_id" = 2 AND (to_char(invoice_no, '9999999') ILIKE 0) O...
                                                             ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT  "invoices".* FROM "invoices"  WHERE "invoices"."ledger_id" = 2 AND (to_char(invoice_no, '9999999') ILIKE 0) ORDER BY invoice_no desc LIMIT 10 OFFSET 0:
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract_adapter.rb:285:in `rescue in log'
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract_adapter.rb:280:in `log'
  activerecord (3.2.17) lib/active_record/connection_adapters/postgresql_adapter.rb:659:in `exec_query'
  activerecord (3.2.17) lib/active_record/connection_adapters/postgresql_adapter.rb:1262:in `select'
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract/query_cache.rb:61:in `block in select_all'
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract/query_cache.rb:75:in `cache_sql'
  activerecord (3.2.17) lib/active_record/connection_adapters/abstract/query_cache.rb:61:in `select_all'
  activerecord (3.2.17) lib/active_record/querying.rb:38:in `block in find_by_sql'

更新

我在 AngularJS 视图中使用 invoice_no_cont,就像这样。

<td data-title="'Invoice No.'" sortable="'invoice_no'" filter="{'invoice_no_cont':'text'}">
      {{invoice.invoice_no}}
</td>

这是通过 'GET' 请求传递给 Ruby on Rails 服务器 invoice#index 方法的,然后该方法将其拾取并通过 ransack 发送。

 @invoices = Invoice.search(params[:filter]).result

【问题讨论】:

  • 看起来 postgres 抱怨您正在将文本与整数进行比较。我认为您的问题是查询中的 'to_char(invoice_no, '9999999') ILIKE 0' 部分。 to_char 为您提供一个字符串,但您将其与 0(一个整数)进行比较。您在哪里使用 invoice_no_cont?更多细节将有助于解决您的问题。

标签: ruby-on-rails postgresql ransack


【解决方案1】:

这是我对您的问题的解释:

  1. 您的发票编号仅由整数组成
  2. 您有一个搜索字段正在使用 angular.js 将输入的值作为文本发送到服务器
  3. 您希望在 search(params[:filter]) 方法调用中注入一个字符串
  4. 您使用 ransacker 来处理您认为是字符串的 params[:filter]

您忘记了,当您将 JSON 数据发送回 Rails 服务器时,它会解析 JSON 有效负载。尽管您认为您正在返回一个字符串,但 json gem 会解析该值并看到一个整数,如 gem's parser documentation 中所述。

这意味着即使你认为你得到一个字符串,params 哈希实际上得到一个整数作为过滤键的值,这就是:

operator does not exist: text ~~* integer

在抱怨。 Postgres 期望与字符串进行比较,而不是整数。

简单的解决方法是将 to_s 添加到控制器中的 params[:filter]。

@invoices = Invoice.search(params[:filter].to_s).result

这样可以确保始终将字符串比较在一起。这也是对作为过滤器发送的输入进行容错的好方法。

你也可以不使用 ransacker 并在你的控制器中做类似的事情,它可能更符合发票号码的实际性质,但更丑。

@invoices = params[:filter].is_a?(Integer) ? Invoice.search(params[:filter]).result : []

希望这能解决您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    相关资源
    最近更新 更多