简体   繁体   中英

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

I am currently running SQLite in my development environment and PostgreSQL in the production environment on Heroku.

My current search functionality has the following method in the model entry.rb:

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

While this might work in my development environment running SQLite – Heroku running PostgreSQL is throwing up an error.

I am aware of the fact that it is bad practice to run different databases in different environments, however, for now I'll stick to it for ease of administration.

Having said that, I am wondering what the correct query would look like for PostgreSQL?

Also, could I add an if clause in my model that feeds one query or the other based on the environment I am in? Like:

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

Thanks guys!

You're trying to use LIKE (a string operator) with a timestamp, PostgreSQL is going to complain about that and rightly so. That will work with SQLite because SQLite doesn't actually have a timestamp type, it uses ISO-8601 formatted strings for timestamps. This is your first problem.

Your second problem is that you're trying to use a string pattern matching operator with a timestamp. This doesn't make a lot of sense to me unless you're expecting people to enter '2016-01' to find things that happened in January of 2016. If this is really what you want to do then you could cast the timestamp to a string:

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

or use to_char to format the timestamp as desired (see the manual for the available formatting options):

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

You might also notice that I switched from position placeholders ( ? ) to a named placeholder ( :pat ) so that you don't have to repeat yourself.

Don't try to use different queries in different environments. That's just opening yourself up to a lot of headaches. Install PostgreSQL in your development environment instead so that you can develop, test, and deploy with the same database. This little problem is going to be the least of your worries if you're not using the same database in all three places. ActiveRecord doesn't give you any useful database portability so either you do it the hard way yourself or you use the same database everywhere.

You can use ILIKE in this case.

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

According to postgres documentation:

The key word ILIKE can be used instead of LIKE to make the match case-insensitive according to the active locale. This is not in the SQL standard but is a PostgreSQL extension.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM