Sinatra : how to use helpers in Mustache views - ruby

I want to use my Sinatra helpers methods in Mustache views.
I do this:
# in app.rb:
...
helpers do
def helloworld
"helloworld!"
end
end
get '/'
mustache :home
end
...
# in views/home
class App < Sinatra::Base
module Views
class Home < Mustache
def hello
helloworld
end
end
end
end
# in home.mustache
<p>{{hello}}</p>
It does not work, I have the error message :
«undefined local variable or method `helloworld' for App::Views::Home:0x000000023ebd48»
How can I use my method helper in Mustache view ?
Or, how can I use my method helper directly from home.mustache ? like this :
# in home.mustache
<p>{{helloworld}}</p>
Many thanks for your help!

You should be able to do something with a module:
# app_helpers.rb
module AppHelpers
def helloworld
"helloworld!"
end
end
# app.rb
helpers AppHelpers
get '/'
mustache :home
end
# views/home.rb
class App < Sinatra::Base
module Views
class Home < Mustache
include AppHelpers
def hello
helloworld
end
end
end

Related

Sinatra App - Separating Concerns

Probably something really basic, but I want to be able to separate my Sinatra routes from controllers. I have this code in my routes.rb:
require 'sinatra/base'
class Server < Sinatra::Base
get '/' do
Action.index
end
end
This is my controller/server.rb
class Action
def sef.index
#user = User.new("Abiodun Shuaib")
haml: index
end
end
It gives the error undefined method 'haml' in Action:Class.
How can I fix this?
You are trying to access method haml in class Action. It simply doesn't contain it.
For example, you can do:
class Server
def index
#user = User.new("Abiodun Shuaib")
haml :index
end
end
By doing this, you will add to Server method index.
Or you can do in such way(it's called Mixin):
module ActionNew
def index
#user = User.new("Abiodun Shuaib")
haml :index
end
end
class Server < Sinatra::Base
include ActionNew
get '/' do
index
end
end

How can I use my Sinatra helpers in included modules?

I have my routes and helpers defined in external files and included by Sinatra, however I'm new to Ruby and I can't now figure out how I can use my helper methods in my routes. When I run the code in RubyMine and access a profile URL I get the error "NoMethodError - undefined method `protected!'"
## Main class
require 'sinatra/base'
class MyApp < Sinatra::Base
register Sinatra::MyHelpers
register ProfileRoutes
...
end
## Helpers include
require 'sinatra/base'
module Sinatra
module LocutusHelpers
def self.registered( app )
app.before do
...
end
def protected!
...
end
end
end
end
## Routes include
require 'sinatra/base'
module ProfileRoutes
def self.registered( app )
app.get '/profile/:userid' do
protected!
...
end
end
end
I've tried def self.protected! for the helper but then it cant access the request object.
I've also tried Sinatra::MyHelpers.protected!, Sinatra.protected! and app.protected!, errors are thrown for all of these too
Do you know how I can access the helpers from my routes? Or have I set something up incorrectly?
It looks like you are mixing up adding helpers from extensions and configuring your app from extensions.
You need to move protected! into a module, then when registering your extension add that module as a helpers module.
module LocutusHelpers
# new module, move protected! into here
module HelperMethods
def protected!
...
end
end
def self.registered( app )
# add new hlpers module
app.helpers HelperMethods
# other extension setup as before...
app.before do
...
end
end
end

Access Sinatra settings from a model

I have a modular Sinatra app. I'm setting some custom variables in my configure block and want to access these settings in my model.
The problem is, I get a NoMethodError when I try and access my custom settings from MyModel. Standard settings still seem to work fine though. How can I make this work?
# app.rb
require_relative 'models/document'
class App < Sinatra::Base
configure do
set :resource_path, '/xfiles/i_want_to_believe'
end
get '/' do
#model = MyModel.new
haml :index
end
end
# models/my_model.rb
class MyModel
def initialize
do_it
end
def do_it
...
settings.resource_path # no method error
...
settings.root # works fine
end
end
i think that you should be able to access it via
Sinatra::Application.settings.documents_path
I ended up doing:
#document.rb
class Document
def self.documents_path=(path)
#documents_path = path
end
def self.documents_path
#documents_path
end
...
end
#app.rb
configure do
set :documents_path, settings.root + "/../documents/"
Document.documents_path = settings.documents_path
end
then just using Document.documents_path inside my find method.

How to use alias_method in Haml to escape html?

What I want to do is using an alias method (defined in a ruby file) in Haml view.
I defined an alias method like following:
require 'sinatra'
require 'sinatra/base'
require 'data_mapper'
require 'haml'
helpers do
include Haml::Helpers
alias_method :h, :html_escape
end
class App < Sinatra::Base
use Rack::MethodOverride
# ...
end
Then I used method h() in a Haml view like following:
- #notes.each do |note|
%article{:class => note.complete? && "complete"}
%p
=h note.content
But I got an error when I opened the page:
NoMethodError - undefined method `h' for #:
...
When I use Haml::Helpers.html_escape() directly on the haml file, there's no problem:
%p
= Haml::Helpers.html_escape note.content
How can I use my alias method in haml files without errors?
Thanks for any advices or corrections to this questions.
Your helpers are getting defined in Application. Instead define them in your class like this:
class App < Sinatra::Base
helpers do
include Haml::Helpers
alias_method :h, :html_escape
end
# ...
end
or in Base like this:
Sinatra::Base.helpers do
include Haml::Helpers
alias_method :h, :html_escape
end

How mix in routes in Sinatra for a better structure

I found nothing about how I can mix-in routes from another module, like this:
module otherRoutes
get "/route1" do
end
end
class Server < Sinatra::Base
include otherRoutes
get "/" do
#do something
end
end
Is that possible?
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.
You could do this:
module OtherRoutes
def self.included( app )
app.get "/route1" do
...
end
end
end
class Server < Sinatra::Base
include OtherRoutes
...
end
Unlike Ramaze, Sinatra's routes are not methods, and so cannot use Ruby's method lookup chaining directly. Note that with this you can't later monkey-patch OtherRoutes and have the changes reflected in Server; this is just a one-time convenience for defining the routes.
I prefer the use of sinatra-contrib gem to extend sinatra for cleaner syntax and shared namespace
# Gemfile
gem 'sinatra', '~> 1.4.7'
gem 'sinatra-contrib', '~> 1.4.6', require: 'sinatra/extension'
# other_routes.rb
module Foo
module OtherRoutes
extend Sinatra::Extension
get '/some-other-route' do
'some other route'
end
end
end
# app.rb
module Foo
class BaseRoutes < Sinatra::Base
get '/' do
'base route'
end
register OtherRoutes
end
end
sinata-contrib is maintained alongside the sinatra project
Well you can also use the map method to map routes to your sinatra apps
map "/" do
run Rack::Directory.new("./public")
end
map '/posts' do
run PostsApp.new
end
map '/comments' do
run CommentsApp.new
end
map '/users' do
run UserssApp.new
end
Just my two cents:
my_app.rb:
require 'sinatra/base'
class MyApp < Sinatra::Base
set :root, File.expand_path('../', __FILE__)
set :app_file, __FILE__
disable :run
files_to_require = [
"#{root}/app/helpers/**/*.{rb}",
"#{root}/app/routes/**/*.{rb}"
]
files_to_require.each {|path| Dir.glob(path, &method(:require))}
helpers App::Helpers
end
app/routes/health.rb:
MyApp.configure do |c|
c.before do
content_type "application/json"
end
c.get "/health" do
{ Ruby: "#{RUBY_VERSION}",
Rack: "#{Rack::VERSION}",
Sinatra: "#{Sinatra::VERSION}"
}.to_json
end
end
app/helpers/application.rb:
module App
module Helpers
def t(*args)
::I18n::t(*args)
end
def h(text)
Rack::Utils.escape_html(text)
end
end
end
config.ru:
require './my_app.rb'

Resources