Atualmente estou migrando nosso aplicativo Rails para usar a proteção de atribuição em massa de Parâmetros Fortes em vez da proteção centrada no modelo, que é usada no Rails 3.2.x por padrão.
A migração de modelos ActiveRecord é fácil e bem documentada . No entanto, desejo ativar esse tipo de proteção até mesmo para nossos modelos não persistentes.
Então vamos ter uma espécie de modelo hipotético ‘CarForm’ com propriedades ‘driver’, ‘fabricante’ e ‘cor’.
class CarForm
# It quacks like ActiveModel...
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
attr_accessor :driver, :manufacturer, :color
validates :driver, :manufacturer, :color, presence: true
def initialize(values = {})
values.each do |k, v|
send("#{k}=", v)
end
end
def persisted?
false
end
end
Leiame para parâmetros fortes nos orienta a usar o no modelo. Então, apenas incluímos isso e pronto, certo? Não. Este módulo foi projetado para trabalhar com ActiveRecord com métodos como e onde os parâmetros são filtrados . Portanto, precisamos adicionar este método ao nosso modelo:include ActiveModel::ForbiddenAttributesProtection
assign_attributes
initialize
sanitize_for_mass_assignment
def assign_attributes(values, options = {})
sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
send("#{k}=", v)
end
end
E podemos reescrever initialize
assim:
def initialize(values = {})
assign_attributes(values)
end
No entanto, quando tentamos executar este código, obtemos o seguinte erro:NoMethodError: super: no superclass method 'sanitize_for_mass_assignment' for #<CarForm:0x000000078aea38>
Só falta uma coisa: a própria proteção de atribuição em massa! Precisamos incluir mais um mixin (que também faz parte do por padrão). Este módulo também contém o método. Portanto, precisamos carregar este módulo antes do mixin para agir como superclasse.ActiveModel::MassAssignmentSecurity
ActiveRecord
sanitize_for_mass_assignment
ActiveModel::ForbiddenAttributesProtection
E agora podemos finalmente chamar:
params = ActionController::Parameters.new({
'car_form' => {
'driver' => 'Alfred',
'color' => '#000000',
'manufacturer' => 'Rolls-Royce'
}
})
sanitized_params = params.require(:car_form).permit(:driver, :color, :manufacturer)
form = CarForm.new(sanitized_params)
Abaixo você pode ver a classe modificada:
class CarForm
# It quacks like ActiveModel...
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
# Mass-assignment protection using Strong Params
include ActiveModel::MassAssignmentSecurity
include ActiveModel::ForbiddenAttributesProtection
attr_accessor :driver, :manufacturer, :color
validates :driver, :manufacturer, :color, presence: true
def initialize(values = {})
assign_attributes(values)
end
def assign_attributes(values, options = {})
sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
send("#{k}=", v)
end
end
def persisted?
false
end
end