|
SinatraReloaded
Getting Started guide for Sinatra with focus on development environment
IntroductionThis guide is based on GettingStarted guide, but extends it with templating changed to HAML and gem management changed to bundler. The Rack::Reloader is used for reloading development environment. Local installationIt's important to understand that development environment for the appengine and the Jruby contain 3 different places of ruby gems:
System ruby gems installationFirst, make sure that you have the latest version of gem installed $ gem --version 1.3.5 $ # If you have the older version perform upgrade $ gem update --system $ # Install the required system gems $ gem install --no-rdoc --no-ri google-appengine bundler rack Application gems installationCreate the folder for application. In this guide it's assumed to be ~/guestbook/. $ mkdir guestbook $ cd guestbook The original guide recommends using appcfg.rb gem for application gem installation, but will be using bundler. In order to manage gems one need to create the Gemfile control file. Ours will be pretty simple. $ cat >Gemfile <<EOF disable_system_gems disable_rubygems bundle_path ".gems/bundler_gems" gem "sinatra" gem "dm-core" gem "dm-appengine" gem "haml" EOF After the file is there, let's install gems $ gem bundle Note, this all done with you local MRI ruby. Now, you should have .gems folder in you application directory with all required gems and dependencies. As you can see, you don't need sinatra or haml installed in your system gems. It's bundled (frozen) in your application. Creating applicationFirst let's create the config.ru, which will configure application and reloading for development environment. The simple use Rack::Reloader will not work as we need to reload the Sinatra framework. $ cat >config.ru <<EOF
require 'appengine-rack'
require 'guestbook'
AppEngine::Rack.configure_app(:application => "guestbook", :version => 1)
configure :development do
class Sinatra::Reloader < ::Rack::Reloader
def safe_load(file, mtime, stderr)
if File.expand_path(file) == File.expand_path(::Sinatra::Application.app_file)
::Sinatra::Application.reset!
stderr.puts "#{self.class}: reseting routes"
end
super
end
end
use Sinatra::Reloader
end
run Sinatra::Application
EOFThe reloader example, above, assumes that application is Sinatra traditional style application and all routes defined in the 'guestbook.rb' file, or main file of the application. If application has a separate file for routes, for example 'route.rb', then ::Sinatra::Application.app_file should be replaced with './route.rb' or similar. What is meant here is that you need to do .reset! only in case when file with routes changes. If you routes scattered in different files you need to write more complex reloading strategy. If you are using 'sinatra/base' instead of the traditional Sinatra application, you, probably, already found out, that you should take care about everything yourself. And the reloader is no exception. Everywhere, where ::Sinatra::Application mentioned, you need to replace it with your class. Assume following example: require 'sinatra/base'
class Simple < Sinatra::Base
get '/' do
'Hello World!'
end
endthen your reloader should do Simple.reset! for file with routes. And, of course, you need to change run Sinatra::Application to run Simple.new. Now, let's get back and put the application itself $ cat >guestbook.rb <<EOF
require 'sinatra'
require 'dm-core'
require 'haml'
# Configure DataMapper to use the App Engine datastore
DataMapper.setup(:default, "appengine://auto")
# Create your model class
class Shout
include DataMapper::Resource
property :id, Serial
property :message, Text
end
# Set Haml output format and enable escapes
set :haml, {:format => :html5 , :escape_html => true }
# Main board
get '/' do
# Just list all the shouts
@shouts = Shout.all
haml :index
end
post '/' do
# Create a now shout and redirect back to the list
shout = Shout.create(:message => params[:message])
redirect '/'
end
EOFLet's add some templates as well $ mkdir views First, the above-mentioned index.haml $ cat >views/index.haml <<EOF
%h2 Messages
- for shout in @shouts
%p<
Someone wrote,
%q= shout.message
%form{:method => :post}
%textarea{:name => :message}
%br/
%input{:type => :submit, :method => :Shout}
EOFAnd the layout for the application $ cat >views/layout.haml <<EOF
!!!
%html
%head
%title Guestbook
%body
!= yield
EOFInstall deployment gems and create local structureFirst we need to install the jruby and appengine. Thanks to this project it's dead easy $ # AppEngine gems version < 0.0.5 : $ appcfg.rb gem bundle $ # ppEngine gems version = 0.0.5 : $ appcfg.rb bundle . In case you changed the Gemfile to add new gems to your environment, just rerun bundler in your local and jruby environment. The appcfg.rb does not always correctly check what's deployed, it doesn't know that we are using bundler, so just delete gems.jar. $ # Install gems in the application .gems folder $ gem bundle $ # Remove the deployment gems $ rm WEB-INF/lib/gems.jar $ # Package the deployment gems (appengine gems version < 0.0.5) $ appcfg.rb gem bundle $ # Package the deployment gems (appengine gems version = 0.0.5) $ appcfg.rb bundle . Running serversNow, finally we are ready to run the development with Sinatra reloading. $ dev_appserver.rb . The Rack::Reloader uses mtime on your system, so if the reloader is not doing its job try touch guestbook.rb. Enjoy! all question and improvements are welcome in the google group |
Sign in to add a comment
I tried to use your reloader but it fails because I have a diferent file for all my models. When I save any file in my application, the application starts sending a not found in every in route... any advice?
Richard, how do you include the code in your application? Reloader works only with "require" and does not with "load". Do you see in the log the "reloaded" message ?
when running appcfg.rb bundle . i get:
/usr/lib/ruby/site_ruby/1.8/rubygems.rb:280:in `activate': can't activate bundler (= 0.6.0, runtime) for ["appengine-tools-0.0.5"], already activated bundler-0.7.0 for (Gem::LoadError?)
Trying to overcome it usging JRuby:
jruby -S appcfg.rb bundle .
i get nothing and gems.jar is not even generated....
this is bug in current version - see bug 36. Uninstall bundler v 0.7.0 with your MRI ruby and install v 0.6.0
gem uninstall bundler
gem install bundler -v 0.6.0
or, alternatively, don't install bundler manually as mentioned above, then correct version will be installed with google-appengine gem.
I'm getting this error on Ubuntu. I think it's a user permission issue with the library. All my other ruby gems work fine, so it may be an issue with appengine-jruby and Ubuntu.
/usr/lib/ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require': no such file to load -- appengine-tools/dev_appserver (LoadError?)
Also, bundler do not install gems for java platform. May be better install gems through old solutions while builder do not updated.
In the last section, under "Install deployment gems and create local structure", "appcfg.rb gem bundle" is deprecated. The new syntax is displayed, however, when that is used a classpath exception is thrown. This happened on Cygwin.
See: http://groups.google.com/group/appengine-jruby/browse_thread/thread/bae51f86fc5b5063