When you write little helper methods in your controllers, do you use protected
or private
? Do you know why?
Pop quiz: what will this sample print out?
class Parent
def mr_public
'public'
end
def access_other_protected(other)
other.mr_protected
end
def access_other_private(other)
other.mr_private
end
def access_self_protected
self.mr_protected
end
def access_self_private
self.mr_private
end
protected
def mr_protected
'protected'
end
private
def mr_private
'private'
end
end
class Child < Parent
def access_parent_protected
mr_protected
end
def access_parent_private
mr_private
end
end
def attempt
puts yield
rescue
puts 'forbidden'
end
parent = Parent.new
other = Parent.new
child = Child.new
attempt { parent.mr_public }
attempt { parent.mr_protected }
attempt { parent.mr_private }
attempt { parent.access_self_protected }
attempt { parent.access_self_private }
attempt { parent.access_other_protected(other) }
attempt { parent.access_other_private(other) }
attempt { child.access_parent_protected }
attempt { child.access_parent_private }
Answer:
public
forbidden
forbidden
protected
forbidden
protected
forbidden
protected
private
What the hell just happened
Some lesser-known rules:
- A child class can invoke private methods defined on its parent
- A class cannot invoke private methods on itself if you use
self
- A class cannot access private methods an another instance of its own class
Some guidelines:
- Define almost everything as private instead of protected!
- You essentially only need to use protected together with methods like
==
,<
, or>
.