The migration from protected_attributes (attr_accessible/protected) to strong parameters moves whitelisting of model attributes from the model to the controller, in line with Rails.
What will change in Foreman:
- attr_accessible will be removed from all models
- Controllers will be updated to call the
paramsto whitelist attributes
- The plugin API will allow plugins to whitelist custom attributes on core models
- A basic (deprecated) compatibility method will be added for plugins that add custom attributes to core models
- A helper will be added to de-duplicate code between UI/API controllers and nested models
Plugin authors will need to migrate too:
- For plugin models, either update controllers to use Rails'
ParameterFilter, or add a dependency on the
- For custom attributes on core models, replace
parameter_filterin plugin registration between now and the end of the deprecation period
Changing a model from attr_accessible to strong parameters¶
This example will use a simple model with three attributes:
class Example < ActiveRecord::Base attr_accessible :name, :description, :foo_id, :foo_name end
If the model has controller(s), they will currently use
params[:example] to create and update the model through mass assignment. Create a new helper method in the controller that calls the
permit method on
class ExamplesController < ApplicationController private def example_params params.require(:example).permit(:name, :description, :foo_id, :foo_name) end end
update etc to call
example_params instead of
If you have both UI and API controllers, the params method can be put into a concern to avoid duplication, e.g.
If the model uses either Taxonomix or NestedCommonAncestry concerns or subclasses any of Foreman's models, then you should use ParameterFilter like Foreman does, as Foreman::Controller::Parameters concerns are also provided.
Changing core extensions to use the plugin API¶
When extending a Foreman model, instead of calling
attr_accessible, whitelist the additional attribute during plugin registration:
Foreman::Plugin.register :foreman_example do parameter_filter CoreExample, :name, :description, :foo_id, :foo_name end
For plugins that provide models extended by other plugins, consider using the ParameterFilter class from Foreman to get the same features.
- Models that don't have controllers can probably have
attr_accessibleremoved entirely. If they accept user input through mass-assignment outside of controllers, consider using ActionController::Parameters directly.
- Attributes that have array values should be listed at the end of the permit line (as a hash) in the form
:example_ids => 
accepts_nested_attributes_for, keys for inner hashes must be specified or use the
keep_paramhelper to skip validation completely (use carefully). Optionally use ParameterFilter which helps de-duplicate whitelists between the main resource controller and nested hashes.
accepts_nested_attributes_foron Foreman core models (including host facets), define the nested model's attributes with ParameterFilter and use the plugin API to register it on the top-level object, e.g.
parameter_filter Host::Managed, :my_facet => [my_facet_param_filter]
accepts_nested_attributes_for, ensure any custom forms or JS use integer keys for nested models and not mixed (e.g. "new_123456" becomes "123456"). Same for API calls, use a unique integer for each unique nested model.
- Aim to remove any use of protected_attributes as soon as possible. It isn't compatible with Rails 5 and adds complex interactions with Rails 4 methods.