Architecture for a modular, component-based Sinatra Application
This is similar to include's proposal, but it doesn't require access to the rackup file.
Write your various Handlers like:
class FoodHandler < Sinatra::Base
get '/chunky/:food' do
"Chunky #{params[:food]}!"
end
end
Then in your main application file:
require './lib/handlers/food_handler.rb'
class Main < Sinatra::Base
enable :sessions
... bla bla bla
use FoodHandler
end
I've used this kind of structure to build some fairly complex Sinatra apps. It scales just as well as Rails.
EDIT
To have your config file define the routes, you could do something like this:
class PlacesHandler < Sinatra::Base
# Given your example, this would define 'places/paris' and 'places/losangeles'
CONFIG['components'].select { |c| c['compontent_type'] == 'Mapper' }.each do |c|
get c['route'] do
@latitude = c['component_settings']['latitude']
@longitude = c['component_settings']['longitude']
end
end
end
What is meant by Modular in Sinatra?
It means that you can create one or more Sinatra apps like the one you outlined in your question, as independent modules within the same super-app, for instance tied together using Rack#map
:
# config.ru
require 'app1'
require 'app2'
run Rack::Builder.new {
map "/app1" do
run App1.new
end
map "/app2" do
run App2.new
end
}
Standardizing api responses in a modular Sinatra application
With some help from #sinatra on irc.freenode.org, I managed to get it down to what I want. I added the following to MyApp:
def route_eval
result = catch(:halt) { super }
throw :halt, {"result" => result}
end
I then changed the following line in ResponseMiddleware:
response = {'status' => 'success', 'data' => body}
to
response = {'status' => 'success', 'data' => body["result"]}
and all my test cases passed.
How mix in routes in Sinatra for a better structure
You don't do include with Sinatra. You use extensions together with register.
I.e. build your module in a separate file:
require 'sinatra/base'
module Sinatra
module OtherRoutes
def self.registered(app)
app.get "/route1" do
...
end
end
end
register OtherRoutes # for non modular apps, just include this file and it will register
end
And then register:
class Server < Sinatra::Base
register Sinatra::OtherRoutes
...
end
It's not really clear from the docs that this is the way to go for non-basic Sinatra apps. Hope it helps others.
How to define a method to be called from the configure block of a modular sinatra application?
It seems the configure
block is executed as the file is read. You simply need to move the definition of your method before the configure block, and convert it to a class method:
class MyApp < Sinatra::Base
def self.read_config_file()
# interpret a config file
end
configure :production do
myConfigVar = self.read_config_file()
end
configure :development do
myConfigVar = self.read_config_file()
end
end
Documenting Sinatra routes for extensions (Yard::Sinatra doesn't work)
You might want to take a look into Cachafla's YARD::Sinatra version of the gem: gem install cachafla-yard-sinatra
more concise url route pattern in sinatra
I haven't used it before, but there's an extension from the sinatra-contrib project that will let you nest like that.
http://www.sinatrarb.com/contrib/namespace.html
Then you could do something like this:
namespace '/v1' do
get '/command_1' {}
get '/command_2' {}
# etc
end
Related Topics
Rails 3: User Created Custom Forms
Ruby Code Beautification, Split Long Instructions on Multiple Lines
How to Stop God from Leaving Stale Resque Worker Processes
How to Fix Libv8 Error from Gemfile on Mavericks
Ruby on Rails Model Inside Namespace Can't Be Found in Controller
Examples of 'Things' That Are Not Objects in Ruby
Rendering a JSON Object of a Join-Model and Its Associated Models
Testing Hash Contents Using Rspec
Is There a Workaround to Open Urls Containing Underscores in Ruby
Ruby Sandboxing VS. Integrating a Scripting Language
Ruby Mechanize Post with Header
How to Calculate 32 Bit Crc in Ruby on Rails
Map an Array Modifying Only Elements Matching a Certain Condition
Good Explanation of Ruby Object Model -- Mainly, 'Classes Are Objects'