Proper way to use a Rack middleware from a gem in a Rails project with Bundler - ruby-on-rails

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

Related

Random "Uninitialized Constant" errors in staging/production

Like many Rails applications, we have a few classes we define in the lib/ folder. We make sure to let Rails know about them in the config/application.rb file like so
config.autoload_paths += Dir[Rails.root.join('lib'), Rails.root.join('lib', '**')]
And that has worked perfectly up until now with no problems. However recently we have been getting random occurrences of "Uninitialied Constant" errors in staging/production. Most of the times things work fine, it's just every once in a while that things break down. Opening a Rails console and the classes are always there.
I tried to better understand how Rails does the autoloading magic, so I read this great article: http://urbanautomaton.com/blog/2013/08/27/rails-autoloading-hell/, but nothing in it helped me.
I also tried a few things that I thought might work, like requiring all the files individually in an initializer, but nothing worked.
I'm using Ruby 2.1.1, Rails 3.2.19, Phusion Passenger 4.x. Anything else that might help? How might Constants become undefined or inaccessible from somewhere? Maybe a gem is messing with the way Rails modifies constant lookup...
Update: I have not enabled threadsafe mode

After installing paper_trail, get "irb: warn: can't alias context from irb_context." from rails console

I've tested this by running rails c both before and after git stash. On Rails 4.1 in Mavericks, after following the instructions to add the versions table and adding has_paper_trail to three models, whenever I run rails c I get
irb: warn: can't alias context from irb_context.
I've spent some time Googling without much luck, there's old threads talking about rspec, but I don't see how that's relevant since I'm not using it. Any ideas why this is happening?
RSpec used to polute provide Object top-level methods, e.g. describe, context, etc. Fortunately they've got rid of all the monkey patching in version 3, and now all these methods are namespaced under RSpec.
One can change this behaviour through the expose_dsl_globally config flag. For backwards compatibility, it defaults to true.
The warning shows up when you open the console because paper_trail automatically loads its rspec helpers when rspec is found. And it calls RSpec.configure before you have the chance to tweak your own configuration.
One possible solution would be paper_trail to disable the automatically loading and let users to load it themselves when they see fit. However, I am not aware of the internals of the library, so I can't guarantee this wouldn't break other things.
Best!
This is now fixed in papertrail 4.0.0, here's the commit.

How to modify Rails middleware to serve gzip assets from Heroku?

My question is closely related to "any way to serve gzip assests from Heroku"
The best approach points to a Gist: https://gist.github.com/2152663
So, how do I make it work? It seems obvious for the person who asked, but I'm having a hard time putting it together.
I understand I have to place compressed_static_assets.rb into /lib and then reference it from my production.rb, but I keep getting the error: "uninitialized constant Middleware (NameError)"
This might be an older question but did you try the heroku-deflater gem? Looks like it does the same thing but is easier to get up and running.

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.

how does a middleware get deleted?

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.

Resources