Last active
September 17, 2016 06:06
-
-
Save rescribet/2c5d268f1f161c7be5c9 to your computer and use it in GitHub Desktop.
A Turbolinks 5 drop-in for when permanent partials can't be lazy loaded (no-script requirement).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A turbolinks 5 drop-in for when permanent partials can't be lazy loaded (no-script requirement). | |
# | |
# Whenever a static partial is really heavy, it is undesirable to render it on every/many request(s), so this render drop-in only renders the partial's content if the `Turbolinks-Referrer` header is *not* present. | |
# | |
# Usage: | |
# ```ruby | |
# render partial: 'navbar', permanent: true | |
# # => <div id="turbolinks_navbar" data-turbolinks-permanent="true">[Always rendered]</div> # Behaviour as described in the RailsConf '15 keynote, where HTML might be lazy loaded via JS | |
# | |
# render partial: 'navbar', permanent: 'navbar' | |
# # => <div id="navbar" data-turbolinks-permanent="true">[Always rendered]</div> | |
# | |
# render partial: 'navbar', permanent: {id: 'unrelated_id'} | |
# # => <div id="unrelated_id" data-turbolinks-permanent="true">[Always rendered]</div> | |
# | |
# render partial: 'navbar', permanent: {turbolinks_render: false} | |
# # => <div id="turbolinks_navbar" data-turbolinks-permanent="true">[Never rendered (server side)]</div> | |
# | |
# render partial: 'navbar', permanent: {prerender: true, turbolinks_render: false} | |
# # => <div id="turbolinks_navbar" data-turbolinks-permanent="true">[Rendered on only on non TL requests]</div> | |
# ``` | |
module ActionView | |
class Base | |
# Turbolinks that doesn't rerenders permanent partials on turbolink requests. | |
# @overload turbolinks_render(options) | |
# @param [Hash] options | |
# @option options [String] :permanent The ID of the partial | |
# @option options [Hash] :permanent An options hash | |
# @option permanent [Hash] :id The id of the wrapper element | |
# @option permanent [Hash] :tag (:div) The element type of the wrapper tag | |
def turbolinks_render(*args, &block) | |
options = normalize_tl_options(*args) | |
return normal_render(*args, &block) unless options | |
if tl_should_render_for(options) | |
inner_content = normal_render *args, &block | |
end | |
if options.fetch(:use_wrapper, true) | |
content_tag options.fetch(:tag, :div), | |
inner_content, | |
options_for_renderer(options) | |
else | |
inner_content | |
end | |
end | |
alias_method :normal_render, :render | |
alias_method :render, :turbolinks_render | |
private | |
def normalize_tl_options(*args) | |
render_options = args.first | |
options = render_options.is_a?(Hash) && render_options.fetch(:permanent, nil) | |
return nil unless options.present? | |
if options.is_a?(Hash) | |
options.presence | |
else | |
{id: partial_tl_id(*args)} | |
end | |
end | |
# Defines the options that are passed to the turbolinks wrapper container | |
def options_for_renderer(options) | |
{ | |
id: options.fetch(:id), | |
data: {turbolinks_permanent: true} | |
}.merge(options.fetch(:html_options, {})) | |
end | |
# Generates the partial's wrapper id based on | |
# @return [String] id The id passed as an option, or one based on the partial name | |
def partial_tl_id(*args) | |
permanent = args.first.fetch(:permanent, nil) | |
return nil if permanent.blank? | |
if permanent.is_a?(String) | |
permanent | |
elsif permanent.is_a?(Hash) && permanent.fetch(:id).present? | |
permanent.fetch(:id) | |
elsif permanent && args.first.fetch(:partial).present? | |
"turbolinks_#{args.first.fetch(:partial)}" | |
end | |
end | |
# Determines whether Turbolinks should render the partial's body | |
def tl_should_render_for(options) | |
if request.headers['Turbolinks-Referrer'].present? | |
options.fetch(:turbolinks_render, true) | |
else | |
options.fetch(:prerender, true) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment