I'm trying to solve the following issue but I just can't get my head around the autoloading in Rails yet. I have the following controller located in app/api/v1/registration_controller.
class Api::V1::RegistrationController < ApplicationController
include ::Foo::Bar
def index
end
end
And the following module/class in app/foo/bar.rb:
module Foo
class Bar
def some_method
end
end
end
However, I'm getting the following error message:
uninitialized constant Foo
I'm trying to get my head around this and already searched Stack Overflow for solutions, but I wasn't able to find the right one. If the solution is already written down elsewhere, please close this topic.
Hopefully someone can help me. Thanks!
The Rails autoloader searches a number of paths to try to locate constants - app/ isn't one of them. You can add it by appending it in application.rb, like:
config.autoload_paths << File.join(config.root, "app")
Or just move foo/bar.rb into lib/, which is already in the loader path.
Related
I've just updated my Gemfile.
At the beginning I thought problem came from Zeitwerk (from 2.4.2 to 2.5.4) but I've downgraded it and I still have an issue on my spec. I've isolated that the problem does not come from RSpec and dependencies.
Actually, RSpec does not found a class which is defined within another file and does not match the file name/class name.
Important point: Filter::MyStandardError is found.
# app/services/filter/my_standard_error.rb
module Filter
class MyStandardError < StandardError; end
class MySpecificError < MyStandardError; end
# ...
end
# app/services/filter/my_tested_service.rb
module Filter
class MyTestedService
def initialize
raise ::Filter::MySpecificError
end
end
end
RSpec.describe Filter::MyTestedService do
subject { described_class.new }
it 'raises an error'
expect{subject}.to raise_error(::Filter::MySpecificError)
end
end
And I got the error:
NameError:
uninitialized constant Filter::MySpecificError
I got the Changelog but breaking changes are not used on my configuration.
Does anybody have an idea for this one?
You do not need to add app/services to the autoload paths, that is done automatically by Rails. I'd suggest to remove that configuration to keep things simple/idiomatic.
The implementation of app/services/filter.rb should not be needed. Your application is doing something that is not right, we just need to find it.
Could you please delete app/services/filter.rb, throw Rails.autoloaders.log! in config/application.rb, trigger the error, and share the traces?
After reading one-file-one-constant-at-the-same-top-level
I found this to fix my issue
# app/services/filter.rb
class Filter
class MyStandardError < StandardError; end
class MySpecificError < MyStandardError; end
end
# app/services/filter/my_tested_service.rb
class Filter
class MyTestedService
def initialize
raise ::Filter::MySpecificError
end
end
end
I still don't know why it was working before..
You cannot define two constants at the same level in the same file. It is one constant, one file. This has not changed in Zeitwerk upgrades. You need one file for the standard error, and another file for the specific error.
I am newbie to Ruby on Rails and I broken my head at Rails autoloading mechanisms.
I have code like that in my /app/helpers/posts_helper.rb :
module PostsHelper
def markdown_render(data)
Utils::Markdown.render data
end
end
And I have /app/utils/markdown.rb with something like:
module Utils
class Markdown
class << self
def render(data)
# render some dataz
end
end
end
end
According to http://guides.rubyonrails.org/autoloading_and_reloading_constants.html, Utils::Markdown will be loaded from /app/utils/markdown.rb, but instead I recieve:
ActionView::Template::Error:
uninitialized constant PostsHelper::Utils
I understand that the problem lies in referencing Utils from helper module, but I have zero ideas how to properly make that reference.
Please, help me before my head crashes! =-)
Try:
module PostsHelper
def markdown_render(data)
::Utils::Markdown.render data
end
end
that is, put a double-colon in front of Utils::Markdown. It basically means "look in the root namespace," rather than "look within the namespace I'm currently in".
In markdown.rb, just define Markdown as a top level class (i.e. not in any namespaces).
Okay, I sorta figured it out.
The app/some_name path is "chewed" from module/class finding, so Rails do not expect to find in app/some_name/some_class.rb SomeName::SomeClass, it simply expect to find SomeClass.
I restructured the file ierarchy, so now it is: app/modules/utils/my_markdown.rb, and it correctly autoloads Utils::MyMarkdown from my_markdown.rb =-)
I have the following in my controller:
class SurveysController < ApplicationController
def index
survey_provider = FluidSurveysProviders::SurveyProvider.new
contact_lists = survey_provider.get_lists()
#survey = Survey.new(contact_lists)
end
And I'm receiving this error:
NameError in SurveysController#index
uninitialized constant SurveysController::FluidSurveysProviders
Excuse my Rails noobiness, I'm sure I'm leaving out something important here. But it seems to me that I am trying to "initialize" the constant with this line:
survey_provider = FluidSurveysProviders::SurveyProvider.new
But that's the same line that's throwing an error because it's not initialized. Where should I be "initializing" the Provider?
Once you require fluid_surveys_providers (or similar) then do this:
include FluidSurveysProviders
Make sure SurveyProvider is wrapped with module FluidSurveysProviders. It may look like this
module FluidSurveysProviders
class SurveyProvider
...
end
end
if its an ActiveRecord object try this
class FluidSurveysProviders::SurveyProvider < ActiveRecord::Base
...
end
The SurveyProvider was not loaded correctly.
For a quick fix, move the class file into app directory, e.g. app/lib/survey_provider.rb. Then all code inside app will be auto-loaded by Rails.
Or make sure the path to class SurveyProvider is included in the autoload_path of Rails. In config/application.rb
config.autoload_paths += %W(#{config.root}/lib) # where lib is directory to survery_provider
If you use Rails 5, be careful that autoload is disabled in production environment. Check this link for more info.
I was able recently to organize my code by grouping everything into folders.
I had an issue with having the same "group name" for both my group of controllers under the app/ directory and my module under the lib/ directory but I was able to fix by following this:
Rails: Same name for a library module and a group of controllers?
I also know that whenever you change your lib code, you need to restart the rails server which is totally fine by me.
But after the recent re-organization, every time I change the code in the controllers, I get the following error!!!
NameError at /admin
uninitialized constant Admin::PagerDuty
and to resolve it, I simply restart the server!!
Any advice?!
EDIT: STRUCTURE:
Controller main_controller.rb is under app/controllers/admin
class Admin::MainController < ApplicationController
end
Helper main_helper.rb is under app/helpers/admin
module Admin::MainHelper
require "admin/pager_duty.rb"
def pager_duty
pagerduty = Admin::PagerDuty.new()
#on_call = pagerduty.on_call()
#counts = pagerduty.open_incidents()
end
end
lib pager_duty.rb is under lib/admin
module Admin
class PagerDuty
....
end
end
Try changing
require "admin/pager_duty.rb"
to
require_dependency "admin/pager_duty.rb"
in your module.
Everytime i get a warning:
app/controllers/agency/agencies_controller.rb:1: warning: toplevel constant ApplicationController referenced by Agency::ApplicationController
My agencies_controller.rb:
class Agency::AgenciesController < Agency::ApplicationController
def index
...
end
...
end
And Agency::ApplicationController:
class Agency::ApplicationController < ApplicationController
layout 'agency'
helper_method :current_agency
private
def current_agency
#current_agency ||= current_user.agency
end
end
What the rails wants from me? What is the trouble?
Same situation with another controller
class Agency::ClientsController < Agency::ApplicationController
...
end
And no warnings, no errors...
I realize this question is almost two years old but I recently stumbled upon this through another stackoverflow post and wanted to share some insight.
Basically, if your namespace Agency happens to be a class instead of a module, you'll get that warning. In the stackoverflow post I pasted above, they had a model (class) of Admin and their namespace was also Admin.
This provides a better explanation of what is happening.
So check to see if your code isn't defining an Agency class somewhere. Good luck.
I had similar issues running Spork and Watchr in my Admin namespaced controllers. So i've fixed this by adding following code into each_run block in spec_helper.rb:
Dir[File.expand_path("app/controllers/admin/*.rb")].each do |file|
require file
end
All credits goes to guy from this thread
ApplicationController is the name of the superclass controller that Rails generates for you when you create a new project that all your other controller classes inherit from. There's probably a conflict somewhere because you've used the same name, even though you put it within a namespace.
Try giving your Agency::ApplicationController a different name.
I had similar issues, after setting up Spork and Watchr. In the process, I turned off class cacheing (config_cache_classes => false in config/environments/test.rb) so that changes would be reloaded as necessary in the spork environment. Turning class cacheing back on made the warnings go away.
In my case it was the problem with Devise. I had a devise model Admin and a namespaced routes Admin. Changing the namespaced route to Admins solved the problem.
Solution for me was add this line:
# spec/rails_helper.rb
Dir[File.expand_path("app/controllers/admin/*.rb")].each { |file| require file }