In chapter 7 I'm getting the following output with
--- !ruby/hash-with-ivars:ActionController::Parameters
elements:
controller: static_pages
action: home
ivars:
:@permitted: false
could someone explain where the hash-with-ivars is coming from and what ivars:
:@permitted: false means?
Interesting question! I searched all library sources of a rails project for 'hash-with-ivars'
and only a single place came up: the psych
ruby library for (de-)serializing arbitrary objects to and from YAML. Specifically, these are links to the source code for reading and writing this YAML structure.
In Chapter 7 of the Rails Tutorial, this output comes out as the output of the debug(params)
command that you are instructed to put in a template. The debug
command apparently calls the psych
library to show a readable representation of the object (params
in this case).
Now, params
- the universal Rails data structure to hold parameters passed from URLs or forms - is an object that behaves like a Hash
but is not pure hash: it is an instance of class ActionController::Parameters
which is a subclass of Hash
, let's see the class definition:
module ActionController
# ...
class Parameters < ActiveSupport::HashWithIndifferentAccess
# ...
end
end
while HashWithIndifferentAccess
is a direct subclass of Hash
.
As a subclass of Hash
, the params
object can hold other data besides the hash itself and this is what psych
actually supports when trying to print the object in a readable form. Besides printing all the hash elements (under the elements
key), it tries to also list all instance variables of the object and prints it under the ivars
key.
So, all in all, this debug print simply says that the object debugged is an instance of the ActionController::Parameters
class, which is a subclass of Hash
, that besides it's hash elements has also a @permitted
instance variable defined and it is currently set to false
. The two elements, by the way, the controller
and action
are parameters used internally by Rails for routing.
When you look into the source of the class again, you will indeed find the @permitted
variable right in the constructor:
class Parameters < ActiveSupport::HashWithIndifferentAccess
# ...
def initialize(attributes = nil)
super(attributes)
@permitted = self.class.permit_all_parameters
end
end
Finally, from the documentation we can conclude that the @permitted
variable holds the state of the params permission. I.e. it is set to true
after the params are permitted by using the permit
method:
permitted = params.require(:person).permit(:name, :age)
permitted.permitted? # this prints out the @permitted instance variable
# => true
Update: why the RailsTutorial's debug output differs
The debug output at the RailsTutorial differs a bit - it does not print ivar
s. Why? It is because the feature for serializing hash-with-ivars
was added to the psych
gem in its version 2.0.9. The psych
gem is now a part of the Ruby standard library and this particular version of it has been added to the stdlib 2.3.0 preview1 version.
So, the mysteriously different output has a simple explanation: the RailsTutorial author most probably used ruby 2.2 or earlier when writing the book and this ruby version did not display instance variables in the Hash
debug output yet. Actually, there are hints in the tutorial that suggest that the author used ruby 2.1.5.