I am porting a plain HTML/CSS/JS site to using Sinatra for its backend. The main thing I'm interested in is templates. For now, I have a views directory with HTML files named like "index.html.erb" and a layout named "layout.html.erb". While I would like to use Sinatra's templates with erb, the site I'm working on is static. In other words, my "index.html.erb" does nothave any erb-specific code in it. I only really need the layout in my views directory, for now.
Is there a way that I can move views/index.html.erb to public/index.html but still wrap it in the template views/layout.html?
require 'rubygems'
require 'sinatra'
get '/index.html' do
#page_title = 'Home'
#page_id = 'index.html'
erb :'index.html', { :layout => :'layout.html' }
end
Having read through the Sinatra Readme, there are two main issues that come up in what you are trying to do. First, static files versus template files: Sinatra doesn't have a template renderer for plain HTML, so you'd have to use ERB. Since ERB can be plain HTML, the issue with this is that Sinatra can only use a certain list of file extensions for ERB (and .html isn't one of them).
The second issue is that, in your example code, you would have to have the layout folder different from the templates folder (which Sinatra sees as being the same, which is /views by default).
With this in mind, the closest you could get to what you are asking is the following:
require 'sinatra'
configure do
set :views, root
end
get '/index.html'
erb :'public/index.html', { :layout => :'views/layout.html' }
end
However, this also has a few problems. First, as mentioned, you would have to name your files with the .html.erb extension (or, just .erb if you cut the .html out of the 7th line above). Additionally, anyone could access the raw template file at /index.html.erb on your server. Therefore, the method that you displayed in your original question is the best way to do what you are trying to do in Sinatra without delivering a plain HTML file.
I'm using jquery to accomplish this:
get '/thtml/:path' do
#path = params[:path]
erb :thtml
end
thtml.erb
<%= "<script>$('#main').load('/t-html/#{#path}')</script>" %>
Place the html files are in folder /public/t-html. Don't forget to include jquery in layout.erb.
Related
On my Middleman-built website, I need to execute specific Ruby code on the contents of all the pages (templates).
For example, if I had following helper in my config.rb:
def myexample(text)
text.gsub("dog","cat")
end
And in my test.html.haml:
= myexample("Some text about a dog.")
My previewed and generated /test.html would read:
Some text about a cat.
However, I am using several different ways to output text that needs to be modified, most notably through HAML's :markdown filter, so I would prefer not to wrap everything in the = myexample("Text") helper.
I would like to be able to run Ruby code that would take contents of all the pages (preferably) or generated HTML output (if the first option is not possible) as an argument passed to such helper.
Ideally, this code would be run in both the development and build environments, but if that's not possible, build is enough.
Is it possible to do so?
PS. In my specific case, I use a shorthand notation to reference other pages and then I use a regular expression and eval() in order to replace them with relative links from data files.
ActionController::Base has the render_to_string method which will give you the normal HTML output from rendering a partial or page, but in string format. This would allow you to grab the rendered HTML and modify it before finally rendering it for real as an inline template.
In your controller:
rendered_html = render_to_string 'your_template_or_partial'
# do stuff to rendered_html
render inline: rendered_html.html_safe, layout: 'layouts/application'
The html_safe method makes sure Rails knows it's safe to render this as HTML. You do NOT want to do this if user input is being rendered and you have not sanitized it!!!!
If you don't want it to use a layout when rendering, just remove the :layout argument.
I have a markdown template for my index page in Sinatra:
get '/' do
markdown :index
end
How can I call a Sinatra helper from the Markdown template?
Unfortunately it's not possible.
It is not possible to call methods from markdown, nor to pass locals to it.
But
You therefore will usually use it in combination with another rendering engine:
Something like this should do the trick
%h1 Hello From Haml!
%p= markdown(:greetings)
Source: http://recipes.sinatrarb.com/p/views/markdown
I'm a bit new to Rails, so far so good. The assets pipeline/sprockets is pretty neat but I'm a bit confused. When generating scaffolding for my various controllers, individual css/SCSS files were put into app/assets/stylesheets. But for my project I'm using LESS not SCSS, so I replaced them with .css.less files.
The problem I'm running into is that if I add CSS to a controller (let's call it "home.css.less" for example), it gets included in every view, not just views belonging to the "home" controller. If I remove "*= require_tree ." from the application.css file, then the file's not included in any views.
How can I specify CSS code for a particular controller/view using the Rails assets pipeline?
application.css:
/*
*= require twitter/bootstrap
*= require_self
*= require "application_custom"
*/
home.css.less:
body {
background: asset-url("circles.png") no-repeat;
}
The above results in no background being applied, even to the home controller's views.
This is a fairly common request; many sites have home page specific CSS that they don't want applied over the whole site.
I will make a couple of comments about this before providing the solution, if I may.
The purpose of the pipeline to present one CSS (and one JS) file to clients. The digest is added to allow the addition of server headers that force remote clients to keep a copy of them in their local cache.
The single request and aggressive caching strategy are the default for Rails for performance reasons; each request slows down the page.
Unless the home page CSS is really extensive, I would recommend using the default behavior. If the desire to split this out comes from clashes in CSS selectors between home and other pages, I suggest changing the CSS structure to over come this.
There are at least two common solutions:
The first would be used if you want to manually a different file for each controller.
<%= stylesheet_link_tag "application", controller_name %>
For this to work in production you have to tell rails to precompile all the individual CSS files (in application.rb):
config.assets.precompile << '*.css'
The second is to add a helper to render CSS only when it is required from a view.
I recommend the top solution on this question. You will have to modify the helper names for CSS. That will render a tag for the required CSS only when it set in the view.
How can we render many partials from different controllers into one view?
The local variables of each partial are calculated separately in different and independent controllers.
What I really have to make things more specific, is a home layout, and in that layout that has dynamic content, there's a partial that only handles site wide news announcements, and these are independently updated.
I know a quick hack such like:
render :partial => '/news', :locals=> {#news = News.last}
but I want something more "correct". Like I've been reading about :templates rendering but i'm not sure how it works exactly in Rails 3.1.
Any help would be highly appreciated!
2.2.3 Rendering an Action’s Template from Another Controller
What if you want to render a template from an entirely different controller from the one that contains the action code? You can also do that with render, which accepts the full path (relative to app/views) of the template to render. For example, if you’re running code in an AdminProductsController that lives in app/controllers/admin, you can render the results of an action to a template in app/views/products this way:
render 'products/show'
Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the :template option (which was required on Rails 2.2 and earlier):
render :template => 'products/show'
Sources: http://guides.rubyonrails.org/layouts_and_rendering.html#using-content_for
Should have read in more details.
I read http://www.padrinorb.com/guides/application-helpers but I'm unclear as to what are the use cases for each of the view helpers. Specifically, how do content_for/yield_content, render/partial, capture_html, and concat_content all fit together?
Right now I've been using render 'my/view' in my controllers and throwing in some =partial 'my/partial' within 'my/view' just to break apart the main template file into smaller chunks.
Is the right way to go about it? And when/where would I want to use the other helper functions?
Let's go through the use cases.
content_for/yield_content
This is for injecting content into a layout file that might be useful. Example is adding additional css/scripts into a layout from another template. The example on the guide is the same, showing how to add CSS files to your layout from any template that requires them. You can also use it for adding content onto sidebars, additional links, etc. It is for things that do not require their own template but need to pass information back to a layout based on the view being shown.
render/partial
render is for showing a given template associated with a route. render should be used for the main actions after a route is processed. partial is like a 'method' in a view. It can be reused and variables can be passed to change the output. You use partials in main templates to break up code and reuse pieces of views that otherwise might seem redundant.
capture_html/concat_content
This is usually used to create your own helpers that take blocks of content. For instance let's create a helper that takes a haml block and wraps it in a div. Usage is as follows:
# template.haml
# NOTE the equals so the content is returned
# and added to the view directly
= div_wrapper do
%h1 Some heading
%p This is now wrapped in a div
To implement this and use it in a template, you need to be able to 'capture' the haml passed into the block in order to process and then wrap a div around it. This is where capture_html comes in:
def div_wrapper(&block)
nested_content = capture_html(&block)
content_tag(:div, nested_content)
end
This will take the content and spit it out into the view wrapped in a div. Now, lets presume we want this helper to be more complex and so you want the use to be more like this:
# template.haml
# NOTE the dash so the content is not outputted directly
- div_wrapper do
%h1 Some heading
%p This is now wrapped in a div
but it also works in other helpers:
# some_helper.rb
def example(name)
div_wrapper { "<h1>Test</h1>" }
end
In order to properly print out the wrapped content from the helper in both a template AND straight ruby, we can use concat_content and check to see if we need to 'concat' the result to the template or simply return it.
def div_wrapper(&block)
nested_content = capture_html(&block)
tag_result = content_tag(:div, nested_content)
block_is_template?(block) ? concat_content(tag_result) : tag_result
end
I hope this works as a basic overview. The functions can overlap but generally it becomes clear when to use which based on specific context.