Roda class instance variables

81 views
Skip to first unread message

Matthew McGarvey

unread,
Jan 12, 2021, 8:55:38 PM1/12/21
to Roda
While looking into Roda I noticed that I was able to remove several of the core Roda class' instance variables and all the tests still passed. I then looked into how they were used and it seems like while these are defined as instance variables, the plugins are setting class variables. For example, @raw_route_block is set in the Base plugins's ClassMethods module https://github.com/jeremyevans/roda/blob/8065b69a74a098d40f1e494820491500c6f276e5/lib/roda.rb#L315 so the instance variable in the core class would not be used. Here's the before and after of the instance variables that still caused the tests to pass

Before:
@app = nil
@inherit_middleware = true
@middleware = []
@opts = {}
@raw_route_block = nil
@route_block = nil
@rack_app_route_block = nil

After:
@inherit_middleware = true
@middleware = []
@opts = {}

Please let me know if I'm missing something or if they could be removed!

Jeremy Evans

unread,
Jan 12, 2021, 10:05:57 PM1/12/21
to ruby...@googlegroups.com
If an instance variable is not defined, then attempts to access it return nil.  So yes, as in most cases, instance variables initialized to nil could be removed.  However, removing them would cause verbose mode warnings on Ruby <3.  The instance variables aren't defined in performance-sensitive code paths, so there isn't a good reason to remove them.

The link you provided shows code that is only run if you call Roda.route.  It's allowed to have Roda apps that do not call Roda.route, in which case that code will not be run.

Note that Roda does not use class variables (@@).

Thanks,
Jeremy

Matthew McGarvey

unread,
Jan 12, 2021, 10:29:25 PM1/12/21
to Roda
I wish I understood why defining an instance variable on the class affects instance variables set in the extended modules. I had expected @variables set in a module that would be extended to become @@variables but I guess that is not the case. Anyways, it seems like the instance variables are defined intentionally, thanks!

Matthew McGarvey

unread,
Jan 12, 2021, 10:50:39 PM1/12/21
to Roda
Actually, I really don't think we're talking about the same thing. I think you were confused by my github link pointing to a instance variable set to nil. A better example is in Roda::RodaRequest.

The initialize block sets:
@match_pattern_cache = ::Roda::RodaCache.new
And a matching @match_pattern_cache is used in RodaPlugins::Base::RequestClassMethods on this line https://github.com/jeremyevans/roda/blob/8065b69a74a098d40f1e494820491500c6f276e5/lib/roda/request.rb#L29
but it is actually coming from the attr_accessor defined right above it and the value is set when inheriting from Roda here https://github.com/jeremyevans/roda/blob/8065b69a74a098d40f1e494820491500c6f276e5/lib/roda.rb#L258

I believe the variable set in the initialize block can be removed along with the ones I was referring to in the first post since they are all in the same situation with the things that use the @variables all being modules that will be extended and so are working at the class-level and not the instance level.

Does that make more sense?

Hopefully this isn't bothersome. I'm studying Roda to see if the plugin pattern you made can be used effectively in the Crystal language.

Jeremy Evans

unread,
Jan 13, 2021, 10:59:18 AM1/13/21
to ruby...@googlegroups.com
On Tue, Jan 12, 2021 at 7:50 PM Matthew McGarvey <matthewm...@gmail.com> wrote:
Actually, I really don't think we're talking about the same thing. I think you were confused by my github link pointing to a instance variable set to nil. A better example is in Roda::RodaRequest.

The initialize block sets:
@match_pattern_cache = ::Roda::RodaCache.new
And a matching @match_pattern_cache is used in RodaPlugins::Base::RequestClassMethods on this line https://github.com/jeremyevans/roda/blob/8065b69a74a098d40f1e494820491500c6f276e5/lib/roda/request.rb#L29
but it is actually coming from the attr_accessor defined right above it and the value is set when inheriting from Roda here https://github.com/jeremyevans/roda/blob/8065b69a74a098d40f1e494820491500c6f276e5/lib/roda.rb#L258

I believe the variable set in the initialize block can be removed along with the ones I was referring to in the first post since they are all in the same situation with the things that use the @variables all being modules that will be extended and so are working at the class-level and not the instance level.

Does that make more sense?

Your second link is inside Roda.inherited, and is only called if you are subclassing Roda.  While it is common to subclass Roda, Roda can be used without subclassing, in which case the code in your second link will not be called, and you need the code from the class definition (line 12 from request.rb). 
 
Hopefully this isn't bothersome. I'm studying Roda to see if the plugin pattern you made can be used effectively in the Crystal language.

It's not bothersome, but you may want to ask questions such as "why is it this way?" instead of implying that Roda is doing something unnecessary.

Thanks,
Jeremy
Reply all
Reply to author
Forward
0 new messages