Micah
Micah

Reputation: 33

Sinatra not understanding settings in config.ru?

I'm trying to write a config.ru file for Sinatra where I have one set of database credentials for each environment: development and production. I'm doing the following:

app.rb:

require 'sinatra'
require 'data_mapper'
require 'dm-mysql-adapter'

DataMapper.setup(:default, "mysql://#{settings.db_user}:#{settings.db_password}@#{settings.db_host}/#{settings.db_name}")

# ... the rest of the app

config.ru:

require 'sinatra'
require './app.rb' # the app itself

configure :development do
  set :db_name, 'thedatabase'
  set :db_user, 'root'
  set :db_password, ''
  set :db_server, 'localhost'
end

run Sinatra::Application

But when I attempt to start the app using ruby app.rb, I get "undefined method 'db_user' for Sinatra::Application:Class (NoMethodError)".

Generally, I'm just trying to offload all these settings into their own file. If config.ru isn't the place for them, what would be an appropriate way to do this?

Upvotes: 2

Views: 2793

Answers (3)

Bruno Melli
Bruno Melli

Reputation: 11

config.ru is only going to be used if you start your app with rakeup. If you start your app with 'ruby app.rb', config.ru is not going to come into play.

Upvotes: 0

Pablo Jomer
Pablo Jomer

Reputation: 10378

I agree with Thomas. This has been confusing for me at times too, thus I want to show you why this works like this. Here is how Ruby interprets requires and class openings.

#user.rb
class User
  def hello
    puts "hello"
  end
end

#config.ru
require 'user' # Here we include the original User class

class User # on this line we reopen the user class
  def goodbye # We add a new method to the user class
   puts "goodbye"
  end
end

If we call user somewhere after the user require in config.ru, but before reopening the class, we can not access the goodbye method. However, after reopening the class definition and adding it we can. This is also the function of the Sinatra set method and is why it can only be called inside an open Sinatra class. That is why you sometimes also see alternative ways not using the set method. requiring or including things in the Sinatra class in your config.ru will make the widely available in your Sinatra applications.

Another common thing that causes problems is that Sinatra is built upon Rack thus opening Rack class and configuring stuff there can also make these changes available in Sinatra.

Upvotes: 0

Thomas
Thomas

Reputation: 181745

Looks like it might be an ordering problem. If that DataMapper.setup(...) line is really at the top level of app.rb, it will be called as soon as you require './app.rb', before configure has run.

It's best not to do any work upon loading a file. Use some form of explicit or lazy initialization instead.

Upvotes: 3

Related Questions