Extensions are used to add functionality to Twig. The most common elements to add through an extension are functions, filters, tests, and globals.
To create an extension, extend the Twig::Extension::Base class, which provides helpful shortcuts
for building extensions and implements empty methods for extension points you may not need.
This base class handles common boilerplate code so you can focus on implementing just the
functionality you need.
All the callables can be setup as class methods, instance methods, or procs
class UpperExtension < Twig::Extension::Base
def functions
[
# The 'static' helper creates a callable reference to a class method
# It's equivalent to self.class.method(:upper) but more concise
Twig::TwigFunction.new('upper', static(:upper)),
]
end
def self.upper(value)
value.upcase
end
endclass UpperExtension < Twig::Extension::Base
def functions
[
Twig::TwigFunction.new('upper', method(:upper)),
]
end
def upper(value)
value.upcase
end
endclass UpperExtension < Twig::Extension::Base
def functions
[
Twig::TwigFunction.new('upper', ->(value) { value.upcase }),
]
end
endAfter creating an extension, you need to register it with the Twig environment. There are several ways to do this:
# Create your environment
environment = Twig::Environment.new(loader)
# Add your extension
environment.add_extension(UpperExtension.new)In a Rails application, you can register extensions in an initializer:
# config/initializers/twig.rb
Rails.application.config.to_prepare do
Twig.environment.add_extension(UpperExtension.new)
# Add other extensions as needed
endOnce registered, you can use your extension's functionality in templates:
{{ upper("hello world") }} {# HELLO WORLD #}Filters work the same way as functions do above in the previous section, just use TwigFilter instead:
class UpperExtension < Twig::Extension::Base
def filters
[
Twig::TwigFilter.new('upper', ->(value) { value.upcase }),
]
end
end{{ "hello world"|upper }} {# HELLO WORLD #}Tests also work as functions and filters do above
class UpperExtension < Twig::Extension::Base
def tests
[
Twig::TwigTest.new('upper', ->(value) { value.match?(/^[A-Z]+$/) }),
]
end
end{{ "hello" is upper ? 'yes' : 'no' }} {# no #}
{{ "HELLO" is upper ? 'yes' : 'no' }} {# yes #}Globals allow you to provide variables that are accessible in any template without needing to pass them explicitly in the context. This is useful for application-wide configuration values, constants, or commonly used data.
class AppExtension < Twig::Extension::Base
def globals
{
# Static configuration values
ga_tracking: 'UA-xxxxx-x',
app_version: '1.2.3',
# Dynamic values
current_year: Time.now.year,
is_production: Rails.env.production?,
# Helper methods/lambdas
format_date: ->(date) { date.strftime('%B %d, %Y') }
}
end
endOnce registered, these globals can be used in any template:
<footer>
© {{ current_year }} My Company | Version {{ app_version }}
{% if is_production %}
<!-- Analytics code: {{ ga_tracking }} -->
{% endif %}
<!-- Using a lambda global -->
Last updated: {{ format_date.call(page.updated_at) }}
</footer>Globals are especially useful for values that would otherwise need to be included in every template render call.