Inline templating does not work along with modularity? - ruby

I'm making a modular application:
main.rb
require "sinatra/namespace"
require "haml"
Dir.glob("servers/*/server.rb").each do |server|
require_relative server
end
And I want to do inline templating:
servers/some/server.rb
namespace "/some/hello" do
get "/" do
haml :index
end
end
__END__
## index
!!!
%html
hello
But I get the:
No such file or directory - views/index.haml
It works if I move the template to main.rb but then it's kinda not modular anymore.

Had the same error in another case:
main.rb
require_relative "server_common"
get / do
haml :index
end
__END__
## index
!!!
.....
server_common.rb
require "sinatra"
.....
Solution:
require "sinatra"
set :inline_templates, caller.first[/[^:]+/]
Also had to add this because Sinatra didn't autorun.
set :app_file, caller.first[/[^:]+/]

Related

How to custom layout directory in sinatra

I have a Sinatra app with multiple layouts, one for admin panel, and one for public. I want to isolate them into their own subdirectory in views:
views/
views/layout.erb (for public)
views/auth/
views/auth/layout.erb (for admin)
but I got error. config.ru :
require 'sinatra'
get "/" do
erb :layout
end
get "/auth" do
erb :layout => :'auth/layout'
end
First, the second "erb" call is wrong. Change it to:
erb :layout, :layout_options => { :views => 'views/auth' }
If you want use Sinatra's "Classic Style", the code you showed should not be in config.ru. Move the code from config.ru to another file, e.g. app.rb. Correcting the second "erb" call, app.rb will contain:
# app.rb
require 'sinatra'
get "/" do
erb :layout
end
get "/auth" do
erb :layout, :layout_options => { :views => 'views/auth' }
end
Run it like this: ruby app.rb. It will by default start a local server on port 4567.
Now the URLs http://localhost:4567 and http://localhost:4567/auth should work.
Remember, you should not render a layout.erb file directly. It is used to wrap your views. Check Sinatra: Getting Started for more examples.

Errno::ENOENT at / no such file or directory

I'm currently working on a sinatra app and im having a little problem.
i'm trying to load my index.erb but sinatra cannot find the index.erb.
Here is my app.rb
require 'rubygems'
require 'sinatra'
module Registration
class HelloWorldApp < Sinatra::Base
get '/' do
erb :index
end
end
end
and this is my Code hierarchy.
It keeps on looking in the directory: Sinatra-Intro/app/views/index.erb
but my views is in the: Sinatra-Intro/views/index.erb
You need to configure your application instance, something like this should work:
require 'rubygems'
require 'sinatra'
module Registration
class HelloWorldApp < Sinatra::Base
configure do
set :public_folder , File.expand_path('../public', __FILE__)
set :views , File.expand_path('../views', __FILE__)
set :root , File.dirname(__FILE__)
set :show_exceptions, development?
# Optional: Load from external file
#YAML.load_file('path/to/config.yml').each do |k, v|
# set(k.to_sym, v)
#end
end
get '/' do
erb :index
end
end
end
Then:
bundle exec rackup
You can change the default location with the view setting. Like this:
set :views, Proc.new { File.join(root, "views") }

Set Up for RSpec in a Sinatra modular app

This is my first attempt with Sinatra. I built a simple classic app, set up RSpec for it, and got it working. Then, I tried to go modular, in a MVC fashion. Even though the app works in the browser, RSpec throws a NoMethodError. I've read Sinatra docs regarding RSpec, also searched a lot here in SO, but I can't find where the bug is. Any clue?
Thank you very much in advance.
Here are my relevant files:
config.ru
require 'sinatra/base'
Dir.glob('./{app/controllers}/*.rb') { |file| require file }
map('/') { run ApplicationController }
app.rb
require 'sinatra/base'
class ZerifApp < Sinatra::Base
# Only start the server if this file has been
# executed directly
run! if __FILE__ == $0
end
app/controllers/application_controller.rb
class ApplicationController < Sinatra::Base
set :views, File.expand_path('../../views', __FILE__)
set :public_dir, File.expand_path('../../../public', __FILE__)
get '/' do
erb :index
end
end
spec/spec_helper.rb
require 'rack/test'
# Also tried this
# Rack::Builder.parse_file(File.expand_path('../../config.ru', __FILE__))
require File.expand_path '../../app.rb', __FILE__
ENV['RACK_ENV'] = 'test'
module RSpecMixin
include Rack::Test::Methods
def app() described_class end
end
RSpec.configure { |c| c.include RSpecMixin }
spec/app_spec.rb
require File.expand_path '../spec_helper.rb', __FILE__
describe "My Sinatra Application" do
it "should allow accessing the home page" do
get '/'
expect(last_response).to be_ok
end
end
The error
My Sinatra Application should allow accessing the home page
Failure/Error: get '/'
NoMethodError:
undefined method `call' for nil:NilClass
# ./spec/app_spec.rb:5:in `block (2 levels) in <top (required)>'
I'm guessing you're following this recipe, correct?
The described_class in this line:
def app() described_class end
is meant to be the class under test, in this case ZerifApp. Try it like so:
def app() ZerifApp end
EDIT
It turns out the above answer is not correct about what described_class does. I assumed it was a placeholder -- actually it is an RSpec method that returns the class of the implicit subject, that is to say, the thing being tested.
The recipe at the link is misleading because of the way it recommends writing the describe block:
describe "My Sinatra Application" do
This is valid RSpec, but it does not define the subject class. Executing described_class in an example for this block will return nil. To make it work, replace the describe block:
describe ZerifApp do
Now described_class will return the expected value (ZerifApp)
https://pragprog.com/book/7web/seven-web-frameworks-in-seven-weeks
It has some source code to get some ideas from.
This has code example too. https://github.com/laser/sinatra-best-practices

Reloading models and helpers with Sinatra::Reloader

I'm trying to automatically reload a Sinatra project in JRuby on Windows Vista/7. I'm using Sinatra::Reloader from Sinatra-contrib. Unfortunately, it only seems to work for controllers. Any changes to models and helpers aren't reloaded.
Am I using also_reload incorrectly or something?
Here's what my project looks like:
/app.rb
require 'sinatra'
require 'sinatra/reloader'
require 'json'
class App < Sinatra::Application
enable :sessions
enable :logging
register Sinatra::Reloader
also_reload "models/*.rb"
also_reload "helpers/*.rb"
helpers do
include Rack::Utils
alias_method :h, :escape_html
end
end
require_relative 'helpers/init'
require_relative 'models/init'
require_relative 'controllers/init'
/controllers/init.rb
enable :sessions
require_relative 'auth'
require_relative 'customer'
require_relative 'policy'
require_relative 'forms'
/helpers/init.rb
require_relative 'auth_helper'
require_relative 'customer_helper'
require_relative 'flash_helper'
require_relative 'form_helper'
require_relative 'policy_helper'
/models/init.rb
require 'lib/sqljdbc4.jar'
require 'sequel'
require 'logger'
Java::com.microsoft.sqlserver.jdbc.SQLServerDriver
url = 'foo'
DB = Sequel.connect(url)
DB.loggers << Logger.new($stdout)
Sequel.inflections do |inflect|
inflect.clear :all
end
files = [
:customer,
:customer_email,
:phone_number ]
files.each do |f|
require_relative f.to_s
end
Under current implementation of yours, let's say you change something in helpers/auth_helper.rb. This file gets reloaded but since the helpers/init.rb is unchanged, it won't be reloaded by sinatra-reloader and you won't see the changes. Have you tried shotgun gem?

Sinatra + Rspec2 - Use Sessions/Helpers?

I am trying to test my Sinatra app using Rspec2 but I can't get access to sessions or helper methods in my tests.
spec_helper:
require File.dirname(__FILE__) + "/../myapp.rb"
require 'rubygems'
require 'sinatra'
require 'rack/test'
require 'rspec'
require 'factory_girl'
set :environment, :test
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
def app
Sinatra::Application
end
app_spec.rb:
require File.dirname(__FILE__) + "/../spec_helper.rb"
describe 'Something' do
it "should do something" do
session["aa"] = "Test"
end
end
This throws an error, can't find session variables. Similarly I can't use helper methods which are defined in my app.
I run my tests using rspec specs/app_spec/app_spec.rb.
What am I doing wrong?
Assuming you've got your specs and spec helper in the /spec dir, then this line should go at the top of your spec:
require_relative "./spec_helper.rb"
I also like to use File.expand_path and File.join as it's more reliable than doing it yourself, e.g.
require File.dirname(__FILE__) + "/../spec_helper.rb"
becomes
require_relative File.expand_path( File.join File.dirname(__FILE__), "/../spec_helper.rb" )
Also, I don't tend to require "sinatra", the app has that. If you're missing bits from sinatra then maybe, but I add things like this instead through rack:
ENV['RACK_ENV'] = 'test'
Finally, if your Sinatra app is using the modular style then you'll have to include it too. I do this at the top of a spec, for example:
describe "The site" do
include Rack::Test::Methods
include MyApp
let(:app) { MyApp.app }
YMMV. Let us know if any of this works.
A different test to try:
before(:all) { get "/" }
subject { last_response }
it { should be_ok }

Resources