My Sinatra application was running fine on Dreamhost until a few days ago (I'm not sure precisely when it went bad). Now when I visit my app I get this error:
can't activate rack (~> 1.1, runtime) for ["sinatra-1.1.2"], already activated rack-1.2.1 for []
I have no idea how to fix this. I've tried updating all my gems, then touching the app/tmp/restart.txt file, but still no fix.
I hadn't touched any files of my app, nor my Dreamhost account. It just busted on its own (my guess is DH changed something on their server which caused the bust).
When I originally deployed my app, I had to go through some hoops to get it working, and I seem to think I was using gems in a custom location, but I can't remember exactly where or how. I don't know my way around Rack/Passenger very well.
Here's my config.ru: (mostly grafted from around the web, I don't fully understand it)
ENV['RACK_ENV'] = 'development' if ENV['RACK_ENV'].empty?
#### Make sure my own gem path is included first
ENV['GEM_HOME'] = "#{ENV['HOME']}/.gems"
ENV['GEM_PATH'] = "#{ENV['HOME']}/.gems:"
require 'rubygems'
Gem.clear_paths ## NB! key part
require 'sinatra'
set :env, :production
disable :run
require 'MY_APP_NAME.rb'
run Sinatra::Application
You could try 'pinning' your gem versions before they are required. If you have command line access to the server try this:
gem list
This should show you which gems are installed. But you do say you have some custom gem paths which may not work for this. Something is calling a 'require "rack"' with a different version to what your application is expecting. It may be Passenger, which means the best you can hope for is to upgrade to the latest version of Sinatra.
After Gem.clear_paths, you could try this:
gem 'rack', '~>1.1'
gem 'sinatra', '~>1.0' # NB use whatever gem list shows you as the version of sinatra you were using when you deployed your application.
It's the typical gem activation problem. Use Bundler to get around it.
Looks like you hit a non supportable Sinatra, Rack, Tilt version.
Take a look here how to solve that: http://codex.heroku.com/past/2010/12/14/sinatra_on_dreamhost/
Related
When I Bundle.require(:default) I'm getting an error saying that one of the gems in my test group isn't found. I installed this bundle --without test so this makes sense, but shouldn't all the gems in the :test group be ignored here? Isn't that the point?
Thoughts on what might be wrong with this environment?
EDIT:
It may have something to do with my setup for this projects. I'm caching the gems in vendor/cache with bundle package --all. My cache has gems from git, file, and traditional sources. Bundler is reporting
some gems appear to be missing from your vendor/cache -> could not
find gem factory_girl which is required by
try editing the gemfile so that it fg is like this:
group :development do
gem 'factory_girl'
end
Then it won't look for it in the testing group. Or, I can't tell which group you actually want it in, but my point is limit it down to the group you want.
Also, try running Bundler.require(:default, Rails.env) instead of just (:default). That would put it back to the standard Rails requirements.
Finally, I figure you're trying to install the gems for development(or production?) have you tried running bundle install --without test production to make sure that nothing is coming in from the other group you aren't focused on?
Edit:
Last try before I'm out of ideas. From the documentation it seems like you can specify the load path as well as requiring them. Try setting Bundler.setup as well? I don't have a rails environment on this machine so I can't test.
Bundle.setup(:production)
Bundle.require(:production)
or
Bundle.setup(:production, :default)
Bundle.require(:production, :default)
So I know that in a Gemfile I can do something like this:
group :development, :test do
gem 'gem1'
gem 'gem2'
end
What I am looking to accomplish is something like this:
group :production do
gem 'gem1'
gem 'gem2'
end
group :development, :test do
gem 'gem1', :path => '/Documents/Code/gem1/'
gem 'gem2', :path => '/Documents/Code/gem2/'
end
So our application uses 2 gems that we also develop locally. In order to improve time while developing on our local machines, we want to be able to point our dev environments to the local copies of the gems - this way it picks up all changes without needing to restart our rails server. Otherwise we would have to rebuild the gem, re-install the gem, and restart rails with every development change in the gem.
However, doing this gives me the following error:
You cannot specify the same gem twice coming from different sources. You specified that gem1 (>= 0) should come from an unspecfied source and source at /Documents/Code/gem1
I have tried even running something like bundle install --without production and I get the same error.
Does anyone know if it IS possible to do what I would like to do?
Thanks!
i think that there is a supported way to do it and some hacks to work around it.
supported way:
use bundle config with the local option as described here: http://bundler.io/v1.3/man/bundle-config.1.html
hacky way:
use env vars and execute bundler before using in production: http://www.cowboycoded.com/2010/08/10/using-2-sources-for-a-gem-in-different-environments-with-bundler/
there is a feature-request for this problem on github with several related issues and lots of comments: https://github.com/carlhuda/bundler/issues/396
the github issue phoet linked to is resolved, and is consistent with the supported way.
I dug around through the docs, you'll need to set the config variable and updated your gemfile to reference the branch as well.
e.g.
edit your Gemfile:
gem <gem_name>, git: <git_url>, branch: <branch>
on command line:
bundle config local.<gem_name> <local_path_to_gem>
I solved this by creating a new Gemfile that's identical to the original except for the target gem's source. Then, in config/boot.rb, I used:
require 'rails'
if Rails.env.development?
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../DevGemfile', __FILE__)
else
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../ProdGemfile', __FILE__)
end
We're using bundler, and on deploy server application is installed without some gems
bundler install --without test
In this case some code should be deactivated (like loading rspec && cucumber task into Rakefile)
Is there some simple methods like Bundler.installed?(:test) то detect this case?
What you are basically trying to do is distinguishing your production environment from your development (or test) environment. You should not rely on the installed gems for this, but Bundler groups can still be useful.
I would recommend using an environment variable, for example like in Rails. Then you could set this var in your server config with
$ export MYAPP_ENV='production'
and load it into your application with the default value :test:
MYAPP_ENV = ENV['MYAPP_ENV'].to_sym || :test
This way, you can always tell if you are on the production server. Suppose your Gemfile looks something like this:
source :rubygems
gem "sinatra"
group :test do
gem "rspec"
gem "faker"
end
You can then require only the relevant gems with
Bundler.require(MYAPP_ENV)
Back to your original question: Now it is very easy to check if you are on your production machine or not, by simply using MYAPP_ENV again:
if MYAPP_ENV == :test
# do some test specific stuff
end
I hope this helps.
I am trying to use the instructions here to install a pre-released version of a gem with bundler.
The "bundle install" output lists the gem as getting installed, but "gem list" fails to find it.
My Gemfile:
source :gemcutter
gem 'sinatra', '1.1.0', :git => 'http://github.com/sinatra/sinatra.git'
gem 'RedCloth', '4.2.3'
Here is a gist with the rest of my sample code.
Has anyone gotten this scenario to work?
NOTE: I am also using RVM (on OS X). bundle show does list the gem (and dependencies) as existing, but I am not able to properly resolve them.
Thanks.
I would look at the load paths, and further debug from there, example:
...(master) $ irb
irb(main):001:0> $LOAD_PATH.count
=> 8
irb(main):004:0> require 'bundler/setup'
=> true
irb(main):005:0> $LOAD_PATH.count
=> 112
irb(main):006:0>
Bundler configures the load path for you, this means not all the gems are included on your load path by default.
Additionally, from the bundler git help:
Because Rubygems lacks the ability to handle gems from git, any gems installed from a git repository will not show up in gem list. They will, however, be available after running Bundler.setup.
Best regards, hope this helps
ED
Bundler might have installed it locally to your app. This could vary wildly, depending on OS and whether you are using RVM.
What is the output of bundle show sinatra?
In my case, sinatra was installed here:
/home/marshall/.rvm/gems/ruby-1.8.7-p302#3846859/bundler/gems/sinatra-9cfa74a7f352
Sinatra doesn't show in the gems list, but the server launches correctly if I execute rackup.
Gems installed via bundler on Engine Yard go to a different folder to isolate them.
it's usually /data/APP_NAME/shared/bundled_gems
To be sure, check your .bundle/config file on your APP folder at Engine Yard
It looks like there is an issue using Shotgun and Bundler (git repositories only).
If I use rackup to start up my app, all is well. I am going to investigate a little more and then file a bug with one (or both) of the projects.
I am using
# my_app.rb
load 'index.rb'
and start the sever like this
ruby my_app.rb
but it never reload any changes I made in index page.
Did I miss anything here?
See the Sinatra FAQ,
"How do I make my Sinatra app reload on changes?"
First off, in-process code reloading in Ruby is hard and having a
solution that works for every scenario is technically impossible.
Which is why we recommend you to do out-of-process reloading.
First you need to install rerun if you haven’t already:
$ gem install rerun
Now if you start your Sinatra app like this:
$ ruby app.rb
All you have to do for reloading is instead do this:
$ rerun 'ruby app.rb'
If you are for instance using rackup, instead do
the following:
$ rerun 'rackup'
You get the idea.
If you still want in-process reloading, check out Sinatra::Reloader.
gem install sinatra-reloader
require 'sinatra'
require 'sinatra/reloader'
Note: it will reload only sinatra handlers (and, maybe some sinatra server configuration commands), but not custom files, which you have to reload manually.
UPD after 9 years: seems like it is already possible to reload other files using also_reload, dont_reload and after_reload -- https://github.com/sinatra/sinatra/pull/1150
You can use the rerun gem.
gem install rerun
rerun 'ruby app.rb'
OR if you are using rackup
rerun 'rackup'
gem install sinatra-reloader
require 'sinatra/base'
require "sinatra/reloader"
class MyApp < Sinatra::Base
register Sinatra::Reloader
get '/' do
"Hello Testing1!"
end
end
You may want to set environment variable to development and conditionally load the gem.
When you run the application with Passenger Standalone, just create a tmp/always_restart file:
$ touch tmp/always_restart.txt
See Passenger documentation for more info.
I like the Shotgun gem. If you're using a modular Sinatra app and have a config.ru file it's easy to run.
shotgun config.ru
Check the gem out here. It's fairly straight forward and no configuration needed.
On Windows, I am using my restart gem for this:
restart ruby my_app.rb
or, with rackup:
restart rackup
See here for more info, hope you find it useful.
You could use guard-rack. Lifted from an article at dblock.org:
Add this to your Gemfile:
group :development do
gem "guard"
gem "guard-bundler"
gem "guard-rack"
end
Then, create a Guardfile at the root of your project with this content:
guard 'bundler' do
watch('Gemfile')
end
guard 'rack' do
watch('Gemfile.lock')
watch(%r{^(config|app|api)/.*})
end
Lastly, run Guard, like so: bundle exec guard, and rackup will reload every time.
If you only change your templates sinatra will always rerender them if you set your environment to development:
ruby app.rb -e development