Вы можете использовать Arel
, который вам не нужен и является базовым построителем запросов для ActiveRecord / Rails.например.
products = Arel::Table.new("products")
products2 = Arel::Table.new("products", as: 'p')
imported_structs = Arel::Table.new("imported_structures")
query = products.project(
products[:id].as('product_id'),
products[:code],
products[:description],
products[:family],
products2[:code].as('father_code'),
products2[:description].as('father_description'),
products2[:family].as('father_family')).
join(imported_structs,Arel::Nodes::OuterJoin).
on(imported_structs[:product_id].eq(products[:id])).
join(products2,Arel::Nodes::OuterJoin).
on(products2[:id].eq(imported_structs[:product_father_id])).
where(products[:enable].eq(true).and(products2[:enable].eq(true)))
if !params[:code].blank?
query.where(
Arel::Nodes::NamedFunction.new('UPPER',[products[:code]])
.matches("%#{params[:code].to_s.upcase}%")
)
end
Результат SQL: (с params[:code] = "' OR 1=1 --test"
)
SELECT
[products].[id] AS product_id,
[products].[code],
[products].[description],
[products].[family],
[p].[code] AS father_code,
[p].[description] AS father_description,
[p].[family] AS father_family
FROM
[products]
LEFT OUTER JOIN [imported_structures] ON [imported_structures].[product_id] = [products].[id]
LEFT OUTER JOIN [products] [p] ON [p].[id] = [imported_structures].[product_father_id]
WHERE
[products].[enable] = true AND
[p].[enable] = true AND
UPPER([products].[code]) LIKE N'%'' OR 1=1 --test%'
Для использования
ProductStructure.find_by_sql(query.to_sql)
Я предпочитаю Arel
, если доступно, более String
запрашивает потому что:
- он поддерживает экранирование
- он использует ваш существующий адаптер подключения для sytnax (поэтому он переносим, если вы меняете базы данных)
- он встроенкод, поэтому порядок операторов не имеет значения
- он гораздо более динамичен и удобен в обслуживании
- он изначально поддерживается ActiveRecord
- вы можете построить любой сложный запрос, который вы можете себе представить (включаясложные соединения, CTE и т. д.)
- все еще очень читабельно