J'essaie de faire une requête similaire comme si
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE '%?%' OR postal_code like '%?%'", search, search], order => 'name'
end
Mais quand il est lancé, quelque chose est en train d’ajouter des guillemets, ce qui provoque l’instruction SQL de sortir comme si
SELECT COUNT(*)
FROM "schools"
WHERE (name LIKE '%'havard'%' OR postal_code like '%'havard'%')):
Donc, vous pouvez voir mon problème. J'utilise Rails 4 et Postgres 9 que je n'ai jamais utilisés, donc je ne suis pas sûr qu'il s'agisse d'une opération activerecord ou éventuellement postgres.
Comment puis-je configurer cela alors j'ai comme '%my_search%'
dans la requête finale?
Votre espace réservé est remplacé par une chaîne et vous ne le gérez pas correctement.
Remplacer
"name LIKE '%?%' OR postal_code LIKE '%?%'", search, search
avec
"name LIKE ? OR postal_code LIKE ?", "%#{search}%", "%#{search}%"
Au lieu d'utiliser la syntaxe conditions
de Rails 2, utilisez plutôt la méthode Rails 4 de where
:
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE :search OR postal_code LIKE :search", search: wildcard_search)
.page(page)
.per_page(5)
end
Remarque: ce qui précède utilise la syntaxe de paramètre au lieu de? espace réservé: ces deux doivent générer le même sql.
def self.search(search, page = 1 )
wildcard_search = "%#{search}%"
where("name ILIKE ? OR postal_code LIKE ?", wildcard_search, wildcard_search)
.page(page)
.per_page(5)
end
REMARQUE: utilisation de ILIKE
pour le nom - version de LIKE insensible à la casse
Bien que l'interpolation de chaîne fonctionne, comme votre question le spécifie Rails 4, vous pourriez utiliser Arel à cet effet et maintenir votre base de données d'applications agnostique.
def self.search(query, page=1)
query = "%#{query}%"
name_match = arel_table[:name].matches(query)
postal_match = arel_table[:postal_code].matches(query)
where(name_match.or(postal_match)).page(page).per_page(5)
end
ActiveRecord est assez intelligent pour savoir que le paramètre référencé par le ?
est une chaîne et qu'il est donc entouré de guillemets simples. Vous pourriez comme le suggère un message utilisez l’interpolation de chaîne Ruby pour garnir la chaîne avec les symboles %
requis. Cependant, cela pourrait vous exposer à l'injection SQL (ce qui est mauvais). Je vous suggère d'utiliser la fonction SQL CONCAT()
pour préparer la chaîne comme suit:
"name LIKE CONCAT('%',?,'%') OR postal_code LIKE CONCAT('%',?,'%')", search, search)
Essayer
def self.search(search, page = 1 )
paginate :per_page => 5, :page => page,
:conditions => ["name LIKE ? OR postal_code like ?", "%#{search}%","%#{search}%"], order => 'name'
end
Voir les docs sur les conditions AREL pour plus d'informations.