how does a middleware get deleted? - ruby-on-rails

rack-timeout is included in the Gemfile, but we only want it as middleware on production. Thus in an initializer, we have:
config.middleware.delete Rack::Timeout
Inspecting before and after this line shows rack-timeout removed from the array. Regardless, requests are still timing out, and a quick 'puts' in the gem shows that it is indeed the culprit.
Is this because the middleware stack has already been built before delete is called? Or is the stack read in every request? If that's the case, what could be the issue?

Why not just have something like the following?
group :production do
gem "rack-timeout"
end
In theory, the middleware deletion in the initializer should take care of the problem after a server restart, assuming you're talking about putting something in config/initializers/.
Did a little more experimentation and dropped this into config/initializers/rack-timeout.rb:
if Rails.env.production?
Rack::Timeout.timeout = 0.5
else
Rails.configuration.middleware.delete Rack::Timeout
end
And this in a scaffolded controller:
sleep 1
Everything seemed cool after I restarted the dev server (no timeouts in sight :D). So, maybe just a bad variable.
I still think using a production-only group is the better solution.
Ran with Rails 3.2.2 with ruby 1.9.2-p290 on OSX.

Related

Rackup LoadError - any config.ru file gives LoadError when rackup command used

Ok, so this is my first ever question. I'm bracing for feeling dumb, but here goes.
I'm currently learning Ruby before I become familiar with Ruby on Rails. I've been following an online course, and at this juncture we've just learned how to use rack to handle some of the logic for a server, and running a config.ru file to start the server.
But, every time I try to start the server using rackup, I get a LoadError like this:
1: from /usr/local/bin/rackup:23:in `<main>'
/usr/local/bin/rackup:23:in `load': cannot load such file -- /usr/lib/ruby/gems/2.5.0/gems/rack-2.0.7/bin/rackup (LoadError)```
Now, I've been slamming my head against every possible angle I can think of. I understand this error to be saying that path - from which the rackup command is trying to load the rack code - doesn't exist. I've tried making multiple different .ru files to test if its a problem with the shebang, a problem with the content of the .ru file, and so on. But that doesn't seem to be the case. I can't even run the example lobster.ru file that comes with the rack gem. I get the same error.
I also tried reinstalling the rack gem, changing the default version of it. Neither helped. I considered using different versions of Ruby, but that didn't seem like it was relevant. The problem is clearly that rackup is looking in the wrong place.
But, if I use require 'rack' on a simple ruby server, there aren't any problems. Rack works. So all of this told me that it must be something to do with the rackup command itself.
Indeed, when I go to /usr/lib/ruby/gems/2.5.0/gems there is no rack-2.0.7 directory. Instead, that directory is in var/lib/gems/2.5.0/gems
I've noticed that var/lib/gems/2.5.0 is in the GEM PATHS of the RubyGems Environment. But /usr/lib/ruby/gems/2.5.0' is not.
So my ideas on solving the issue were:
Change the way that rackup loads the rack gem. I looked into this and it would mean changing what looks like seriously proper code in the rubygems or even rackup files. I will break it if I tamper with it because I have no clue what I'm doing. This is not a sensible option.
Add the usr/lib... to the GEM PATH, so that when rackup and rubygems looks for the rack gem it can find it. Having searched a bit about this possibility, it seems like manually adding things to the GEM PATH is not recommended. I tried it anyway...but it didn't work (FYI, I added to the GEM PATH by adding export GEM_PATH=... to the .bashrc
EDIT: Having slept on it, I can see why the second option above doesn't work either. Simply adding the missing directory to the GEM PATH or to the $LOAD_PATH won't help because rackup is looking in a specific place for rack but can't find it. If I look at the rackup code, it looks like this:
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('rack', 'rackup', version)
else
gem "rack", version
load Gem.bin_path("rack", "rackup", version)
end
The segments of code doing the looking are directed by :activate_bin_path and bin_path, which are both defined in the rubygems code.
So if I understand this correctly, its like rackup is getting the wrong directions to a place that doesn't exist. Like it's turning right when it should go left. My options are either to somehow change its directions to tell it 'go left' or to build the thing its looking for 'on the right'.
Making sure it 'goes left' is the better solution but I can't figure out how to do that. So I built what its looking for 'on the right': I copied the rack gem to the /usr/lib/ruby/gems/2.5.0/gems/ directory that rackup is looking in. It has solved the problem of rackup not finding what it is looking for - rackup now works and the server works. BUT this solution is going to haunt me in the future, e.g. if rack is updated... It's a barbarian solution, and I'd prefer an elegant one.
So if anyone has insight into how to make sure rackup gets the proper directions, please let me know! I think it must have something to do with making sure the rubygems bin_path and :activate_bin_path correspond with where the gems are actually installed. At the moment the fundamental discrepancy seems to be that the gems live in var but its looking in usr.
Thanks in advance!
Try this file:
config.ru
app = ->(env){
status = 200
headers = {"content-type" => "text/html"}
body = ["<Html><Body><H1>Hello, World!</H1></Body></Html>"]
[status, headers, body]
}
run app
rackup config.ru

How to get rid of postgresql but still use ActiveRecord::RecordNotFound on heroku when using mongohq?

Edit:
How to use ActiveRecord::RecordNotFound exception to make Rails respond with the standard 404? The basic approach suggested in many places is to modify the config/application.rb to not require "rails/all", but instead check out the file: railties/lib/rails/all.rb and pick and choose what you want/need. However, if you just leave out the part a about active_record, then you can't use ActiveRecord::RecordNotFound (and apparently using fixtures might have problems too, I wouldn't know as I don't use them). How to solve this problem?
The old explanation of the problem is not very relevant but, I'm leaving it here for reference and context for the comments below..
Old explanation:
So here's the deal. We have a Rails app that uses MongoHQ as it's database. Locally thing's run smoothly without any problems, but on production and staging environments it seems that Heroku insists that we must have postgresql database and gems setup/installed. I've tried to delete the addons and related config variables, but it just wont do. This is rather annoying as now the free postgresql causes problems because if we crank up the dynos it will very quickly run out of connections (20 connection limit). However, upgrading to a more production level tier of postgresql seems like a very silly thing to do when the database has 0 tables. How are everyone else using MongoHQ managing this? I can't seem to be able to find any anything about it though I would have thought it to be an apparent issue that everyone using MongoHQ and Heroku would face?
The key idea is that we can still require "activer_record", but lets just leave out the corresponding railtie. This is what I ended up putting into my config/application.rb
require "rails"
frameworks = %w(action_controller action_mailer active_resource rails/test_unit)
frameworks.each { |framework| require "#{framework}/railtie" }
# For errors like ActiveRecord::RecordNotFound
require "active_record"
Credits for the idea goes to mr. Benjamin Oakes:
http://www.benjaminoakes.com/2011/09/15/activerecordconnectionnotestablished-in-rails-3-1-on-heroku/

Proper way to use a Rack middleware from a gem in a Rails project with Bundler

I've got a Rails project that's setup using Bundler. One of my bundled gems provides a Rack middleware that I'd like to use in my Rails app (but only in the 'production' Rails environment).
If I just put something like this in config/environments/production.rb, I get an unknown constant error:
config.middleware.use ::Rack::MyMiddleware
... presumably because Bundler.require has not yet been called at this point, and none of my bundled gems are available.
I have found a few ways of working around this, but none seem great, and I'm wondering if there's a more standard solution that I'm missing:
Explicitly require 'my_middleware_gem' in config/environments/production.rb
Wrap the config.middleware.use call in an after_initialize block, ensuring that Bundler has a chance to do its thing before I try to reference the constant.
Use a string ("::Rack::MyMiddleware") instead of the bare class constant. This doesn't seem to work with Unicorn for some reason, but does work with some other servers (with Unicorn it ends up trying to call "::Rack::MyMiddleware".new, which of course fails).
Am I missing some better approach? At what point in the initialization process is it expected that bundled gems should be available?
Copying the answer from the comments in order to remove this question from the "Unanswered" filter:
matt suggested:
I think using the after_initialize block is the right way in this case.
grumbler confirmed:
Yeah, that's what I ended up going with. Thanks! Regarding the unicorn issue alluded to in the original question, turns out I was hitting this problem: http://davidvollbracht.com/blog/headachenewunicorn-capistrano-bundler-usr2

Rails 3 Locale switches when using different server

I've got a Rails 3.2.3 app with the default_locale set to :nl. When I start the app using Thin or Unicorn, the app's locale is set to :en. When I use Webrick, the locale is correctly set to :nl.
This change is triggered by a commit that updates several third-party gems, although I have not been able to single out any one gem upgrade in particular -- I can reverse each of them individually and get the same result. However, when I checkout the offending commit's parent, all is well too.
When I run the app on a remote server in production mode, it all works fine, so it seems to be local to my machine.
I have removed every single installed gem and re-installed them all, which made no difference.
Does anyone have any idea what might trigger this behaviour? And especially why using webrick or unicorn would make a difference?
Edit: I have pinpointed the bug to be triggered by upgrading Draper from 0.11 to 0.12 (issue at Github). Not sure if it is also the cause.
http://labs.revelationglobal.com/2009/11/13/unicorn_and_i18n.html
This problem has occured to me before wich was triggered by the "active_admin" gem you might want to use an earlier version to prevent this, I do not really know wich one so you can play around with it a little.
another option would be to set the active_admin locale in a before_filter,
config.before_filter :set_admin_locale
And set_admin_locale is in the application_controller:
def set_admin_locale
I18n.locale = :nl
end
hope it helped
I managed to track this problem down to a bad practice in my own Rails app that caused a bug by upgrading the Draper gem. There's a full explanation in the Draper documentation.

A copy of [middleware] has been removed from the module tree but is still active! - error

We use rails version 2.3.5
This error has been reported in SO here
I tried the following:
adding config.cache_class = true - the problem with this was that, the server had to be restarted every time a change was made to any controller. Also the server start time was too long
adding unloadable to the middleware - no use
adding config.middleware.use [middleware] to development.rb - no use
Is there a way to overcome this other than making development similar to production?
Edit
even tried adding config.middleware.use [middleware] to environment.rb. Well this behaved totally different. My error disappeared, but my middleware cracked. All it's objects were nil..!
maybe you need to make a plugin reloadable?
refs: http://blog.yves-vogl.me/2010/01/12/automatically-reload-rails-plugins/
Rails auto-reloading plug in development mode
et al
Found the answer.
adding config.middleware.use [middleware] to environment.rb
this was not working previously for me because i was initializing this middle ware inside session_store too. So the same middle ware was executed twice with the second time all params with nil - Hence the nil problem.
Thank you rogerdpack for trying to help.!

Resources