active - Cómo desinfectar el fragmento sql en Rails
rollback migration rails (5)
Tengo que desinfectar una parte de la consulta SQL. Puedo hacer algo como esto:
class << ActiveRecord::Base
public :sanitize_sql
end
str = ActiveRecord::Base.sanitize_sql(["AND column1 = ?", "two''s"], '''')
Pero no es seguro porque expongo el método protegido. ¿Cuál es una mejor manera de hacerlo?
A partir de los rieles 5, la forma recomendada es usar: ActiveRecord::Base.connection.quote(string)
como se indica aquí: https://github.com/rails/rails/issues/28947
ActiveRecord::Base::sanitize(string)
está en desuso
ActiveRecord :: Base.connection.quote hace el truco en Rails 3.x
Esta pregunta no especifica que la respuesta debe provenir de ActiveRecord
ni especifica para qué versión de Rails debe estar. Por esa razón (y porque es una de las mejores y pocas) respuestas sobre cómo desinfectar los parámetros en Rails ...
Aquí una solución que funciona con Rails 4:
En ActiveRecord::Sanitization::ClassMethods
tiene sanitize_sql_for_conditions y sus otros dos alias : sanitize_conditions y sanitize_sql . Los tres hacen literalmente exactamente lo mismo.
sanitize_sql_for_conditions
Acepta una matriz, hash o cadena de condiciones SQL y las desinfecta en un fragmento SQL válido para una cláusula WHERE .
También en ActiveRecord tienes
sanitize_sql_for_assignment
que
Acepta una matriz, hash o cadena de condiciones de SQL y las desinfecta en un fragmento SQL válido para una cláusula SET .
- Los métodos anteriores se incluyen en ActiveRecord :: Base de manera predeterminada y, por lo tanto, se incluyen en cualquier modelo de ActiveRecord .
Además, en ActionController tienes ActionController::Parameters
que te permite
elegir qué atributos deben incluirse en la lista blanca para la actualización masiva y así evitar la exposición accidental de lo que no debe exponerse. Proporciona dos métodos para este propósito: requerir y permitir .
params = ActionController::Parameters.new(user: { name: ''Bryan'', age: 21 })
req = params.require(:user) # will throw exception if user not present
opt = params.permit(:name) # name parameter is optional, returns nil if not present
user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional
La "magia de los parámetros" se llama Parámetros fuertes ( aquí los documentos ) y puede usar eso para desinfectar los parámetros en un controlador antes de enviarlo a un modelo.
- Los métodos anteriores están incluidos por defecto en
ActionController::Base
y, por lo tanto, están incluidos en cualquier controlador de Rails .
Espero que eso ayude a cualquiera, ¡solo para aprender y desmitificar a Rails! :)
Puede omitir el valor protected
del método invocando indirectamente:
str = ActiveRecord::Base.__send__(:sanitize_sql, ["AND column1 = ?", "two''s"], '''')
... que al menos le ahorrará tener que remodelar ese método como public
.
(Soy un poco sospechoso de que realmente necesites hacer esto, pero lo anterior funcionará).
Puedes simplemente usar:
ActiveRecord::Base::sanitize(string)