I've been trying to make sense of the class of self
in the present
method that Ryan Bates used in his Presenters RailsCast (#287 Presenters from Scratch (pro) - RailsCasts). In the video, Ryan says, 'Self is the template object which has all the helper methods we want to access', but I wanted to know the class for this object. After reading a range of blog posts, SO threads, and Ruby docs, I'm starting to think that self
is a kind of Struct, but I don't know how to confirm this notion.
My questions are: 1) In the present
method below, is self
a Struct?, and 2) How does one verify that something is a Struct?
module ApplicationHelper
def present(object, klass = nil)
klass ||= "#{object.class}Presenter".constantize
presenter = klass.new(object, self)
yield presenter if block_given?
presenter
end
end
I'm asking this because I don't have much experience working with Struct
classes and when I stick binding.pry
in the middle of the method above and try to get the name of the class for self
, I end up with more questions.
self.class
, I get, #<Class:0x007fb64f696268>
I wondered if getting Class
here might indicate that I have a Struct
, but I couldn't find any documentation that confirmed thisself.class.class
, I get Class
When I enter self
, I get an extensive object that starts with the lines of code of code listed below
@ line 16 ApplicationHelper#present:
14: def present(object, klass = nil)
15: klass ||= "#{object.class}Presenter".constantize
16: binding.pry
17: presenter = klass.new(object, self)
18: yield presenter if block_given?
19: end
[1] pry(#<#<Class:0x007fb64f696268>>)> self
=> #<#<Class:0x007fb64f696268>:0x007fb64f6948f0
@_assigns={"marked_for_same_origin_verification"=>true},
@_config={},
@_controller=
#<PostsController:0x007fb64f6762d8
@_action_has_layout=true,
@_action_name="show",
@_config={},
@_db_runtime=0,
@_lookup_context=
#<ActionView::LookupContext:0x007fb64f6760d0
@cache=true,
@details=
{:locale=>[:en],
:formats=>[:html],
:variants=>[],
:handlers=>[:raw, :erb, :html, :builder, :ruby]},
@details_key=#<Concurrent::Map:0x007fb64f697938 entries=0 default_proc=nil>,
@prefixes=["posts", "application"],
@rendered_format=:html,
@view_paths=
#<ActionView::PathSet:0x007fb64f675fe0
This post was helpful in explaining how a Struct works, but doesn't explain how one can confirm that they have a Struct.
Initially, when I started dissecting the present
method, I found this answer to be helpful. However, I was thrown off by the comment, saying that the "ModelPresenter is initialized by passing the model, and the ApplicationHelper class", since ApplicationHelper is a module.
Use is_a?(Struct)
A struct is a constructor for an anonymous class:
struct_class = Struct.new(:foo)
# => #<Class:0x007fa7e006ea98>
You can check that an instance of the anonymous class is a struct like so:
inst = struct_class.new
inst.class.superclass
# => Struct
However Object#is_a? checks the parent class as well as superclasses:
inst.is_a?(Struct)
# => true
You can see the same behavior in the following arbitrary example:
# inherits from String
anon_class = Class.new(String)
inst = anon_class.new
# => ""
inst.class == String
# => false
inst.is_a?(String)
# => true