Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Rails Auto Loading Magic Gone Wrong!
shushugah
shushugah

Posted on • Edited on • Originally published atMedium

     

Rails Auto Loading Magic Gone Wrong!

TL;DR, use explicit module namespacing or avoid complex namespacing as often as possible when inheriting classes.

Class and Module constants depend on the order ofautoload-paths lookup (a Ruby on Rails feature), more on that below. Because of this, class discoverability can vary depending on the name and location of an inheriting class. When multiple classes share the same name, as is the case in our Rails app, this subtlety can impact implicit class inheritance.

Ruby on Rails hastwo main algorithms for constant lookup in itsautoload_paths (by default all subdirectories ofapp/ in the application and engines present at boot time, andapp/*/concern).

The values ofautoload_paths can be inspected with the following command:

$bin/rails r'puts ActiveSupport::Dependencies.autoload_paths'.../app/assets.../app/controllers.../app/helpers.../app/mailers.../app/models.../app/resources# This is loaded before models/.../app/controllers/concerns.../app/models/concerns.../test/mailers/previews

In my attempt to clean up some of our code, I unwittingly created a difficult bug to spot. Here is some example code to see the issue in action:

# app/models/campaign.rb# This class is completely irrelevant to our code but has the same class name as the other campaign class.classCampaign;end# app/resources/homepage/apple.rbmoduleResourcesmoduleHomepageclassApple<Campaigncampaign_method!# This fails because apple.rb is loaded before resources/homepage/campaign.rbendendend# app/resources/homepage/campaign.rbmoduleResourcesmoduleHomepageclassCampaigndefself.campaign_method!"I should be callable"endendendend# app/resources/homepage/yolo.rbmoduleResourcesmoduleHomepageclassYolo<Resources::Homepage::Campaigncampaign_method!# This works because the parent class is unambiguousendendend# app/resources/homepage/zolo.rbmoduleResourcesmoduleHomepageclassZolo<Campaigncampaign_method!# This works by luck because Zolo is loaded alphabetically after resources/homepage/campaign.rbendendend

I was able to debug this issue usingrails console

pry(main)> Resources::Homepage::Yolo# returns a constant=> Resources::Homepage::Yolopry(main)> Resources::Homepage::Apple# returns an error messageNameError: undefinedlocalvariable or method`campaign_method!' for Resources::Homepage::Apple:Class`

After changingclass Apple < Campaign toclass Apple < Resources::Homepage::Campaign and reloading the console, the code loads correctly.

Explicitly loading the required file also works, which is what Rails AutoLoader (usually) does correctly for you. The Rails Guides discourages usingrequire orrequire_relative for autoloaded files. Instead, userequire_dependency

# resources/homepage/apple.rbrequire_dependency'resources/homepage/campaign'moduleResourcesmoduleHomepageclassApple<Campaigncampaign_method!# this works and loads campaign's class methodendendend

Hopefully, Ruby on Rails autoloading is clearer now. You can always read more and improve Ruby on Railsdocumentation here. If you have any questions or found errors, please comment here or contact me ontwitter!
In Rails 5, autoloading isdisabled by default in production.

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
ben profile image
Ben Halpern
A Canadian software developer who thinks he’s funny.
  • Email
  • Location
    NY
  • Education
    Mount Allison University
  • Pronouns
    He/him
  • Work
    Co-founder at Forem
  • Joined

Yikes

CollapseExpand
 
dablurr profile image
Dablurr
Lead back end dev @Plezi#Ruby #React #NextJS
  • Location
    Paris
  • Education
    Bacheler + Master degree in Soft. Engineering @MonmouthUniversity
  • Work
    full stack
  • Joined

Interesting read !

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Passionate about human rights, community, Ruby and caffeine
  • Location
    Berlin, Germany
  • Work
    Software Developer
  • Joined

More fromshushugah

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp