Error using Log4r - ruby-on-rails

I have a problem using Log4r.
uninitialized constant Log4r::Logger::RootLogger
I tried this, but still got an error:
>> require "log4r"
=> true
>> Log4r::DEBUG
NameError: uninitialized constant Log4r::DEBUG
>> Log4r::Logger.root
=> uninitialized constant Log4r::Logger::RootLogger
from /var/lib/gems/1.9.1/gems/log4r-1.1.11/lib/log4r/staticlogger.rb:5:in `root'
from (irb):5
from /usr/bin/irb:12:in `<main>'

Your problem with Log4r::Logger.root is version depending (the actual version 1.1.11 has this problem).
You may use the previous log4r-version 1.1.10:
gem 'log4r', '<=1.1.10' #or '= 1.1.10'
require 'log4r'
Log4r::Logger.root
log4r defines the constants like Log4r::DEBUG with the creation of the first logger.
You need a Log4r::Logger.new('dummy') before you have access to the level constants.
require 'log4r'
p defined? Log4r::INFO #false
Log4r::Logger.new('dummy')
p defined? Log4r::INFO #constant -> is defined
Some background:
There is a constant Log4r::Log4rConfig::LogLevels defining the different levels. The level-constants are defined, when the first logger is created. You may define them also with Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
This technique allows it to create loggers with different logging levels.

AlthoughLog4r::Logger.root no longer enables the constants, the code included later on in the answer you referred to does introduce the constants:
Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
per the following:
MacbookAir1:so1 palfvin$ irb
2.0.0p247 :001 > require 'log4r'
=> true
2.0.0p247 :002 > Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
=> 5
2.0.0p247 :003 > Log4r::DEBUG
=> 1
2.0.0p247 :004 >

Related

What all things can you access when you require a gem?

Let us take Rails gem for example
Before require 'rails'
irb(main):001:0> Rails
NameError: uninitialized constant Rails
irb(main):002:0> ActionPack
NameError: uninitialized constant ActionPack
After require 'rails'
irb(main):005:0> require 'rails'
true
irb(main):007:0> Rails.constants
[:Railtie, :Rack, :Initializable, :Configuration, :WelcomeController, :InfoController, :VERSION, :Paths, :Info, :MailersController, :Application, :Engine]
irb(main):009:0> ActionPack.methods-Object.methods
[:gem_version, :version, :initialize_copy]
So now the ActionPack module is available in the console, what other modules or class (if any) are available and how to know about those modules?
Thats up to the gem developer. To see how your Name- and Objectspace changed there should be many clever ways.
I answer shortly how to find out which new Module (-Constants) there are:
initial_modules = Module.constants
# -> [:Object, :Module, :Class, :BasicObject, :Kernel, :NilClass, ...]
require 'rails'
Module.constants - initial_modules # all NEW constants
# -> [:Pathname, :OpenSSL, :Digest, :SecureRandom, :Concurrent, :I18n, :CGI, :ActiveSupport, :Set, :SortedSet, :Timeout, :TimeoutError, :Logger, :LoggerSilence, :DateAndTime, :Psych, :StringScanner, :ScanError, :Date, :DateTime, :YAML, :Base64, :TSort, :Rails, :BigDecimal, :BigMath, :TZInfo, :ThreadSafe, :Threadsafe, :SynchronizedDelegator, :JSON, :OpenStruct, :Singleton, :Mutex_m, :ActionPack, :Rack, :ActionDispatch, :Mime]
As you see, this also comes with a lot of new stuff that is required (but not provided) by Rails, like Date, OpenSSL, etc.pp.
Actually, requirements can happen at runtime, too, such that this lists grows as you use the code.
Hope that helps a bit.

Reload namespaced constant in initializer

Ran into an interesting scenario today that I'm unsure how to resolve.
Given a rails app with an initializer:
file: config/initializers/integrations.rb
Integrations::CONFIGS = { "key" => "value" }.freeze
If I go into bundle exec rails console and ask for that constant it works as expected:
Integrations::CONFIGS
=> {"key"=> "value"}
Then if I use reload! in the console, I lose that constant:
[2] pry(main)> reload!
Reloading...
=> true
[3] pry(main)> Integrations::CONFIGS
NameError: uninitialized constant Integrations::CONFIGS
from (pry):3:in `<main>'
If I remove the namespace and just have CONFIGS as a constant it works and reloads as expected. I've read through as much of the reload! documentation as I could find and from what I can tell this isn't expected.
My question being, how can I correctly use a namespaced constant in an initializer while also still being able to use reload!?

Ruby Gemfile gem has different behavior than 'require' gem

I am using the Matrix library in Ruby, and when I use it in irb, it works fine:
2.1.5 :001 > require 'matrix'
=> true
2.1.5 :002 > a=Matrix.build(3,3) { |row,col| row==col ? 0 : 1}
=> Matrix[[0, 1, 1], [1, 0, 1], [1, 1, 0]]
But when I use it from Gemfile, the behavior is different:
Loading development environment (Rails 4.1.8)
2.1.5 :001 > a=Matrix.build(3,3) { |row,col| row==col ? 0 : 1 }
NoMethodError: undefined method `build' for Matrix:Module
I inspected this a bit, and I noticed the require behavior loads a class, while Gemfile loads a module:
Require:
2.1.5 :003 > Matrix.class
=> Class
2.1.5 :004 > Matrix.constants
=> [:EigenvalueDecomposition, :LUPDecomposition, :SELECTORS, :ConversionHelper, :CoercionHelper, :Scalar, :ErrDimensionMismatch, :ErrNotRegular, :ErrOperationNotDefined, :ErrOperationNotImplemented]
Gemfile:
2.1.5 :002 > Matrix.class
=> Module
2.1.5 :003 > Matrix.constants
=> [:VERSION]
How should I include this in my Rails project? I can use require somewhere, but I'd really rather load it as a dependency from Gemfile.
Ruby Gemfile gem has different behavior than 'require' gem
Yes, that's because they are two different things. Adding a gem to your Gemfile does not replace the need to require classes, it only informs the bundler that this gem is needed to run your program. See here for more information about Gemfile and Bundler.
I think you're installing the matrix 'gem' http://rubygems.org/gems/matrix in your gemfile. The matrix class is part of stdlib so you should not need to install a gem for it: http://www.ruby-doc.org/stdlib-2.0/libdoc/matrix/rdoc/Matrix.html. You do need to require it to use it however.
TL/DR: Remove gem 'matrix' from your Gemfile and just use require 'matrix' to use the stdlib matrix implementation rather than the seemingly empty 'matrix' gem Module.

Where is Rails.application defined?

Out of curiosity, where is Rails.application defined? If I do this in irb in a Rails-powered app, I got an error:
$ irb
1.9.3-p327 :001 > require 'rails/application'
=> true
1.9.3-p327 :002 > class App < Rails::Application; end
NoMethodError: undefined method `application' for Rails:Module
I have tried requiring more, like active_support and rails/railtie/configuration but no luck.
The purpose of this is to load a minimal Rails env where I can test an ActiveRecord::Base helper :)
Usually when working with Rails you use rails console instead of IRB. When you run rails console it will boot up your Rails application.
FWIW, Rails.application is defined in railties:
lib/rails.rb

How to figure out which Ruby gem has hijacked an ActiveRecord association method

Given this definition (using Rails 3.2.13 on Ruby 2.0.0-p195)...
class Food < ActiveRecord::Base
has_many :recipe_foods, foreign_key: :food_id
.reset is not acting as documented (it's supposed to reset the #loaded flag but instead it's re-querying the database and returning results)...
2.0.0-p195 :037 > f = Food.last
Food Load (1.6ms) ...
=> #<Food ...
2.0.0-p195 :038 > f.recipe_foods
RecipeFood Load (9.4ms) ...
=> [#<RecipeFood ...
2.0.0-p195 :039 > f.recipe_foods.reset
RecipeFood Load (10.0ms) ...
=> [#<RecipeFood ...
I suspect some other gem has hijacked the method, but this is what I get from .method ...
2.0.0-p195 :040 > f.recipe_foods.method(:reset).source_location
NameError: undefined method `reset' for class `Array'
How do I figure out what version of .reset is actually executing?
UPDATE:
When I try to call a non-existent method I get this chaos (in case that helps with the mystery):
2.0.0-p195 :052 > f.recipe_foods.snafu
NoMethodError: undefined method `snafu' for #<ActiveRecord::Relation:0x007fdaef6315b0>
2.0.0-p195 :053 > f.recipe_foods.method(:snafu)
NameError: undefined method `snafu' for class `Array'
My guess is that reset is actually a method on the AssociationProxy object, not the Array, which is why you're getting the undefined method. Rails 4 seems to be smarter about this:
> c = Company.first
> c.users.method(:find)
=> # <Method: ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_User(ActiveRecord::Associations::CollectionProxy)#find>
> c.users.method(:find).source_location
=> ["/Users/me/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/associations/collection_proxy.rb", 140]
I'm not sure of the best solution here, but I'd see if any of the tools in pry can be helpful.
Use a debugger. ruby-debug worked up until Ruby 1.9; byebug works for Ruby 2.0.
Write a script with a debugger breakpoint right before the call that's breaking:
f = Food.last
rf = f.recipe_foods
byebug # or debug
rf.reset
Then execute the script. The debugger will break right at before the call, which you can then step into to find out what code is actually being executed.

Resources