Rails 3.2.7 auto reloading lib - ruby-on-rails

I've tried most of the solutions such as require_dependency, adding autoload in application.rb, and enabling the lib folders but still no dice.
Here's how my application is set up:
I have in lib/index_tank_searcher.rb:
class IndexTankSearcher < Spree::Core::Search::Base
def method
end
end
And I have Spree::Config.searcher_class = IndexTankSearcher in config/intializers/spree.rb.
Any ideas on how to make sure that index_tank_searcher.rb auto reloads without restarting the server each time it changes?

Reloading classes doesn't mutate existing classes. Classes to be unloaded are unassigned from their constant and a fresh copy is assigned. This is easily verifiable in the console
1.9.3p194 :002 > User.object_id
=> 70274894338560
1.9.3p194 :003 > reload!
Reloading...
=> true
1.9.3p194 :004 > User.object_id
=> 70274935456220
However Spree::Config.searcher_class is still set to the original IndexTankSearcher class.
You could add a to_prepare callback that will be called on each request in development, but only once (on startup) in production

Related

Rails cant connect to database with ActiveRecord::establish_connection

I am opening rails console session and do:
2.6.3 :048 > ActiveRecord::Base.connected?
=> true
2.6.3 :049 > ActiveRecord::Base.connection_pool.disconnect!
=> []
2.6.3 :050 > ActiveRecord::Base.connected?
=> false
2.6.3 :051 > ActiveRecord::Base.establish_connection(:development)
=> #<ActiveRecord::ConnectionAdapters::ConnectionPool:0x00 ... >
2.6.3 :052 > ActiveRecord::Base.connected?
=> false
2.6.3 :053 > SomeModel.connection
=> #<ActiveRecord::ConnectionAdapters::PostgreSQLAdapter:0x00 ...>
2.6.3 :055 > ActiveRecord::Base.connected?
=> true
$ rails -v
Rails 5.2.3
my config/database.yml file has to be fine, because HTTP requests are working fine.
Why I cant establish connection in rails console this way?
I am asking because I have similar use of establish_connection in one of config/initializers/ file, that is configuring sneakers workers like here and there it is also returning me false on ActiveRecord::Base.connected?
To connect again you can use
ActiveRecord::Base.connect
AR calls establish_connection only once, for ActiveRecord::Base. All subclasses use the one connection.
You can manually call establish connection yourself on some subclasses. This is very convenient for using two databases at once, e.g.
class MyMainUser < ActiveRecord::Base; end
class MyOtherDb < ActiveRecord::Base; end
class MyOtherUser < MyOtherDb; end
MyOtherDb.establish_connection ...
MyMainUser.first # uses default db
MyOtherUser.first # uses other db
You can't do queries that would cross databases though.
To connect you can use ActiveRecord::Base.connection and than you can call Somemodel.first and its should work.

Cannot override core ruby class in Rails 2.3.4

I want to extend the ruby class, for example,
# lib/core_ext/hash.rb
class Hash
def gop_compact
delete_if{|k, v| (k.blank? || v.blank?)}
end
end
I have created a separate folder in the /lib directory as follows,
lib/core_ext/hash.rb
And I tried to include this path in load_paths as follows,
# config/environment.rb
config.load_paths += %W( #{RAILS_ROOT}/lib/core_ext )
After all this setup, restarted the server and tried calling method on a Hash object but it throws an undefined method exception.
Note:- Rails version is 2.3.4
I spent lot of time on this but no luck yet. Any help is appreciated.
Thanks in advance!
Even though you've added the core_ext folder to your load paths, you'll still need to require it with require 'hash'. To minimize memory usage, Rails won't actually require ruby files just because you add them to your load_path.
>> Hash.instance_methods.grep(/gop/)
=> []
>> require "hash"
=> true
>> Hash.instance_methods.grep(/gop/)
=> [:gop_compact]

Ruby on Rails: Configure API in initializer in development

I have a Ruby on Rails app with an API in lib. Files in lib are autoloaded, and the API is configured in an initializer.
# lib/my_api.rb
module MyApi
extend Configuration
end
# lib/my_api/configuration.rb
module MyApi
module Configuration
attr_accessor :my_setting
def configure
yield self
end
end
end
# config/initializers/my_api.rb
MyApi.configure do |config|
config.my_setting = 'foo'
end
This works in production, but in development the API gets configured when the server is started. After I change some code, the configuration is lost and there are errors because the settings are nil:
irb(main):001:0> MyApi.my_setting
=> "foo"
irb(main):002:0> reload!
Reloading...
=> true
irb(main):003:0> MyApi.my_setting
=> nil
My guess is that in development, the classes are reloaded, but the initializer is not, which means it only gets configured once after starting the server.
Right now I'm duplicating my configuration in lib/my_api.rb, but that's very hacky.
What's a clean solution for this problem?
module MyApi
module Configuration
mattr_accessor :my_setting
def configure
yield self
end
end
end
mattr_accessor is an ActiveSupport macro for creating module level accessors.
Well, until someone comes up with a better solution, I've come up with two workarounds. I went with 2.
Don't autoload the lib directory (meaning don't autoload the API). That means having to restart the server when the API code changes, but solves the problem. That's why configuring gems like this works -- because they aren't autoloaded.
Manually reload the initializer in development at the end of lib/my_api.rb:
load Rails.root.join('config/initializers/smart_meter.rb') if Rails.env.development?
The MyApi constant will be replaced by a new one when Rails autoloads classes. The configuration is still available on the old object:
Loading development environment (Rails 4.2.0)
irb: warn: can't alias context from irb_context.
irb(main):001:0> MyApi.my_setting
=> "foo"
irb(main):002:0> OldMyApi = MyApi
=> MyApi
irb(main):003:0> reload!
Reloading...
=> true
irb(main):004:0> MyApi.my_setting
=> nil
irb(main):005:0> OldMyApi.my_setting
=> "foo"
irb(main):006:0> load Rails.root.join('config/initializers/smart_meter.rb')
=> true
irb(main):007:0> MyApi.my_setting
=> "foo"

Error using Log4r

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 >

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