Issue finding controller concerns only in production - ruby-on-rails

My application has a number of controller concerns in app/controllers/api/V2/concerns
When I work on this in development, everything works well. However, as soon as I push to production, I get the following error when the rails server boots up: Uninitialized constant Concerns::MyConcern (NameError)
My concerns look like this:
module Api::V2
module Concerns
module MyConcern
extend ActiveSupport::Concern
def some_method(some_arg)
# some stuff here
end
end
end
end
I have set up config.eager_load = true in both my production and development environments to try and make them as consistent as possible; however, still not seeing this error occur in production.
What's strange is if I comment out the areas where I include the concerns in the controllers, the application manages to boot up; then, when I go to rails console on the production server and see if I can access Api::V2::Concerns::MyConcern I am able to access it without error. This makes me think that there's some sort of autoloading issue going on where the concerns aren't loaded when they are called in the controllers; however, I was under the impression that Rails loaded up everything in the app/ folder automatically and only areas such as the /lib had to be explicitly added.
As an FYI, my controller sits in app/controllers/api/V2/my_controller.rb
Any ideas what could be happening here?

It's highly probable that the V2 component in your path is causing the issue here. On a case insensitive file system this will be resolved as v2 which works. On a case sensitive file system it will be looking for app/controllers/api/v2/concerns/my_concern.rb which doesn't exist, and won't load.

Related

Rails controller handling discrepancy development/production

Summary: in development, requests are routed to workouts_controller.rb but in production to workouts_controllerPrev.rb
In a Rails 5.2.3 app, I have the file workouts_controller.rb in the controllers/ folder with first line:
WorkoutsController < ApplicationController
I took a copy of workouts_controller.rb (to serve as a quick reference backup) which I renamed to workouts_controllerPrev.rb and retained in the controllers/ folder.
I then introduced some new functionality to workouts_controller.rb. I tested the new functionality locally (it worked as expected in development) and then I deployed to Heroku (v 7.42.0) (for production).
The new functionality, however didn’t work in production. After some debugging, I identified that in production, the WorkoutsController class in workouts_controllerPrev.rb was handling calls to the Workouts controller (rather than the Workouts controller defined in workouts_controller.rb (as anticipated and as happening in development).
I made a more dramatic name change to workouts_controllerPrev.rb, changing it to Xwurkouts_controllerPrev.rb, and changed the class name in this file to XWurkoutsController redeployed and it all worked fine.
What is happening here? Why would Rails function differently in this respect between the 2 environments? Is this a bug or an unsurprising consequence of a bad practice of having unused files loitering around? If a bug, where should I report it?
I am using SQLite in development, and PostGreSQL in production, but I don’t see this can be a database issue? The production webserver is Puma.
Thanks for any guidance
Daniel
The issue is that both files have the same class name in them, so the actions (methods) in whichever one is loaded last will override the actions defined in the one loaded first.
If you want to keep both files around and not have surprising results, change the class name in the old file to something else like PrevWorkoutsController.
Or, save it in a branch in Git so it doesn't clutter your current code.
To answer about why you got different results in different environments, it is because of the difference between autoloading vs. eager loading. Rails uses autoloading in development, but it eager loads everything up front in production, then turns autoloading off.
In other words, in development, Rails will reload the class from its matching file any time that file is saved. In production, it simply loads all files up front, so whichever one it loads last will win.
You can read more here.

Rails engine creates circular dependency fault

I have an app with a rails engine i use. I've stripped them down pretty much to the bone, but i get a fault when I start the engine up with multi-threading enabled. I faults out with missing constant the model name i'm calling from the controller. I've reduced it down to just calling the Model.all.pluck(:id). And still get the fault. The models are being invoked via an Ajax call to the controller.
The app runs correctly if i refresh the page and continue, never faulting out again, that I can see.
I think it's actually a multi-treading issue, I'm using Rails 4.1, Ruby 2.12 and Puma 2.8.2 and postgress.
This is happening on my development system a macbook. I will don't see it in the heroku logs when I deploy, but ??
Now somewhat curious. I've made the issue go away, by forcing the app to load each model in the engine, one at a time. Things seem to run smoothly after that.
Any suggestions on how to dubug this
This is directly linked to config.eager_load settings of your app. In production it is set to true so you do not have the circular dependency problem, in development it is generally set to false and that's where rails auto loading systems may trigger this kind of error.
I do believe (though I'm not certain) that you can solve this by not declaring nested classes and modules in one single line
Instead of
class MyModule::MyClass
...
end
Use
module MyModule
class MyClass
...
end
end

confusing about autoload_paths vs eager_load_paths in rails 4

I read a post about the rails load_paths, here is the link.
But, I am still confused about the difference between the autoload_paths and eager_load_paths:
I have tested them in a newly created Rails 4 project. It seems that they run the same way, that auto-reload in the development mode but in the production mode.
Author of the linked article here. Here's an attempt to clear up the confusion, going off of #fkreusch's answer.
In Ruby you have to require every .rb file in order to have its code run. However, notice how in Rails you never specifically require any of your models, controllers, or other files in the app/ dir. Why is that? That's because in Rails app/* is in autoload_paths. This means that when you run your rails app in development (for example via rails console) — none of the models and controllers are actually required by ruby yet. Rails uses special magical feature of ruby to actually wait until the code mentions a constant, say Book, and only then it would run require 'book' which it finds in one of the autoload_paths. This gives you faster console and server startup in development, because nothing gets required when you start it, only when code actually needs it.
Now, this behavior is good for local development, but what about production? Imagine that in production your server does the same type of magical constant loading (autoloading). It's not the end of the world really, you start your server in production, and people start browsing your pages slightly slower, because some of the files will need to be autoloaded. Yes, it's slower for those few initial requests, while the server "warms up", but it's not that bad. Except, that's not the end of the story.
If you are running on ruby 1.9.x (if I recall correctly), then auto-requiring files like that is not thread safe. So if you are using a server like puma, you will run into problems. Even if you aren't using a multi-threaded server, you are still probably better off having your whole application get required "proactively", on startup. This means that in production, you want every model, every controller, etc all fully required as you start your app, and you don't mind the longer startup time. This is called eager loading. All ruby files get eagerly loaded, get it? But how can you do that, if your rails app doesn't have a single require statement? That's where eager_load_paths come in. Whatever you put in them, all the files in all the directories underneath those paths will be required at startup in production. Hope this clears it up.
It's important to note that eager_load_paths are not active in development environment, so whatever you put in them will not be eagerly required immediately in development, only in production.
It's also important to note that just putting something into autoload_paths will not make it eager-loaded in production. Unfortunately. You have to explicitly put it into eager_load_paths as well.
Another interesting quirk is that in every rails app, all directories under app/ are automatically in both autoload_paths and eager_load_paths, meaning that adding a directory there requires no further actions.
Basically, autoload_paths are paths Rails will use to try loading your classes automatically. E.g. when you call Book, if that class isn't loaded yet, it will go through the autoload_paths and look for it in those paths.
In production, it might be better to load those upfront to avoid autoload concurrent issues. For that, it provides the eager_load_paths. Paths in that list will be required upfront when your application starts.

Ruby and/or Rails caching require()'ed scripts?

I'm testing out a basic Rails app and I seem to be getting some undesirable caching behavior on a library script that's being require()'ed into my controller script.
Suppose FooController.rb contains the following:
require 'utils' # a library script
class FooController
def some_action
#some_member = do_something() # global method defined in utils.rb
end
end
It appears that changes to utils.rb do not take effect until I restart the Rails server. I don't believe this is due to a misconfiguration of Rails' class caching, since a) I am running in a "development" environment, and b) I can make changes directly to the controller code (e.g., to the some_action method above) that are reflected upon the next execution of the script. I've been testing this with some calls to puts that spam messages into the console.
Is there some behavior in either Ruby or Rails that would cause require()-ed scripts to remain cached? If so, is there a way to configure that behavior?
Rails class reloader is relatively naive. I believe it's only intended to reload things like controllers and models, leaving anything you might be require'ing into your project alone. So, if you have some custom code in the lib directory or elsewhere that you have changed it is expected behavior for you to have to restart the Rails server.
If you want to require each time the code is encountered, you really want load.
http://www.ruby-doc.org/core/Kernel.html#method-i-load

Using nested controllers

Since my site had an admin section and a normal (front-end user) section, I needed to structure the articles controller in such a way that it was RESTful.
So what I did was , have 2 articles controllers, 1 nested under the admin namespace (which would result in admin/articles) and the other one as a normal articles resource (/articles).
(I followed this blog.)
Now I started facing issues such as
A copy of AuditObserver has been removed from the module tree but is still active!
2 questions .
Is this error really because of me using such a structure of nested resources?
Is it a good programming practice to use such a structure? If not, is there a better alternative?
Thanks!
The structure is perfectly fine, and your code will probably function just fine in production mode. The issue usually arises in development when modules or classes are not 'unloaded' after a first request. Without seeing the code it's hard to tell exactly which module or plugin might be causing this issue, but you might want to have a look at this blog post.
You can usually solve this issue by loading the offending module or class only once:
config.autoload_once_paths << '/path/to/class/or/module.rb'
or by reloading your plugins in development mode:
config.reload_plugins = true if Rails.env == 'development'

Resources