Ruby on Rails: Query in model for SQLite in Dev => PostgreSQL in Prod



我目前在开发环境中运行SQLite,在Heroku的生产环境中运行PostgreSQL。

我当前的搜索功能在模型条目.rb中有以下方法:

def self.search(search)
  where("content LIKE ? OR created_at LIKE ?", "%#{search}%", "%#{search}%") 
end

虽然这可能在我运行SQLite的开发环境中有效,但运行PostgreSQL的Heroku会抛出一个错误。

我知道在不同的环境中运行不同的数据库是一种糟糕的做法,但是,为了便于管理,现在我将坚持使用它。

话虽如此,我想知道PostgreSQL的正确查询是什么样子的?

此外,我可以在我的模型中添加一个if子句,根据我所处的环境为一个或另一个查询提供信息吗?类似:

if Rails.env.development?
  # SQLite query
else
  # PostgreSQL query
end

谢谢大家!

您正试图使用带有时间戳的LIKE(字符串运算符),PostgreSQL会抱怨这一点,这是正确的。这将适用于SQLite,因为SQLite实际上没有时间戳类型,它使用ISO-8601格式的字符串作为时间戳。这是你的第一个问题。

您的第二个问题是,您正试图使用带有时间戳的字符串模式匹配运算符。这对我来说没有多大意义,除非你期望人们进入'2016-01'来寻找2016年1月发生的事情。如果这真的是你想要做的,那么你可以将时间戳转换为一个字符串:

where('content like :pat or cast(created_at as text) like :pat', :pat => "%#{search}%")

或者使用to_char根据需要格式化时间戳(有关可用的格式化选项,请参阅手册):

where("content like :pat or to_char(created_at, 'YYYY-MM-DD HH24:MI:SS.MS') like :pat", :pat => "%#{search}%")

您可能还注意到,我从位置占位符(?)切换到了命名占位符(:pat),这样您就不必重复自己的操作了。

不要试图在不同的环境中使用不同的查询。这只会让你头疼。在您的开发环境中安装PostgreSQL,这样您就可以使用同一个数据库进行开发、测试和部署。如果你没有在所有三个地方使用相同的数据库,这个小问题将是你最不担心的。ActiveRecord没有为您提供任何有用的数据库可移植性,所以您要么自己硬着头皮做,要么到处使用相同的数据库。

在这种情况下,您可以使用ILIKE

def self.search(search)
  where("content ILIKE ? OR created_at ILIKE ?", "%#{search}%", "%#{search.to_datetime}%") 
end

根据postgres文件:

关键字ILIKE可以用来代替LIKE来匹配根据活动区域设置,不区分大小写。这不在SQL标准,但它是PostgreSQL的扩展。

最新更新