我正在尝试使用 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 View 中使用 invoice_no_cont,就像这样。
<td data-title="'Invoice No.'" sortable="'invoice_no'" filter="{'invoice_no_cont':'text'}">
{{invoice.invoice_no}}
</td>
这是通过对 Ruby on Rails 服务器 invoice#index 方法的“GET”请求传递的,该方法随后将其提取并通过搜索发送。
@invoices = Invoice.search(params[:filter]).result
最佳答案
这是我对你的问题的解释:
- 您的发票编号仅由整数组成
- 您有一个搜索字段,它使用 angular.js 将输入的值作为文本发送到服务器
- 您希望在 search(params[:filter]) 方法调用中注入(inject)一个字符串
- 你使用 ransacker 来处理你认为是字符串的 params[:filter]
您忘记的是,当您将 JSON 数据发送回 Rails 服务器时,它会解析 JSON 负载。尽管您认为您正在返回一个字符串,但 json gem 会解析该值并看到一个 Integer,如 gem's parser documentation 中所述。 .
这意味着即使你认为你得到的是一个字符串,params 哈希实际上得到一个整数作为过滤键的值,这就是:
operator does not exist: text ~~* integer
正在提示。 Postgres 希望与字符串进行比较,而不是整数。
简单的解决方法是将 to_s 添加到 Controller 中的 params[:filter]。
@invoices = Invoice.search(params[:filter].to_s).result
这样您就可以确保始终比较字符串。这也是对作为过滤器发送的输入进行容错的好方法。
你也可以不使用 ransacker 而在你的 Controller 中做类似的事情,它可能更符合发票号码的实际性质,但更难看。
@invoices = params[:filter].is_a?(Integer) ? Invoice.search(params[:filter]).result : []
希望这能解决您的问题。
关于ruby-on-rails - 使用 ransacker 对整数 to_char 进行洗劫,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25131568/