Uninitialized Constant in Rails Controller - ruby-on-rails

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.

Related

Accessing helpers and models from rails engine initializer

I'm trying to make a Ruby on Rails engine, and I want the initializer to be able to have access to the helpers and models.
I'll write below an example, part of the code, and the error that I have. It may not be the recommended way, because I can see that in some cases I'm repeating myself, but it's the first engine I make.
file lib/my_engine/engine.rb
module MyEngine
require 'my_engine/functions'
class Engine < ::Rails::Engine
isolate_namespace MyEngine
config.autoload_paths += %W( #{config.root}/lib )
end
class GlobalVars
attr_accessor :foo
def initialize
#foo = MyEngine::Functions.new
end
end
class << self
mattr_accessor :GLOBAL
mattr_accessor :USER_CONFIG
self.GLOBAL = MyEngine::GlobalVars.new
# add default values of more config vars here
self.USER_CONFIG = 'default config'
end
def self.setup(&block)
yield self
end
end
file lib/my_engine/functions.rb
module MyEngine
require '../../app/helpers/my_engine/options_helper'
class Functions
include MyEngine::OptionsHelper
attr_accessor :some_link
def initialize
#some_link = get_option('dummy')
end
end
end
There is also a controller named OptionsController in app/controllers/my_engine, and OptionsHelper in app/helpers/my_engine/options_helper.rb:
module MyEngine
module OptionsHelper
def get_option(name)
MyEngine::Option.new
end
end
end
When I try to run the dummy application, this error occurs:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)
If I change to just Option.new, I have this error:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::OptionsHelper::Option (NameError)
For ::MyEngine::Option.new, I have:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant MyEngine::Option (NameError)
For ::Option.new, I have:
/app/helpers/my_engine/options_helper.rb:4:in `get_option': uninitialized constant Option (NameError)
The dummy application has nothing in it. All helpers and models defined above are in the engine.
Before this, I had other errors because it couldn't access the helper, or the Functions class. I had to add require and include to make it work even if they are placed in the same directory. Also, to work, I had to move GlobalVars from its own file inside engine.rb.
Can somebody show me what I'm doing wrong?
After I used required for every class, I ended with ActiveRecord::ConnectionNotEstablished, and it seems that not everything is loaded and available at that point when the GLOBAL object is created.
So I moved the code that was using the models in a separate init method. Then, I added an after initialize event:
config.after_initialize do
MyEngine.GLOBAL.init
end
I see a possible problem: because you are inside module MyEngine it might be possible that actually rails is looking for MyEngine::MyEngine::Option, so I see two approaches:
just write Option: this will look for MyEngine::Option
write ::MyEngine::Option this will look in the global namespace and find MyEngine::Option
Secondly, if that does not help, even though your path seems correct, but you can always explicitly require "my_engine/option" at the top of the file. I am not entirely sure the autoloading in an engine works in quite the same way, and I tend to, in my engine file, require almost everything (to make sure it works).
In my engine.rb I do
require_relative '../../app/models/my_engine/option'
maybe this will help, but it is not a nice solution.

rails organizing folders for service objects

I'm trying yo create a service object to extract a few methods from the product.rb AR model, but for some reason I can't autoload the new TwitterShare class. When I hit up the console and try something like Product.last.twitter_share_text I get NameError: uninitialized constant Product::TwitterShare error.
What's going on in here? How should I organize my folders/files? Do I have to tell rails to autoload services? Here is the current code:
app/models/product.rb
class Product < ActiveRecord::Base
def twitter_share_text
TwitterShare.new(name: self.name, oneliner: self.oneliner).return_text
end
app/services/twitter_share.rb
class TwitterShare
attr_reader .........
def initialize....
end
You need to let rails know where it could possibly find TwitterShare.
Add the following to your application.rb
config.autoload_paths << "#{Rails.root}/app/services"
and then restart the console or server.
rails should now be able to locate twitter_share.rb and load TwitterShare correctly.
Refer to Autoloading and Reloading Constants for more info.

Can not call method of other class from static method

At first, i have a class which in app/workes/ like this:
class SendMailTask
include Resque::Plugins::Status
require 'mail'
def perform
...
end
And as a controller, i have class UsersController and a static method like bellow:
class UsersController < ApplicationController
def self.check
...
::SendMailTask.create(to: [] << #to_addresses, subject: #subject, body: #body)
end
When i call method UsersController.check() from other file, i received the error: "in `block in check': uninitialized constant SendMailTask (NameError)"
But from other controller, i can call SendMailTask normally:
class ErrorController < ApplicationController
def index
...
::SendMailTask.create(to: [] << #to_addresses, subject: #subject, body: #body)
end
I try to add this line:
config.autoload_paths += %W(#{config.root}/app/workers)
to application.rb and try to add
require './SendMailTask'
at the begin of file users_controller.rb but it does not work.
Please help me resolve this error. Thanks you
NameError means the your SendMailTask isn't loaded. so you will have to load that. so couple of things.
I noticed a typo workes, so please verify the file name is correct. By Convention, it should be located at app/workers/send_mail_task.rb. so kindly double-triple check the same.
About require './SendMailTask', this is wrong. Instead it would be send_mail_task as requires works on filenames & not class names.
if still get an error, then please post your $LOAD_PATH to see you are requiring the file relative to the defined $LOAD_PATH
Instead of require, I prefer to use require_dependency as it works with code-reloading etc. so if you have trouble with auto-loading, just stick that require_dependency on top of the file, this will hint rails to load the file BEFORE running the controller.

"NameError, uninitialized constant" error after modifying controller code

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.

Where to put custom classes to make them globally available to Rails app?

I have a class that I'm trying to use in my controller in the index action.
To simplify it, it looks like this
class PagesController < ApplicationController
def index
#front_page = FrontPage.new
end
end
FrontPage is a class that I have defined. To include it, I have placed it in the /lib/ folder. I've attempted to require 'FrontPage', require 'FrontPage.rb', require 'front_page', and each of those with the path prepended, eg require_relative '../../lib/FrontPage.rb'
I keep getting one of the following messages: cannot load such file -- /Users/josh/src/ruby/rails/HNReader/lib/front_page or
uninitialized constant PagesController::FrontPage
Where do I put this file/how do I include it into a controller so that I can instantiate an object?
This is Rails 3.1.3, Ruby 1.9.2, OS X Lion
You should be able to use require 'front_page' if you are placing front_page.rb somewhere in your load path. I.e.: this should work:
require 'front_page'
class PagesController < ApplicationController
def index
#front_page = FrontPage.new
end
end
To check your load path, try this:
$ rails console
ree-1.8.7-2011.03 :001 > puts $:
/Users/scottwb/src/my_app/lib
/Users/scottwb/src/my_app/vendor
/Users/scottwb/src/my_app/app/controllers
/Users/scottwb/src/my_app/app/helpers
/Users/scottwb/src/my_app/app/mailers
/Users/scottwb/src/my_app/app/models
/Users/scottwb/src/my_app/app/stylesheets
# ...truncated...
You can see in this example, the first line is the project's lib directory, which is where you said your front_page.rb lives.
Another thing you can do is add this in your config/application.rb:
config.autoload_paths += %W(#{config.root}/lib)
That should make it so you don't even need the require; instead Rails will autoload it then (and everything else in your lib dir, so be careful).
The file was named FrontPage.rb. Changing the name to 'front_page.rb', but leaving the class name as 'FrontPage' resolved the issue.
We just need to load the file,
class PagesController < ApplicationController
require 'front_page.rb'
def index
#front_page = FrontPage.new
end
end
lib/front_page.rb
class FrontPage
end
We can also set the application.rb to autoload these files
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
Second option would be a preferable solution.

Resources