使用ransacker进行整数to_char的ransack

时间:2014-08-05 05:10:19

标签: ruby-on-rails postgresql ransack

我正在尝试使用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;

尝试搜索ransack时遇到的错误:invoice_no_cont

  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

1 个答案:

答案 0 :(得分:1)

以下是我对您的问题的解释:

  1. 您的发票号码仅由整数组成
  2. 您有一个搜索字段,使用angular.js将输入的值作为文本发送到服务器
  3. 您希望在搜索(params [:filter])方法调用
  4. 中注入一个字符串
  5. 你使用ransacker来处理你认为是字符串的params [:filter]
  6. 您忘记的是,当您将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 : []
    

    希望这可以解决您的问题。