Rails requiring standard Ruby libraries? - ruby-on-rails

I ran into an issue testing a new app in production environment.that Net::HTTP was not defined, but in development it was.
Naturally a require 'net/http' somewhere solves this (e.g. I put it in config/application.rb after Bundler.require(*Rails.groups),as I understand, there is no gem name I can add to Gemfile).
But can I find a list of which Ruby standard modules/classes need to be required, or should I just start adding everything I need to application.rb to be clear (date, json, net/http, etc.)?

Related

Upgrading Rails, how to autoload constants before config/environment/devlopment.rb runs?

I'm new to Ruby and Rails, so please forgive me if this is a n00b question. I'm trying to upgrade a very old app (using Ruby 2.3.4 and Rails 5.0.6) to the latest versions of Ruby (3.1.3) and Rails (7.0.4). When config/environment/devlopment.rb executes, I get an uninitialized constant error. It's trying to access a constant that's defined in a file /lib/settings.rb. If I try to use this constant in a controller, I have no problems. However, trying to use this constant in my development.rb causes the error.
I've already added these lines to my application.rb, but it hasn't helped:
config.autoload_paths << "#{Rails.root}/lib"
config.eager_load_paths << "#{Rails.root}/lib"
From my research, this seems to be a problem with autoloading, and that the new Rails uses something called Zeitwerk which does loading a bit differently. However, I'm not sure how to make this work. Is there a way to get this constant to load before development.rb executes?
Files in lib are not supposed to be autoloaded. Please don't add those configuration lines, instead, issue a
require 'settings'
in config/environments/development.rb.
The reason for the error is likely caused by changes in how Rails handles autoloading in the latest versions. In previous versions of Rails, constants defined in lib were automatically loaded, but in newer versions this is not the case.
One solution is to use the require_dependency method in your development.rb file to explicitly require the file that defines the constant. For example:
require_dependency "#{Rails.root}/lib/settings"
Alternatively, you can use the config.autoload_paths and config.eager_load_paths settings in your application.rb file to specify that Rails should automatically load files in the lib directory. However, based on your existing configuration this should be already covered.
Another option is to move the constant definition to a file located under the app directory, which will be automatically loaded by Rails.
It's also worth noting that upgrading such a large version gap of Ruby and Rails may require significant effort and testing, and it's recommended to take a backup of the current application before proceeding with the upgrade.

explanation of application.rb file in Rails App

I'm trying to get a deeper understanding of how a rails app initializes. I'm looking over the config/application.rb file and I'm confused by these three lines:
require_relative 'boot'
require 'rails/all'
Bundler.require(*Rails.groups)
From what I can tell all three of these lines are loading the gems used by the Rails Application. boot.rb appears to load all the gems as does Bundler.require(*Rails.groups). Why is it necessary to have all three lines of code?
Mostly correct, and you can verify what is "needed" by disabling one line at a time in a working Rails app.
require_relative 'boot': Application still runs.
require 'rails/all': Method not found error for a gem not listed in my Gemfile (one of Rails' built-ins (require 'rails/all')
Bundler.require(*Rails.groups): Method not found for gem from Gemfile.
So, the second and third are independent and essential. boot.rb's call to bundler/setup cannot stand in for either of the other two, because its function is actually to clean the load path by making sure that only Gemfile gems are included, and everything else is removed. See the last line of the Bundler setup source. So, while the app runs, it could be running with access to other gems that you did not intend to include, and give you a false sense that the app is working when it could fail for another user who only installed the Gemfile dependencies.
So you may get away with only the second and third in the short term, but would definitely want all three on anything that someone else may someday have to execute. The overhead is minimal so I would not remove any of these.
require_relative 'boot'
Sets up Bundler and load paths for gems
require 'rails/all'
This loads the rails gems. It can be replaced in order to explicitly require only the rails gems that you need (i.e. require "action_mailer/railtie"
Bundler.require(*Rails.groups)
This requires gems listed in your Gemfile by default. If you remove this line, you would have to require each gem by hand.

require 'lib/my_module' in deploy.rb

I have a module in in lib/redmine.rb that has some classes and stuff. I can call Redmine.some_method from the console just fine, but I'd like this module to be loaded during deployment using Capistrano.
I've tried:
require 'lib/redmine'
require 'redmine'
require './lib/redmine'
require '../lib/redmine'
load 'lib/redmine'
and all of those with a .rb at the end of it.
I can't seem to get access to the Redmine module from the deploy namespace...
The best way would be if you turn it into a gem project, and then simply refer to this
project via the name you gave it.
The problem I have with the code above is that I do not know the layout you use inside of redmine.rb and you are not showing the specific error.
Note that require() tries to go to the ruby SITE_DIR path first, so it would expect require 'redmine' to be installed like a gem (or, via setup.rb which was the old way before gem was written).
Try this too for ad-hoc solution (but don't use it in production code; you modify the load path and this is not good nor needed; use the gem project layout and installation, it is much easier and safer in the long run):
$: << '.'
require './redmine.rb'

Loading parts of a Rails 3 application

I am developing a gem for Rails 3 that consists of two main components. The first is a rails generator that adds some new files/folders to a rails project. The second is a runtime environment that loads all the aforementioned files (some ruby classes that use my DSL) as well as a portion of the default Rails stack. Essentially it's everything you'd expect to be able to access in rails c, sans routing, controllers, helpers and views. What is the proper way to load a Rails environment, except for specific portions?
Sidenote: I'd love to see any good articles regarding requiring Rails applications.
I am not entirely clear what you mean, or if this will help, but it sounds similar to something I do in a utility I wrote.
My utility loads the environment like so:
#!/usr/bin/env ruby
require File.expand_path('../../config/environment', __FILE__)
The require of the ../../config/boot will cause the gems defined in your Gemfile to load. So if you needed only part of the Rails stack then you would only require that part of the stack in your Gemfile.
This gives me my rails context, access to models and other resources.
(UPDATE)
To skip parts of the rails stack - take a look at how its been done to swap out ActiveRecord:
http://www.mongodb.org/display/DOCS/Rails+3+-+Getting+Started
Hope that helps.
Maybe you need Rails::Initializable?
You can do like that:
initializer "active_support.initialize_whiny_nils" do |app|
require 'active_support/whiny_nil' if app.config.whiny_nils
end

In Ruby on Rails, why do some gems require config/initializers/foo.rb and some gems don't?

For example, I think the gems such as haml doesn't need a file in config/initializers/, while devise needs a config/initializers/devise.rb.
Why do some gems not need an initializer file and some do? Can they all be made to be without one or all require one? What's the rule?
Some gems need more configuration than others, usually when the functionality is related to an account or needs to be manually configured to work with your specific rails apps (like hoptoad_notifier and devise), other gems provide or add in more general functionality in your rails apps, often these will work without any configuration but do have some flexibility and can be customized with an initialiser (like haml and will_paginate).

Resources