Sinatra public assets not available when uploading to Heroku - ruby

I've just started working on a simple Sinatra app and when uploading it to Heroku. None of the files in the public folder seem to be available but it works fine locally.
Are there any obvious reasons this might be happening?
Right now the code is really simple:
require 'rubygems'
require 'sinatra'
require 'bundler/setup'
require 'haml'
require 'rdiscount'
set :static, true
set :public_folder, "#{File.dirname(__FILE__)}/public"
get '/' do
haml :landing
end
__END__
## layout
%html
%head
%meta{charset: "utf-8"}/
%meta{content: "width=device-width, initial-scale=1.0", name: "viewport"}/
%meta{content: "", name: "description"}/
%meta{content: "", name: "author"}/
%title TIL
%link{href: "http://yui.yahooapis.com/pure/0.3.0/pure-min.css", rel: "stylesheet"}
%link{rel: "stylesheet", href: "/styles.css"}
%body
= yield
##landing
%section.hero
.container
.pure-g-r
.pure-u-1
.logo
...
.container
%hr/
.pure-g-r
.pure-u-2-3
.padding-box
:markdown
...
.pure-u-1-3
.padding-box
..
%hr/
.pure-g-r
.pure-u-1
.padding-box
:markdown
...
%hr/
.pure-g-r
.pure-u-1
.padding-box
%h2 ...
.pure-u-1-3
.padding-box
%img.img-rounded{src: "GD-thumbnail.png"}/
:markdown
...
.pure-u-1-3
.padding-box
%img.img-rounded{src: "AL-thumbnail.png"}/
:markdown
...
.pure-u-1-3
.padding-box
%img.img-rounded{src: "BP-thumbnail.png"}/
:markdown
...
%hr/
%footer
.row
.col-lg-12
%p
Local file structure is:
TIL (folder)
- app.rb
- Gemfile
- Procfile
- public (folder)
- AL-thumbnail.png
- BP-thumbnail.png
- GD-thumbnail.png
- logo.png
- styles.css

Have a look in your Heroku log file:
heroku logs
If you can see something like
Rack::Flash::SessionUnavailable - Rack::Flash depends on session middleware.:
Then add
gem "rack-flash-session"
to you Gemfile.
Also add 'require 'rack/flash/test'' to you main file.
This will force heroku to load the desired middelware.

Related

Change Sinatra views directory location

I'd like to structure a Sinatra application more like a Rails application with the following structure:
.
├── app
│ ├── models
│ │ └── a_model.rb
│ └── views
│  └── a_view.erb
└── app.rb
According to the documentation, it can be done by overwriting the :views setting:
:views - view template directory
A string specifying the directory where view templates are located. By default, this is assumed to be a directory named “views” within the application’s root directory (see the :root setting). The best way to specify an alternative directory name within the root of the application is to use a deferred value that references the :root setting:
set :views, Proc.new { File.join(root, "templates") }
I've setup :root and :views:
set :root, File.dirname(__FILE__)
set :views, Proc.new { File.join(root, 'app', 'views') }
# Also tried some variations like:
# set :views, 'app/views/'
# set :views, Proc.new { File.join(setting.root, 'app', 'views' }
# set :public_folder, Proc.new { File.join(root, 'app', 'views' }
# ...
class MyApp < Sinatra::Base
get '/' do
erb :a_view
end
end
But I'm always facing the same error message:
No such file or directory # rb_sysopen - /path/to/my/app/views/a_view.erb
Indeed, settings.views is evaluated to /path/to/my/app/views (instead of /path/to/my/app/app/views)
It looks like I cannot control the value of the :views (settings.views) variable. I know I could simply move the views folder to the root location.
Can anyone explain why I'm not able to control theses settings ?
Move settings inside class definition has all the settings are inherited from inside Sinatra::Base
class MyApp < Sinatra::Base
set :root, File.dirname(__FILE__)
set :views, Proc.new { File.join(root, 'app', 'views') }
get '/' do
erb :a_view
end
end
Or
class MyApp < Sinatra::Base
configure do
set :root, File.dirname(__FILE__)
set :views, Proc.new { File.join(root, 'app', 'views') }
end
get '/' do
erb :a_view
end
end

Public Directory Not Being Served With Sinatra

As the title says, I cannot get Heroku to use my public assets.
Locally, when running my app with shotgun it works. But with rackup (what Heroku uses), the css and assets 404.
I've tried a bunch of answers on here (one, two, three) but none have worked.
Here's my directory structure:
My config.ru:
require 'bundler'
Bundler.require
require File.expand_path('../config/environment', __FILE__)
run BikeShareApp
And my controller:
class BikeShareApp < Sinatra::Base
get '/' do
erb :'home/index'
end
get '/stations' do
#stations = Station.all
erb :'stations/index'
end
end
EDIT: This is how I'm referencing my assets by the way
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/overwrite.css" rel="stylesheet">
Found it.
Following this guide and putting this in my config.ru worked:
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
}
]
}

my Rack::Static middleware works with root url in urls parameter and without

I have this in my config.ru:
require 'rack'
require './app.rb'
use(Rack::Static,
:urls => %w(/css /fonts /images /js),
:root => '../static',
:index => 'index.html')
end
run MyApp
it correctly serves static files for all four of the above URLs, but in addition, it also serves index.html from the root URL as if I had :urls => %w(/ /css /fonts /images /js) and I do not understand why this is happening. I could not find any explanation in the documentation.

How to get Liquid template partials (includes) working with Sinatra?

I am new to ruby and I am trying to get template partials working in my Sinatra + Liquid project.
I have several template partials in my /includes directory.
How can I get all of these templates working as liquid partials so I can use them with liquid include tag?
What I actually have done:
# Sinatra First App
require 'sinatra'
require 'sinatra/config_file'
require 'liquid'
config_file 'config.yml'
# WebRick
set :run, true
set :server, %w[webrick]
# App Paths
set :root, File.dirname(__FILE__)
set :views, File.dirname(__FILE__) + '/views'
set :controlers, File.dirname(__FILE__) + '/controlers'
set :public_folder, Proc.new { File.join(root, "static") }
# Includes Folder
includes = File.dirname(__FILE__) + '/includes'
get '/' do
Liquid::Template.file_system = Liquid::LocalFileSystem.new(includes)
Liquid::Template.parse(includes).render
liquid :index, :locals => { :title => "My Sinatra App"}
end
get '/test' do
"This is the test page."
end
But I am still getting: Liquid error: Illegal template name ''.
Here is my index template:
<html>
{% include 'header' %}
<body>
<h1>{{ title }}</h1>
{{content}}
</body>
</html>
and here is the header part template:
<head>
<title>{{ title }}</title>
</head>
How can I fix it? Thanks for every response.
Of the get '/' route, it seems to me that the first line should be in a configuration block, and the second line shouldn't be needed at all as Tilt/Sinatra should take care of calling render, e.g.
configure do
set :views, File.join(File.dirname(__FILE__),'/includes')
# or just put these in the views dir
end
get '/' do
liquid :index, :locals => { :title => "My Sinatra App"}
end
or, if you want a views directory with sub-directories for partials/includes etc, something like "./views/includes", you could pass the view folder as an option, e.g.
get '/' do
liquid :index, :locals => { :title => "My Sinatra App"}, :views => File.join(File.dirname(__FILE__),'views/includes')
end
or you could try Sinatra Partial (I'm the maintainer).
Since the above didn't work (see comments), I looked at the Sinatra tests for Liquid and played around with the OP's code. I found that the following worked for me:
# ./app.rb
# Sinatra First App
require 'sinatra'
require 'sinatra/config_file'
require 'liquid'
config_file 'config.yml'
configure do
# WebRick
set :run, true
set :server, %w[webrick]
# App Paths
set :root, File.dirname(__FILE__)
set :views, File.dirname(__FILE__) + '/views'
set :controlers, File.dirname(__FILE__) + '/controlers'
set :public_folder, Proc.new { File.join(root, "static") }
Liquid::Template.file_system = Liquid::LocalFileSystem.new(File.join(File.dirname(__FILE__),'views/includes'))
end
get '/' do
liquid :index, :locals => { :title => "My Sinatra App" }
end
get '/test' do
"This is the test page."
end
#./Gemfile
source "https://rubygems.org"
gem "sinatra"
gem "liquid"
gem "sinatra-contrib"
#./views/includes/_header.liquid
<head>
<title>{{ title }}</title>
</head>
#./views/index.liquid
<h1>{{ title }}</h1>
{{content}}
#./views/layout.liquid
<html>
{% include "header" %}
<body>
{{ yield }}
</body>
</html>

Less hangs Sinatra application

I am trying to add Bootstrap to a Sinatra application. I have setup routes to compile bootstrap.less and responsive.less. Loading the two stylesheets separately in a web browser works as expected. But when I try to use them in a html page my application hangs. I can only stop the application with kill -9.
It seems that somehow Less imports and multiple stylesheets cause a hang of the application. I was able to isolate the problem:
app.rb
require 'rubygems'
require 'bundler/setup'
require 'sinatra'
require 'less'
get '/' do
haml :index
end
get '/style1.css' do
less :style1, :paths => ['views']
end
get '/style2.css' do
less :style2, :paths => ['views']
end
views/index.haml
!!! 5
%html
%head
%title Hello World
%link{'rel' => 'stylesheet', 'href' => 'style1.css', 'type' => 'text/css'}
%link{'rel' => 'stylesheet', 'href' => 'style2.css', 'type' => 'text/css'}
%body
%h1 Hello World
%p Hello World
views/style1.less
#import "mixins.less";
#import "shadows.less";
#color: #00eeff;
h1 {
color: #color;
}
views/mixins.less
.box-shadow(#shadow) {
-webkit-box-shadow: #shadow;
-moz-box-shadow: #shadow;
box-shadow: #shadow;
}
views/shadows.less
h1 {
.box-shadow(6px 6px 3px #888);
}
views/style2.less
#color: #ccff00;
p {
color: #color;
}
Accessing the index page hangs Sinatra. If I comment out style2.less in the html page or inline shadows.less or mixins.less in style1.less the page loads as expected.
Any idea what could be the problem or how I can debug this further?
I took your files and made small changes to them:
I renamed style2.css to style2.less so i can use Less on it, and eventually download the style2.css with the correct css syntax ---It was not working with the other extension.
And, I told Less that the path to search for directives, was the views path of Sinatra: Less.paths << settings.views.
So, with these changes, the Sinatra application stopped hanging.

Resources