I'm using sidekiq to do a simple sample worker. When a make a request to my endpoint, it finished successfully but in the worker I got the following error:
*** NameError Exception: uninitialized constant SaveMessageWorker::Message
I'm using:
ruby 2.5.7
rails 5.2.3
sidekiq 6.0.0
This is part of my api rails project structure:
app
---controllers
------api
---------v1
------------messages_controller.rb
---workers
------save_message_worker.rb
config
---initializers
------sidekiq.rb
---application.rb
These are my files and paths:
app/workers/save_message_worker.rb
class SaveMessageWorker
include Sidekiq::Worker
def perform(message_list)
# byebug
# When I tried the below line, I got: *** NameError Exception: uninitialized constant SaveMessageWorker::Message
message = Message.new(message: message_list)
end
end
app/controllers/api/v1/messages_controller.rb
def multiple_concurrent_workers
begin
SaveMessageWorker.perform_async("Hello World!")
return (render json: {status: "success", data:"processed successfully"})
rescue => exception
logger.error CONTROLLER_NAME + ': An error happened in method multiple_concurrent_workers: ' + exception.to_json
return (render json: {status: "error", message: exception})
end
end
config/routes.rb
Rails.application.routes.draw do
require 'sidekiq/web'
mount Sidekiq::Web => '/sidekiq'
devise_for :users
namespace :api, defaults: { format: "json" } do
namespace :v1 do
resources :messages do
collection do
post :multiple_concurrent_workers
end
end
end
end
end
config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
config.redis = { url: 'redis://' + Rails.application.credentials[Rails.env.to_sym][:redis][:host].to_s + ':' +Rails.application.credentials[Rails.env.to_sym][:redis][:port].to_s + '/' + Rails.application.credentials[Rails.env.to_sym][:redis][:database].to_s }
end
Sidekiq.configure_client do |config|
config.redis = { url: 'redis://' + Rails.application.credentials[Rails.env.to_sym][:redis][:host].to_s + ':' +Rails.application.credentials[Rails.env.to_sym][:redis][:port].to_s + '/' + Rails.application.credentials[Rails.env.to_sym][:redis][:database].to_s }
end
config/application.rb
require_relative 'boot'
require "rails"
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
require "rails/test_unit/railtie"
Bundler.require(*Rails.groups)
module IbeenDev
class Application < Rails::Application
config.load_defaults 5.2
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
config.middleware.use ActionDispatch::Flash
config.log_level = :error
config.autoload_paths << Rails.root.join("lib")
config.eager_load_paths << Rails.root.join("lib")
config.api_only = true
Koala.config.api_version = 'v2.0'
config.active_job.queue_adapter = :sidekiq
end
end
There was an opened issued in the github project, but author said that this is not an exactly sidekiq problem.
Can anyone help me to find the solution? Any help will be appreciated
Related
I am following the rails api book but building the code in an engine. The test is at spec/controllers/concerns/handicap/authenticable_spec.rb and looks like this
require 'spec_helper'
require_relative '../../../../app/controllers/concerns/handicap/authenticable.rb'
class Authentication
include Handicap::Authenticable
end
module Handicap
describe Authenticable, type: :controlller do
let(:authentication) { Authentication.new }
subject { authentication }
describe "#current_user" do
before do
#user = FactoryGirl.create :handicap_user
request.headers["Authorization"] = #user.auth_token
authentication.stub(:request).and_return(request)
end
it "returns the user from the authorization header" do
expect(authentication.current_user.auth_token).to eql #user.auth_token
end
end
end
end
When I run the test directly i.e. rspec ./spec/controllers/concerns/handicap/authenticable_spec.rb I get an error:
uninitialized constant Handicap::FactoryGirl
However, when I run all the tests i.e. rspec spec, it does find the FactoryGirl constant and the test fails with
undefined local variable or method `request' for #<RSpec::ExampleGroups::HandicapAuthenticable::CurrentUser:0x007ff276ad5988>.
According to this github issue, I need to add < ActionController::Base to the Authentication class i.e.
class Authentication < ActionController::Base
but if I add this in, I get
uninitialized constant ActionController
I have also tried adding < Handicap::ApplicationController but get
uninitialized constant Handicap::ApplicationController
There appears to be something wrong with my namespacing. There are three symptoms, the fact that FactoryGirl cannot be found if I run the test by itself, but is found when all the tests are run. The second is that it cannot find ActionController even when all the tests are run. The third is that I need to add the line:
require_relative '../../../../app/controllers/concerns/handicap/authenticable.rb'
to find the module that is being tested.
How do I fix my namespacing?
The rails_helper.rb file is
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../dummy/config/environment.rb', __FILE__)
require 'rspec/rails'
require 'capybara'
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara-screenshot'
require 'capybara-screenshot/rspec'
require 'capybara/poltergeist'
require 'capybara/email/rspec'
require 'pp'
require 'chris_api_helpers'
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'factory_girl_rails'
ActiveRecord::Migration.maintain_test_schema!
Shoulda::Matchers.configure do |config|
config.integrate do |with|
# Choose a test framework:
with.test_framework :rspec
with.library :rails
end
end
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# force test migrations for db:migrate
ActiveRecord::Migration.maintain_test_schema!
Capybara::Screenshot.prune_strategy = { keep: 20 }
Capybara::Screenshot.append_timestamp = false
config.include FactoryGirl::Syntax::Methods
FactoryGirl.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
FactoryGirl.find_definitions
config.include Devise::Test::ControllerHelpers, type: :controller
end
and the spec_helper.rb is
require 'simplecov' if ENV["COVERAGE"]
SimpleCov.start do
add_filter '/spec/'
add_filter '/config/'
add_filter '/lib/'
add_filter '/vendor/'
add_group 'Controllers', 'app/controllers'
add_group 'Models', 'app/models'
add_group 'Helpers', 'app/helpers'
add_group 'Mailers', 'app/mailers'
add_group 'Views', 'app/views'
end if ENV["COVERAGE"]
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
#http://stackoverflow.com/questions/30859037/suppress-backtrace-for-rspec-3
config.backtrace_exclusion_patterns = [
/\/lib\d*\/ruby\//,
/bin\//,
/gems/,
/spec\/spec_helper\.rb/,
/lib\/rspec\/(core|expectations|matchers|mocks)/
]
end
You should not be putting specs into modules. This is the cause of problem here. If you need to reference a namespaced class, reference it like RSpec.describe Handicap::Authenticatable.
In general, when you are within a namespace and need to reference something explicitly from the 'root' scope, you can prepend it with double-colons. Such as:
module Handicap
class Something
def do_stuff
::FactoryGirl.create(:person)
end
end
end
It turns out that at the top of my file I should have had require 'rails_helper', not require 'spec_helper'``. All my other files hadrequire 'rails_helper'`` so when I ran the whole test suite, the rails_helper was being loaded anyway.
Embarrassing, but this Q&A might help someone else that has trouble spotting simple errors.
I am building a Rails-API using Omniauth-facebook and Devise-token-auth with Angular and ng-token-auth for the frontend.
However when logging in with facebook I am presented with the error:
undefined local variable or method `flash' for #<Devise::OmniauthCallbacksController:0x007fd027a51e10>
It seems omniauth automatically uses flash middleware however the rails-api doesn't include this and I have been unsuccessfully disabling the use of flash with omniauth.
My configuration is as below:
application.rb:
require File.expand_path('../boot', __FILE__)
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module PathfinderApi
class Application < Rails::Application
config.active_record.raise_in_transactional_callbacks = true
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
config.api_only = true
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
end
end
devise_token_auth.rb:
DeviseTokenAuth.setup do |config|
Rails.application.secrets.facebook_app_secret
config.change_headers_on_each_request = true
end
devise.rb:
Devise.setup do |config|
config.navigational_formats = [:json]
end
omniauth.rb:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['APP_KEY'], ENV['APP_SECRET']
end
I have not managed to disable the flash error with:
config.navigational_formats = [:json]
and devise/omniauth is still using flash middleware and throws the error, any help appreciated!
Had the same problem. Searched the devise source code for 'flash'. Found about 17 matches, all using set_flash_message! (with exclamation mark), except for the failure method in the OmniauthCallbacksController, which uses set_flash_message (without exclamation mark). Looking at the definition we see:
\app\controllers\devise\omniauth_callbacks_controller.rb
# Sets flash message if is_flashing_format? equals true
def set_flash_message!(key, kind, options = {})
if is_flashing_format?
set_flash_message(key, kind, options)
end
end
\lib\devise\controllers\helpers.rb
def is_flashing_format?
is_navigational_format?
end
def is_navigational_format?
Devise.navigational_formats.include?(request_format)
end
The actual flash message is generated in the method without exclamation mark (I would have progged it the other way around...). The missing exclamation mark is the reason why setting the navigational_formats as mentioned in other solutions doesn't work here.
Conclusion: they forgot the exlamation mark.
The fix: monkey-patch the failure method from the OmniauthCallbacksController. Do this in an initializer, for example in
\config\initializers\devise.rb
Rails.application.config.to_prepare do # to_prepare ensures that the monkey patching happens before the first request
Devise::OmniauthCallbacksController.class_eval do # reopen the class
def failure # redefine the failure method
set_flash_message! :alert, :failure, kind: OmniAuth::Utils.camelize(failed_strategy.name), reason: failure_message
redirect_to after_omniauth_failure_path_for(resource_name)
end
end
end
Had the same problem in Rails (5.0.0.1) + devise_token_auth (0.1.39).
Besides the override in #Koen's answer, the following addition is also necessary in my case:
# in config/application.rb
config.middleware.use ActionDispatch::Cookies
I managed to solve this by adding this to the devise.rb config:
config.navigational_formats = []
This way devise will never attempt to use flash and never throw a 500 error.
Taken from https://github.com/heartcombo/devise/issues/4275
I have strange error when i run my tests for helpers with rake test:helpers
ApplicationHelper::dummy#test_0001_must return string:
NameError: Unable to resolve controller for ApplicationHelper::dummy
Test:
require "test_helper"
describe ApplicationHelper do
include ApplicationHelper
context "dummy" do
it "must return string" do
result = dummy()
result.must_be_kind_of ( String )
result.wont_be_empty
end
end
end
My helper
module ApplicationHelper
def dummy
"hello world".html_safe
end
end
My test_helper
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/rails/capybara"
require 'minitest/rg'
require "warden_mock"
class ActiveSupport::TestCase
fixtures :all
class << self
alias :context :describe
end
end
class ActionController::TestCase
def setup
request.env['warden'] = WardenMock.new # mockup warden
User.current = request.env['warden'].user
end
register_spec_type(/.*/, self)
end
rails 4.1.6
minitest-rails 2.1.0
Try to comment out require "minitest/rails/capybara" in your test_helper.rb and require it only in your feature tests
Getting the following when running my capybara rails tests with "rake test". Problem seems to be url helpers I'm using in my application.html.erb:
DashboardLoginTest#test_login_and_check_dashboard:
ActionView::Template::Error: arguments passed to url_for can't be handled. Please require routes or provide your own implementation
app/views/layouts/application.html.erb:29:in `_app_views_layouts_application_html_erb__938277815294620636_4045700'
test/integration/dashboard_login_test.rb:6:in `block in <class:DashboardLoginTest>'
Here's line 29 in application.html.erb that its complaining about:
<%= link_to("asdf", root_path, {:class => 'brand'}) %>
Here's what the test looks like:
test "login and check dashboard" do
visit("/")
assert page.has_content?("welcome")
end
Here's my test_helper.rb:
ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'factory_girl'
require 'capybara/rails'
include Warden::Test::Helpers
Warden.test_mode!
def main_app
Rails.application.class.routes.url_helpers
end
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
fixtures :all
end
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
include Rails.application.routes.url_helpers
def sign_in(user = nil)
if user.nil?
user = FactoryGirl.create(:user)
$current_user = user
end
login_as(user, :scope => :user)
user.confirmed_at = Time.now
user.save
end
end
Why the error?
Here's the setup:
config/initializers/rack_ip_restrictor.rb
Rack::IpRestrictor.configure do
respond_with [403, {'Content-Type' => 'text/html'}, '']
ips_for :test do
add '127.0.0.1'
add '127.0.0.2/8'
end
restrict /^\/admin/, '/admin', :only => :test
end
config/application.rb
class Application < Rails::Application
...
config.middleware.use Rack::IpRestrictor.middleware
...
end
/lib/rack_ip_restrictor.rb
require 'ipaddr'
require 'active_support/core_ext/array/extract_options'
# namespace Rack
module Rack
# namespace IpRestrictor
module IpRestrictor
class << self
attr_reader :config
# #see Config#initialize
def configure(&block)
#config = IpRestrictor::Config.new
#config.instance_eval &block
end
# Rack middleware
# #return [Middleware] The configured plug & play Rack middleware
def middleware
IpRestrictor::Middleware
end
end
end
end
require 'rack_ip_restrictor/ip_group'
require 'rack_ip_restrictor/middleware'
require 'rack_ip_restrictor/config'
require 'rack_ip_restrictor/restriction'
Any idea why rails can't find Rack::IpRestrictor ?
Thanks
You're not requiring this file anywhere. That is why it cannot find the constant. Files in the lib directory are not automatically loaded in Rails 3. Require this file manually.