views:

284

answers:

2

Hi All

I'm working on my first Sinatra/CouchDB project and I'm getting an error I can't explain.

Here's my rackup (config.ru) file:

require 'rubygems'
require 'couchrest'
require 'patina'

set :environment, :development
set :root, File.dirname(__FILE__)
set :run, false

FileUtils.mkdir_p 'log' unless File.exists?('log')
log = File.new("log/sinatra.log", "a")
$stdout.reopen(log)
$stderr.reopen(log)

set :db, CouchRest.database!("http://127.0.0.1:5984/test")

run Sinatra::Application

And here's the app file (patina.rb):

require 'rubygems'
require 'sinatra'
require 'couchrest'
require 'haml'

class Article < CouchRest::ExtendedDocument
  use_database settings.db

  property :title
  timestamps!
  view_by :title
end

get '/' do
  @db = settings.db
  haml :index
end

Without the class definition in patina.rb, the route returns a page that displays the @db property as I was expecting. However, when I add the class definition to patina.rb I get "Ruby (Rack) application could not be started" error message.

Obviously this has something to do with my class definition, but I can't figure out what the problem is and the error message doesn't seem that helpful to me.

Also, I'd actually prefer to have the class definition in a separate file (Article.rb), but I can't figure out how to do that in the context of my Sinatra app.

Any help would be greatly appreciated!

EDIT:

See my answer below.

A: 

try requiring 'patina' after setting :db. I think the class body of Article is executing the use_database method before the setting exists.

you should be able to put Article in article.rb (ruby naming convention is UpperCamel for classes, but under_scores for the files in which classes are defined) and then require 'article' in patina.rb.

thats the only thing that stood out for me, so let me know if that works.

Ben Hughes
Hi, Ben - thanks for the reply. With those changes, I'm getting a different error: `undefined method `set' for #<Rack::Builder:0xb7b95a0c @ins=[]>`...
safetycopy
its defined in sinatra.rb, require 'sinatra' in the rackup
Ben Hughes
That just leaves me back at my original error: `stack level too deep` :(
safetycopy
can you get a trace on that?
Ben Hughes
The trace was about 3000 lines :/ I think I have it working now, though - see my edit above. Not sure why it works this way, but at least it's progress :)
safetycopy
+2  A: 

After a lot of googling, I discovered that the 1.4 series of json.gem are known to cause a lot of problems. I uninstalled all the json gems I had and installed json-1.2.4.gem instead. I have everything working correctly now. Here's the setup I'm using:

config.ru (Rackup file):

require 'application'

set :environment, :production
set :root, File.dirname(__FILE__)
set :run, false

FileUtils.mkmdir_p 'log' unless File.exists?('log')
log = File.new('log/sinatra.log', 'a+')
$stdout.reopen(log)
$stderr.reopen(log)

run Sinatra::Application

environment.rb:

require 'rubygems'
require 'couchrest'
require 'haml'
require 'ostruct'

require 'sinatra' unless defined?(Sinatra)

configure do
  SiteConfig = OpenStruct.new(
    :title => 'Application Title',
    :author => 'Your Name',
    :url_base => 'Your URL',
    :url_base_db => 'Your CouchDB Server',
    :db_name => "Your DB Name"
  )

  # load models
  $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
  Dir.glob("#{File.dirname(__FILE__)}/lib/*.rb") { |lib| require File.basename(lib, '.*') }
end

lib/contact.rb (Model example, models auto-loaded in environment.rb):

class Contact < CouchRest::ExtendedDocument
  include CouchRest::Validation
  use_database CouchRest.database!((SiteConfig.url_base_db || '') + SiteConfig.db_name)

  property :name
  timestamps!

  view_by :name
end

application.rb:

require 'rubygems'
require 'sinatra'
require 'environment'

configure do
  set :views, "./views"
end

error do
  e = request.env['sinatra.error']
  Kernel.puts e.backtrace.join("\n")
  'Application error'
end

helpers do
end

get '/new/?' do
  haml :new
end

post '/save/?' do
  @contact_name = params[:contact_name]

  @contact = Contact.new
  @contact.name = @contact_name
  @contact.save

  haml :save
end

get '/' do
  haml :index
end

Hope this helps someone in the future!

safetycopy