Is this the right way to require ruby gems? - ruby

Hi so i stumbled upon a new way to require my ruby gems in my sinatra app using bundler and i was wondering if this is how i should do it:
My gem file looks like:
source 'https://rubygems.org'
gem 'sinatra'
gem 'thin'
gem 'haml'
My config.ru file looks like:
require 'rubygems'
require 'bundler'
Bundler.require
require './web'
run Sinatra::Application
My web.rb file looks like:
class MyApp
before do
cache_control :public, :max_age => 60
end
not_found do
haml :not_found
end
get '/' do
haml :index
end
end

Get rid of these lines from your config.ru file:
require 'rubygems'
require 'bundler'
Bundler.require
Just make sure you run
bundle install
from the terminal to install your gems before starting the application.

Related

Can't get request when config routes.rb file with Sinatra

My app structure like this
Gemfile
app.rb
config.ru
lib/routes.rb
# app.rb
require 'sinatra'
class Todo < Sinatra::Base
set :environment, ENV['RACK_ENV']
Dir[File.join(File.dirname(__FILE__), 'lib', '*.rb')].each {|lib| load lib}
end
#config.ru
require 'sinatra'
require 'bundler/setup'
Bundler.require
ENV['RACK_ENV'] = 'development'
require File.join(File.dirname(__FILE__), 'app.rb')
Todo.start!
#lib/routes.rb
get '/' do
"Hello world"
end
When I run with ruby config.rb then locate to localhost:4567, it doesn't recognize the route /. But if I move the code get '/' do into class Todo it works.
Anyone can explain that for me?
If you have a config.ru file, that means that the application has to be invoked by the rackup utility and not ruby config.ru. The reason for this is that rackup sets a lot of settings before invoking the code inside config.ru. Rackup utility is part of Rack gem that Sinatra builds on, so it will be present if you install Sinatra.
Although not a problem for the example you provided, in a modular style application, you need to require sinatra/base rather than just sinatra.

Why is bundler loading all my gems instead of specific ones

I have a Sinatra application and I'm trying to use groups in my Gemfile in order to load only specified gems. But, when I restrict loading to just one group bundler still loads every gem in the file. Here's my Gemfile:
source 'https://rubygems.org'
group :one do
gem 'sinatra'
end
group :two do
gem 'bitly'
end
And here's my application:
require 'bundler/setup'
Bundler.require(:one)
class App < Sinatra::Base
configure do
puts Gem.loaded_specs.keys.sort.join("\t")
end
get '/foo' do
end
end
And I can clearly see the Bitly gem loaded when the application starts. What am I doing wrong?
Use
require 'bundler'
instead of
require 'bundler/setup'
The last one automatically loads all gems in Gemfile: Why do you need "require 'bundler/setup'"?

rubygems doesn't install on push in openshift

I'm trying to deploy an app in Openshift that requires some gems, how do I get Openshift to install those when I push via git?
Here's what my config.ru file currently looks like:
require 'rubygems'
require './app.rb'
run Sinatra::Application
And as for app.rb it requires the following gems:
require 'sinatra'
require 'redcarpet'
require 'stringex'
require 'data_uri'
Any ideas what I'm doing wrong here? Thanks in advance!
You probabily need to add those into a Gemfile like:
# Gemfile
source 'http://rubygems.org'
gem 'sinatra'
gem 'redcarpet'
gem 'stringex'
gem 'data_uri'
and run bundle locally before pushing to generate the Gemfile.lock
Use Bundler for you app
in Gemfile
gem 'sinatra'
gem 'redcarpet'
gem 'stringex'
gem 'data_uri'
in config.ru
require 'rubygems'
require 'bundler'
Bundler.require
require './my_app'
run Sinatra::Application
Start server with rackup, and Sinatra will be loaded via Bundler.
$ rackup

Sinatra + Bundler?

I'm wondering how one can use Bundler with Sinatra. The idea is to use the gems that Bundler downloads inside the .gems folder.
Inside your Sinatra app, you just have to require the bundler setup:
require "bundler/setup"
require "sinatra"
get "/" do
"Hello world!"
end
Alternatively, if you don't want to add the additional require "bundler/setup" at the top of your app, you can instead invoke sinatra via bundle exec (e.g. bundle exec ruby myapp.rb)
This assumes that you have a Gemfile in the root of your application. It might look like this:
source "http://rubygems.org"
gem "sinatra"
This also assumes that you've already installed bundler (gem install bundler) and that you ran bundle install to install all the gem dependencies.
I believe the best way is described here on EngineYard blog:
# This makes sure the bundled gems are in our $LOAD_PATH
require File.expand_path(File.join(File.dirname(__FILE__), 'vendor', 'gems', 'environment'))
# This actually requires the bundled gems
Bundler.require_env
class MyApp < Sinatra::Base
# stuff
end
As my original answer was quite old but there seems to be still attention to this topic here's the latest version of bundler/sinatra setup which will cover most of the use case:
A minimal config.ru
require './my_sinatra_app'
run MySinatraApp
An environment env.rb file that requires all the bundled gems (also supports loading the current environment's group):
require 'bundler/setup'
APP_ENV = ENV["RACK_ENV"] || "development"
Bundler.require :default, APP_ENV.to_sym
Then your app file (requiring the environment) with your sinatra app (Sinatra::Base):
require_relative 'env'
class MyApp < Sinatra::Base
get "/" do
"hello world"
end
end
Start your development server with rackup, and Sinatra will be loaded via Bundler, your app will be accessible from http://localhost:9292.
$ rackup
or bundle exec rackup if needed
Make sure you have a Gemfile like the following one and you run the bundle command before starting the app
source "https://rubygems.org"
gem "sinatra"
gem "puma" # a better rack server than the default webrick
+1 for the guide on the bundler website, but if you have a simple app and use Sinatra's dsl at the top level, then you need to do the following:
in your Gemfile (tell bundler not require sinatra):
gem 'sinatra', :require => false
and in the app's file (explicitly require sinatra):
require 'rubygems'
require 'bundler'
Bundler.require
require 'sinatra'
get '/' do
'hello world'
end
To use bundler with a Sinatra application, you only need to do two things. First, create a Gemfile.
gem 'sinatra'
Then, set up your config.ru file to load the bundle before it loads your Sinatra app.
require 'rubygems'
require 'bundler'
Bundler.require
require './my_sinatra_app'
run MySinatraApp
Start your development server with rackup, and Sinatra will be loaded via Bundler.
rackup
source bundler docs

Deploying Sinatra app on Dreamhost/Passenger with custom gems

I've got a Sinatra app that I'm trying to run on Dreamhost that makes use of pony to send email. In order to get the application up and running at the very beginning (before adding pony), I had to gem unpack rack and gem unpack sinatra into the vendor/ directory, so this was my config.ru:
require 'vendor/rack/lib/rack'
require 'vendor/sinatra/lib/sinatra'
set :run, false
set :environment, :production
set :views, "views"
require 'public/myapp.rb'
run Sinatra::Application
I have already done gem install pony and gem unpack pony (into vendor/). Afterwards, I tried adding require 'vendor/sinatra/lib/pony' to config.ru only to have Passenger complain about pony's dependencies (mime-types, tmail) not being found either!
There has to be a better way to use other gems and tone down those long, ugly, redundant requires. Any thoughts?
I'd recommend creating your own gem path "somewhere" then adding it in your config.ru
like:
ENV['GEM_PATH'] = xxx
Gem.clear_paths
then install your gems into that
Install Ruby gems on dreamhost
https://c.kat.pe/installing-ruby-gems-on-dreamhost
Change config.ru (works for Sinatra 1.0)
require 'rubygems'
require 'vendor/sinatra/lib/sinatra.rb'
ENV['GEM_HOME'] = '/home/username/.gems'
ENV['GEM_PATH'] = '$GEM_HOME:/usr/lib/ruby/gems/1.8'
require 'rubygems'
Gem.clear_paths
disable :run, :reload
set :environment, :production
require 'yourapp'
run Sinatra::Application
Hope it helps someone.
I am using pony and a lot of other gems for my Sinatra. It should work well for you too. It's just those two lines (GEM_HOME and GEM_PATH) you have to add on your config.
It took me ages to find that you can simply use "gem install sinatra" and gem will figure out (because the system directories are read-only) that you will need to use a local gem install directory. As of now, there seems to be no need to set any special environment at all. It figures out to use $HOME/.gem as the local gem path and everything just works. No need for require 'vendor/stuff' at all. I did find I had to add $HOME/.gem/ruby/1.8/bin to my path in order to execute binaries installed by gems.
Here's my config.ru (for Dreamhost)
## Passenger should set RACK_ENV for Sinatra
require 'test'
set :environment, :development
run Sinatra::Application
Later edit: This is all well and fine, but there remains the issue that Passenger can't find my gems when the job initially starts up.
My config.ru is just simple as:
require 'rubygems'
require 'vendor/sinatra/lib/sinatra.rb'
require 'app.rb'
and app.rb head:
require 'yaml'
require 'haml'
require 'ostruct'
require 'date'
require 'pp'
module FlytoFB
log = File.new("sinatra.log", "a")
STDOUT.reopen(log)
STDERR.reopen(log)
configure do
enable :logging, :dump_errors
set :app_file, __FILE__
set :reload, true
set :root, File.dirname(__FILE__)
set :environment, :production
set :env, :production
set :run, false
set :raise_errors, true
set :public, 'public'
error do
e = request.env['sinatra.error']
puts e.to_s
puts e.backtrace.join("\n")
"Application Error!"
end
not_found do
"Page not found!"
end

Resources