I am trying to add a custom serializer to ActiveJob following the ActiveJob Rails Guide. I have the following class, originally in the file app/lib/money_serializer.rb,
class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
# ...
end
And in config/application.rb
# ...
config.active_job.custom_serializers << MoneySerializer
# ...
I keep getting uninitialized constant MoneySerializer (NameError) which suggests to me that the Serializer is not being loaded on boot and tried placing it in different locations (including under config/initializers) without any luck.
What am I missing here? Where should I place an ActiveJob serializer?
Based on the discussion here, the issue is best solved as follows:
Rails.autoloaders.main.ignore(Rails.root.join("app/serializers"))
Dir[Rails.root.join("app/serializers/**/*.rb")].each { |f| require f }
Rails.application.config.active_job.custom_serializers << MoneySerializer
Update: In Rails 7, you can simply add the following to config/application.rb:
config.autoload_once_paths += Dir[Rails.root.join("app/serializers")]
If it helps anyone,
It seems to work when I put both the Serializer and the config in an initializer
class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
# ...
end
config.active_job.custom_serializers << MoneySerializer
Feels very odd to have a class here. Any other suggestions?
Related
I'm trying to update this gem to work with rails 7 and I think that the error is due to zeitwerk. The error that's popping up is the following
/Users/nate/.rbenv/versions/3.0.2/lib/ruby/gems/3.0.0/gems/impressionist-2.0.0/lib/impressionist/engine.rb:15:in `block (2 levels) in <class:Engine>': uninitialized constant Impressionist::Engine::ImpressionistController (NameError)
and It's originating from lib/impressionist/engine.rb here from the lines below
module Impressionist
class Engine < ::Rails::Engine
attr_accessor :orm
initializer 'impressionist.model' do |app|
#orm = Impressionist.orm
include_orm
end
initializer 'impressionist.controller' do
require "impressionist/controllers/mongoid/impressionist_controller" if orm == :mongoid.to_s
ActiveSupport.on_load(:action_controller) do
include ImpressionistController::InstanceMethods <--- HERE
extend ImpressionistController::ClassMethods <--- HERE
end
end
private
def include_orm
require "#{root}/app/models/impressionist/impressionable.rb"
require "impressionist/models/#{orm}/impression.rb"
require "impressionist/models/#{orm}/impressionist/impressionable.rb"
end
end
end
I think that this first include is trying to call app/controllers/impressionist_controller.rb, but for some reason doesn't load with rails 7. Any ideas on how to approach fixing this? I suspect that I have to somehow incorporate zeitwerk here.
I'm trying to update my app from Rails 5.2 to 6.1, and use Zeitwerk autoload, and I am having some issues for autoloading /lib classes.
I included this in config/application.rb:
config.load_defaults 5.2
config.autoloader = :zeitwerk
config.enable_dependency_loading = true
config.autoload_paths += Dir[Rails.root.join('lib/**/*')]
config.eager_load_paths += Dir[Rails.root.join('lib/**/*')]
And, when I run zeitwerk:check, it alerts me that:
Hold on, I am eager loading the application.
expected file lib/facades/coconut/v2/foo.rb to define constant Foo
It is declared as:
# /lib/facades/coconut/v2/foo.rb
module Coconut
module V2
class Foo
# ...
end
end
end
When I try to debug it (putting a binding.pry in some test file), Zeitwerk says it do not defined, until I call it without modules (namespaces):
[1] pry(#<#filename>)> Coconut::V2::Foo
NameError: uninitialized constant Coconut::V2::Foo
from (pry):1:in `setup`
[2] pry(#<#filename>)> Foo
Zeitwerk::NameError: expected file /my-app/lib/api/coconut/v2/foo.rb to define constant Foo, but didn't
from /usr/local/bundle/gems/zeitwerk-2.5.4/lib/zeitwerk/loader/callbacks.rb:25:in `on_file_autoloaded'
[3] pry(#<#filename>)> Coconut::V2::Foo
=> Coconut::V2::Foo
It sounds really strange, because there are another classes in /lib that follows the same structure, but it works well, example
# /lib/api/services/youtube/client.rb
module Services
module Youtube
class Client
# ...
end
end
end
Inspecting it with binding.pry in some test:
pry(#<#filename>)> Services::Youtube::Client
=> Services::Youtube::Client
Has anyone had this problem or know what could be happening?
System:
ruby 2.7.6p219
Rails 6.1.6
Zeitwerk (2.5.4)
An autoload path is a root directory, not its contents.
You need to remove the wildcards as documented here.
I have some code i've inherited and am in the process of upgrading it to Rails 3.1. I'm suuuuper close to done but I got a bug.
In Rails Console I run User.first and I get this error
undefined local variable or method `acts_as_userstamp' for #<Class:0x000000046bef50>
Now acts_as_userstamp is a method located on line two inside my User model
class User < ActiveRecord::Base
#TODO /lib is not loading??? or is it??? why this method not work in browser?
acts_as_userstamp
And is defined in a file called app/lib/model_modifications.rb.
Now I recently discovered that my app/lib folder was not being autoloaded in my application.rb file and I think that's been fixed...or has it? Is this file correct? Or no?
require File.expand_path('../boot', __FILE__)
require 'rails/all'
# evil outdated soap middleware, TODO: kill it with fire
# Does this have to be loaded BEFORE the first line???
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', "vendor", "soap4r"))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', "vendor", "plugins", "soap4r-middleware", "lib"))
# evil outdated soap middleware, TODO: kill it with fire
require 'soap4r-middleware'
require File.join(File.dirname(__FILE__), '..', 'app', 'lib', 'soap.rb')
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module MyappDev
class Application < Rails::Application
# startup the lib directory goodies <-- IS THIS CORRECT???
# config.autoload_paths << "#{Rails.root}/lib"
# config.autoload_paths += %W( lib/ )
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
config.middleware.use MyAPIMiddleware
end
end
I'm trying to debug this file as I post this now. Here is a peak at it's internal structure...(i've just included the overall structure for the sake of brevity)
app/lib/model_modificatons.rb
class Bignum
...
end
class Fixnum
...
end
class ProcessorDaemon
...
end
module ActiveRecord
module UserMonitor
...
end
module MyLogger
...
end
end
class Object
...
end
class Struct
...
end
class String
...
end
class Fixnum
...
end
class OpenStruct
...
end
class ActiveRecord::Base
def self.visible_columns
...
end
...
def self.acts_as_userstamp
logger.info "HI fonso - acts_as_userstamp is called"
include ActiveRecord::UserMonitor
end
...
protected
def self.range_math(*ranges)
...
end
end
class Array
...
end
class DB
...
end
If you can spot a problem with the overall structure or anywhere else please let me know.
So why is this method not found? I'm trying to debug it as I'm posting this and I'm getting nothing.
I suspect the file app/lib/model_modifications.rb is not being loading. That nothing in the /lib directory is being loaded..but how do I confirm this?
Thank you for reading this far, I hope I've not rambled on too much.
autoload_path configuration does not load all the given files on the boot but defines folders where rails will be searching for defined constants.
When your application is loaded, most of the constants in your application are not there. Rails have a "clever" way of delaying loading the files by using a constant_missing method on Module. Basically, when Ruby encounters a constant in the code and fails to resolve it, it executes said method. THe sntandard implementation of this method is to raise UndefinedConstant exception, but rails overrides it to search all of its autoload_paths for a file with a name matching the missing constant, require it and then check again if the missing constant is now present.
So, in your code everything works as expected and you need to load this extension file manually. If you want to have some code that executes on the application boot, put your file within config/initializers folder.
Aside: Try avoiding monkey patching whenever possible. It might be looking clever, but adding more methods to already overpopulated classes will not make them easier to use.
My cop:
# lib/rubocop/cop/myproject/my_cop.rb
require 'rubocop'
module RuboCop
module Cop
module MyProject
class MyCop < RuboCop::Cop::Cop
# ...
end
end
end
end
This cop needs to know some global settings Rails. For example, Rails.logger.log_level
But I get errors:
1) undefined method 'logger' for RuboCop::Cop::Rails:Module - when I call Rails.logger.log_level
2) uninitialized constant Rails - when I call ::Rails.logger.log_level
Can this be done or is it a stupid idea?
As an option you can do:
# lib/rubocop/cop/myproject/my_cop.rb
require 'rubocop'
require_relative '../../../../../config/environment'
module RuboCop
module Cop
module MyProject
class MyCop < RuboCop::Cop::Cop
# ...
end
end
end
end
And call ::Rails.logger.level
Rubocop is a static code analyzer. Which means when you run rubocop command, it does not load any ruby environments, including Rails. It just reads ruby files and analyses those as text files.
So the short answer is: no, it can not be achieved with Rubocop.
Since rails 3.2.9 I'm unable to store models in subfolders. In my app I have this tree:
models
-type_models
-assets
-user
-concerns
Also in application.rb there is
config.autoload_paths += Dir["#{config.root}/app/models/*"]
All things was ok till rails 3.2.9. Now I have "Unknown constant" error.
I don't want to namespace tons of model and fix all app to use namespaced models.
Warning: Error loading /var/www/my_app/app/models/type_models/context_type.rb:
uninitialized constant TypeModels::ContextType
file context_type.rb:
class ContextType ... end
Try to use:
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
in config/application.rb:
config.autoload_paths += %W(type_models assets user concerns).map { |folder| "#{config.root}/app/models/#{folder}"}
in models/type_models/context_type.rb:
class TypeModels::ContextType < ActiveRecord::Base
...
end
Restart Rails and you're all set!
Wrap your class ContextType ... end to module:
module TypeModels
class ContextType
# blah blah
end
end