Accessing a Constant Defined in ActiveRecord::Base - ruby-on-rails

I am trying to access the constant VALID_FIND_OPTIONS defined in ActiveRecord::Base (active_record/base.rb Line 2402 Rails 2.3.5).
ActiveRecord::Base::VALID_FIND_OPTIONS
I get the NameError exception.
NameError: uninitialized constant ActiveRecord::Base::VALID_FIND_OPTIONS
I have accessed the class constants in other libraries using the similar syntax before. I am not sure where I am going wrong.

The constant VALID_FIND_OPTIONS was defined inside the anonymous class of ActiveRecord::Base, hence it was not accessible as ActiveRecord::Base::VALID_FIND_OPTIONS
module ActiveRecord
class Base
class << self
# the constant belongs to the scope of the anonymous class
VALID_FIND_OPTIONS = [..]
end
end
end
The constant can be accessed using following syntax:
ActiveRecord::Base.singleton_class::VALID_FIND_OPTIONS

Where is the code that tries to get ActiveRecord::Base::VALID_FIND_OPTIONS?
If you are defining a class before ActiveRecord is loaded, then the constant will not be available.
You can force ActiveRecord to be loaded by requiring it. In some cases, you will have to require rubygems before requiring active_record.
Try requiring them both:
require 'rubygems'
require 'active_record'
# you should now be able to access ActiveRecord::Base::VALID_FIND_OPTIONS

Related

Ruby - NameError: uninitialized constant. Using class from a different module

I have these 2 files in a large system, both are located in PackA
people.rb
module People
class HobbyValueObject
end
end
job.rb
module People
class Job
end
class CityValueObject
end
end
I am trying to use CityValueObject in a different module like this,
Module is in PackB
work.rb
module Profile
class Work
....
def calculateTaxes
...
a = People::CityValueObject....
end
end
end
But it's giving me an error saying,
NameError: uninitialized constant People::CityValueObject
Did you mean? People::HobbyValueObject
Why is not being able to fine CityValueObject but can find HobbyValueObject just fine?
How do I make it find the object that I am intending to use?
I am not explicitly declaring any requires or includes
I was able to resolve this by adding require at the top while using full path file name.
require './packs/people/app/public/people/job'

ActiveRecord bug with namespaces or expected behavior?

Rails 4.1.16
Ruby 2.2.7
I have this ActiveRecord model:
class Something::Type < ActiveRecord::Base
When referencing the model like this:
Something::Type.find_by_whatever("test")
I get the following error:
NoMethodError: undefined method `find_by_whatever' for ActiveRecord::AttributeMethods::Serialization::Type:Class
I understand that Ruby constants are broken up, so that Type exists as its own constant, and the autoloader is finding ActiveRecord::AttributeMethods::Serialization::Type first.
However, referencing the namespace in an "absolute" way (prefixing with colons) is supposed to solve the issue, but the result is the same. Any ideas why?
::Something::Type.find_by_whatever("test")
NoMethodError: undefined method `find_by_whatever' for ActiveRecord::AttributeMethods::Serialization::Type:Class
The problem when you define a class with the scope resultion operator is that the module nesting is resolved to the point of definition (the point where you use the module keyword). If you look at the module nesting:
class Something::Type < ActiveRecord::Base
puts Module.nesting.inpsect # [Something::Type]
end
The class not even really nested in the Something module. Which will give you an extremely surprising constant lookup:
module Something
FOO = "test"
end
class Something::Type
puts Foo # gives a uninitialized constant error since its not looking in the Something module
end
Instead you should ALWAYS declare namespaced classes with explicit nesting:
module Something
class Type
puts Module.nesting.inspect # [Something::Type, Something]
puts Foo # test
end
end
Which gives the module nesting [Something::Type, Something] which means that it will properly look up constants in the same Something namespace.
This is something that the old classic autoloader tended to gloss over as it relied on monkeypatching Module#const_missing. Zeitwork does not so do it right.

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.

Using Watir and uninitialized constant Watir::RSpec::Core

I am trying to create a custom rspec formatter using Watir and got this error while executing the class. I have never used Watir before. Do I need some special gems for it?
Error: uninitialized constant Watir::RSpec::Core (NameError)
My code:
require 'rspec/core/formatters/html_formatter'
module Watir
class RSpec
class CustomFormatter < RSpec::Core::Formatters::HtmlFormatter
end
end
end
The exception is occurring because of the class that the CustomFormatter is trying to inherit from. Due to the location, it is look for the RSpec::Core::Formatters::HtmlFormatter class within the scope of the Watir::RSpec class.
Usually custom formatters are done as:
require 'rspec/core/formatters/html_formatter'
class CustomFormatter < RSpec::Core::Formatters::HtmlFormatter
end
You do not need to put it in a Watir::RSpec space.

Auto-create the containing module of a class

In Rails you can create a model under app/foo/bar.rb, with bar.rb containing:
class Foo::Bar
def some_method
puts "I work fine"
end
end
If you try to do this in a pure ruby app you'd get a NameError: uninitialized constant Foo unless you've already initialized a module Foo.
What is Rails doing that allows it to create classes without first initializing their containing module? Is it possible to import this behavior through something like activesupport, or are we left to implement on our own?
Rails modifies the Class class to include a const_missing method which gets called when an undefined class is used. It then loads things to try and load the requested class.
The implementation of this in ActiveSupport is in lib/active_support/dependencies.rb.
actually model class created is extend to < ActiveRecord::Base

Resources