0

在我使用 SQLite3 的开发过程中,我正在将我的应用程序部署到 heroku(和 n00b 一样)。我部署到 Heroku,但我收到特定页面的错误。我加载了 Postgresql 作为我的开发数据库,​​我注意到我的错误是由于排序功能而发生的。这在 SQLite3 中工作得很好,但在 Postgresql 中被破坏了。有人对如何更改语法以使用 Postgresql 有任何想法吗?

def index
  @users = User.paginate(:page => params[:page], :per_page => 100).search(params[:search]).find(:all, :order => sort_order('id'))
 end

private
#called to sort the table. taking in case insensitive  
def sort_order(default)
  "LOWER( #{(params[:c] || default.to_s).gsub(/[\s;'\"]/,'')} ) #{params[:d] == 'down' ? 'DESC' : 'ASC'}"
end 

这是我收到的错误

ActiveRecord::StatementInvalid in UsersController#index

PG::UndefinedFunction: ERROR: function lower(integer) does not exist LINE 1: SELECT "users".* FROM "users" ORDER BY LOWER( id ) DESC L... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. : SELECT "users".* FROM "users" ORDER BY LOWER( id ) DESC LIMIT 100 OFFSET 0
4

3 回答 3

0

Rails 已经知道列类型,您可以通过columns_hash. 将columns_hash列名称映射到列对象,并且列对象具有type与您在create_table. 例如:

User.columns_hash['id'].type

会给你:integer

User.columns_hash['created_at'].type

会给你:datetime。这让你可以在你的sort_order

def sort_order(default)
  c    = params[:c] || default.to_s
  type = User.columns_hash[c].type
  c    = "lower(#{c})" if(type == :string || type == :text)
  "#{c} #{params[:d] == 'down' ? 'DESC' : 'ASC'}"
end

当然,您应该将其列入白名单params[:c],以防有人试图将一些讨厌的东西放入您的 SQL 中,但您可以User.columns_hash.has_key?这样做:

cols = User.columns_hash
c    = (cols.has_key?(params[:c]) ? params[:c] : default).to_s
type = User.columns_hash[c].type
c    = "lower(#{c})" if(type == :string || type == :text)
"#{c} #{params[:d] == 'down' ? 'DESC' : 'ASC'}"

这种事情甚至应该可以跨数据库移植。

于 2013-11-10T20:36:53.063 回答
0

"ID" 是 INTEGER 类型吗?如果是这样,只需删除该LOWER()功能。如果没有,您将需要转换为 TEXT 或 VARCHAR。例如。ORDER BY CAST(id AS TEXT)

于 2013-11-10T20:37:47.833 回答
-1

您可以将值转换为文本,但您需要检查 postgres 或破坏 SQLite。

#called to sort the table. taking in case insensitive  
def sort_order(default)
  sort_col = (params[:c] || default.to_s).gsub(/[\s;'\"]/,'')
  sort_col += "::text" if ActiveRecord::Base.connection.class.to_s.match(/PostgreSQLAdapter$/)
  "LOWER( #{sort_col} ) #{params[:d] == 'down' ? 'DESC' : 'ASC'}"
end 
于 2013-11-10T20:18:18.103 回答