Como ativar a proteção de parâmetros fortes para modelos não ActiveRecord?

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::ForbiddenAttributesProtectionassign_attributesinitializesanitize_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 initializeassim:

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::MassAssignmentSecurityActiveRecordsanitize_for_mass_assignmentActiveModel::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