Class: Liquid::Context
- Inherits:
-
Object
- Object
- Liquid::Context
- Includes:
- ContextProfilingHook
- Defined in:
- lib/liquid/context.rb
Overview
Context keeps the variable stack and resolves variables, as well as keywords
context['variable'] = 'testing'
context['variable'] #=> 'testing'
context['true'] #=> true
context['10.2232'] #=> 10.2232
context.stack do
context['bob'] = 'bobsen'
end
context['bob'] #=> nil class Context
Instance Attribute Summary collapse
-
#environment ⇒ Object
Returns the value of attribute environment.
-
#environments ⇒ Object
readonly
Returns the value of attribute environments.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#exception_renderer ⇒ Object
Returns the value of attribute exception_renderer.
-
#global_filter ⇒ Object
Returns the value of attribute global_filter.
-
#partial ⇒ Object
Returns the value of attribute partial.
-
#registers ⇒ Object
readonly
Returns the value of attribute registers.
-
#resource_limits ⇒ Object
readonly
Returns the value of attribute resource_limits.
-
#scopes ⇒ Object
readonly
Returns the value of attribute scopes.
-
#static_environments ⇒ Object
readonly
Returns the value of attribute static_environments.
-
#static_registers ⇒ Object
readonly
Returns the value of attribute static_registers.
- #strainer ⇒ Object readonly
-
#strict_filters ⇒ Object
Returns the value of attribute strict_filters.
-
#strict_variables ⇒ Object
Returns the value of attribute strict_variables.
-
#template_name ⇒ Object
Returns the value of attribute template_name.
-
#warnings ⇒ Object
readonly
rubocop:enable Metrics/ParameterLists.
Attributes included from ContextProfilingHook
Class Method Summary collapse
-
.build(environment: Environment.default, environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block) ⇒ Object
rubocop:disable Metrics/ParameterLists.
Instance Method Summary collapse
-
#[](expression) ⇒ Object
Look up variable, either resolve directly after considering the name.
-
#[]=(key, value) ⇒ Object
Only allow String, Numeric, Hash, Array, Proc, Boolean or
Liquid::Drop
. -
#add_filters(filters) ⇒ Object
Adds filters to this context.
- #apply_global_filter(obj) ⇒ Object
- #clear_instance_assigns ⇒ Object
- #evaluate(object) ⇒ Object
-
#find_variable(key, raise_on_not_found: true) ⇒ Object
Fetches an object starting at the local scope and then moving up the hierachy.
- #handle_error(e, line_number = nil) ⇒ Object
-
#initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {}, environment = Environment.default) {|_self| ... } ⇒ Context
constructor
A new instance of Context.
-
#interrupt? ⇒ Boolean
are there any not handled interrupts?.
- #invoke(method, *args) ⇒ Object
- #key?(key) ⇒ Boolean
- #lookup_and_evaluate(obj, key, raise_on_not_found: true) ⇒ Object
-
#merge(new_scopes) ⇒ Object
Merge a hash of variables in the current local scope.
-
#new_isolated_subcontext ⇒ Object
Creates a new context inheriting resource limits, filters, environment etc., but with an isolated scope.
-
#pop ⇒ Object
Pop from the stack.
-
#pop_interrupt ⇒ Object
pop an interrupt from the stack.
-
#push(new_scope = {}) ⇒ Object
Push new local scope on the stack.
-
#push_interrupt(e) ⇒ Object
push an interrupt to the stack.
-
#stack(new_scope = {}) ⇒ Object
Pushes a new local scope on the stack, pops it at the end of the block.
- #tag_disabled?(tag_name) ⇒ Boolean
- #with_disabled_tags(tag_names) ⇒ Object
Constructor Details
#initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {}, environment = Environment.default) {|_self| ... } ⇒ Context
Returns a new instance of Context.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/liquid/context.rb', line 25 def initialize(environments = {}, outer_scope = {}, registers = {}, rethrow_errors = false, resource_limits = nil, static_environments = {}, environment = Environment.default) @environment = environment @environments = [environments] @environments.flatten! @static_environments = [static_environments].flatten(1).freeze @scopes = [outer_scope || {}] @registers = registers.is_a?(Registers) ? registers : Registers.new(registers) @errors = [] @partial = false @strict_variables = false @resource_limits = resource_limits || ResourceLimits.new(environment.default_resource_limits) @base_scope_depth = 0 @interrupts = [] @filters = [] @global_filter = nil @disabled_tags = {} @registers.static[:cached_partials] ||= {} @registers.static[:file_system] ||= environment.file_system @registers.static[:template_factory] ||= Liquid::TemplateFactory.new self.exception_renderer = environment.exception_renderer if rethrow_errors self.exception_renderer = Liquid::RAISE_EXCEPTION_LAMBDA end yield self if block_given? # Do this last, since it could result in this object being passed to a Proc in the environment squash_instance_assigns_with_environments end |
Instance Attribute Details
#environment ⇒ Object
Returns the value of attribute environment.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def environment @environment end |
#environments ⇒ Object (readonly)
Returns the value of attribute environments.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def environments @environments end |
#errors ⇒ Object
Returns the value of attribute errors.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def errors @errors end |
#exception_renderer ⇒ Object
Returns the value of attribute exception_renderer.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def exception_renderer @exception_renderer end |
#global_filter ⇒ Object
Returns the value of attribute global_filter.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def global_filter @global_filter end |
#partial ⇒ Object
Returns the value of attribute partial.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def partial @partial end |
#registers ⇒ Object (readonly)
Returns the value of attribute registers.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def registers @registers end |
#resource_limits ⇒ Object (readonly)
Returns the value of attribute resource_limits.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def resource_limits @resource_limits end |
#scopes ⇒ Object (readonly)
Returns the value of attribute scopes.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def scopes @scopes end |
#static_environments ⇒ Object (readonly)
Returns the value of attribute static_environments.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def static_environments @static_environments end |
#static_registers ⇒ Object (readonly)
Returns the value of attribute static_registers.
17 18 19 |
# File 'lib/liquid/context.rb', line 17 def static_registers @static_registers end |
#strainer ⇒ Object
63 64 65 |
# File 'lib/liquid/context.rb', line 63 def strainer @strainer ||= @environment.create_strainer(self, @filters) end |
#strict_filters ⇒ Object
Returns the value of attribute strict_filters.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def strict_filters @strict_filters end |
#strict_variables ⇒ Object
Returns the value of attribute strict_variables.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def strict_variables @strict_variables end |
#template_name ⇒ Object
Returns the value of attribute template_name.
18 19 20 |
# File 'lib/liquid/context.rb', line 18 def template_name @template_name end |
#warnings ⇒ Object
rubocop:enable Metrics/ParameterLists
59 60 61 |
# File 'lib/liquid/context.rb', line 59 def warnings @warnings ||= [] end |
Class Method Details
.build(environment: Environment.default, environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block) ⇒ Object
rubocop:disable Metrics/ParameterLists
21 22 23 |
# File 'lib/liquid/context.rb', line 21 def self.build(environment: Environment.default, environments: {}, outer_scope: {}, registers: {}, rethrow_errors: false, resource_limits: nil, static_environments: {}, &block) new(environments, outer_scope, registers, rethrow_errors, resource_limits, static_environments, environment, &block) end |
Instance Method Details
#[](expression) ⇒ Object
Look up variable, either resolve directly after considering the name. We can directly handle Strings, digits, floats and booleans (true,false). If no match is made we lookup the variable in the current scope and later move up to the parent blocks to see if we can resolve the variable somewhere up the tree. Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions
Example:
products == empty #=> products.empty?
178 179 180 |
# File 'lib/liquid/context.rb', line 178 def [](expression) evaluate(Expression.parse(expression)) end |
#[]=(key, value) ⇒ Object
Only allow String, Numeric, Hash, Array, Proc, Boolean or Liquid::Drop
166 167 168 |
# File 'lib/liquid/context.rb', line 166 def []=(key, value) @scopes[0][key] = value end |
#add_filters(filters) ⇒ Object
Adds filters to this context.
Note that this does not register the filters with the main Template object. see Template.register_filter
for that
71 72 73 74 75 |
# File 'lib/liquid/context.rb', line 71 def add_filters(filters) filters = [filters].flatten.compact @filters += filters @strainer = nil end |
#apply_global_filter(obj) ⇒ Object
77 78 79 |
# File 'lib/liquid/context.rb', line 77 def apply_global_filter(obj) global_filter.nil? ? obj : global_filter.call(obj) end |
#clear_instance_assigns ⇒ Object
161 162 163 |
# File 'lib/liquid/context.rb', line 161 def clear_instance_assigns @scopes[0] = {} end |
#evaluate(object) ⇒ Object
186 187 188 |
# File 'lib/liquid/context.rb', line 186 def evaluate(object) object.respond_to?(:evaluate) ? object.evaluate(self) : object end |
#find_variable(key, raise_on_not_found: true) ⇒ Object
Fetches an object starting at the local scope and then moving up the hierachy
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/liquid/context.rb', line 191 def find_variable(key, raise_on_not_found: true) # This was changed from find() to find_index() because this is a very hot # path and find_index() is optimized in MRI to reduce object allocation index = @scopes.find_index { |s| s.key?(key) } variable = if index lookup_and_evaluate(@scopes[index], key, raise_on_not_found: raise_on_not_found) else try_variable_find_in_environments(key, raise_on_not_found: raise_on_not_found) end # update variable's context before invoking #to_liquid variable.context = self if variable.respond_to?(:context=) liquid_variable = variable.to_liquid liquid_variable.context = self if variable != liquid_variable && liquid_variable.respond_to?(:context=) liquid_variable end |
#handle_error(e, line_number = nil) ⇒ Object
96 97 98 99 100 101 102 |
# File 'lib/liquid/context.rb', line 96 def handle_error(e, line_number = nil) e = internal_error unless e.is_a?(Liquid::Error) e.template_name ||= template_name e.line_number ||= line_number errors.push(e) exception_renderer.call(e).to_s end |
#interrupt? ⇒ Boolean
are there any not handled interrupts?
82 83 84 |
# File 'lib/liquid/context.rb', line 82 def interrupt? !@interrupts.empty? end |
#invoke(method, *args) ⇒ Object
104 105 106 |
# File 'lib/liquid/context.rb', line 104 def invoke(method, *args) strainer.invoke(method, *args).to_liquid end |
#key?(key) ⇒ Boolean
182 183 184 |
# File 'lib/liquid/context.rb', line 182 def key?(key) self[key] != nil end |
#lookup_and_evaluate(obj, key, raise_on_not_found: true) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/liquid/context.rb', line 212 def lookup_and_evaluate(obj, key, raise_on_not_found: true) if @strict_variables && raise_on_not_found && obj.respond_to?(:key?) && !obj.key?(key) raise Liquid::UndefinedVariable, "undefined variable #{key}" end value = obj[key] if value.is_a?(Proc) && obj.respond_to?(:[]=) obj[key] = value.arity == 0 ? value.call : value.call(self) else value end end |
#merge(new_scopes) ⇒ Object
Merge a hash of variables in the current local scope
115 116 117 |
# File 'lib/liquid/context.rb', line 115 def merge(new_scopes) @scopes[0].merge!(new_scopes) end |
#new_isolated_subcontext ⇒ Object
Creates a new context inheriting resource limits, filters, environment etc., but with an isolated scope.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/liquid/context.rb', line 142 def new_isolated_subcontext check_overflow self.class.build( environment: @environment, resource_limits: resource_limits, static_environments: static_environments, registers: Registers.new(registers), ).tap do |subcontext| subcontext.base_scope_depth = base_scope_depth + 1 subcontext.exception_renderer = exception_renderer subcontext.filters = @filters subcontext.strainer = nil subcontext.errors = errors subcontext.warnings = warnings subcontext. = @disabled_tags end end |
#pop ⇒ Object
Pop from the stack. use Context#stack
instead
120 121 122 123 |
# File 'lib/liquid/context.rb', line 120 def pop raise ContextError if @scopes.size == 1 @scopes.shift end |
#pop_interrupt ⇒ Object
pop an interrupt from the stack
92 93 94 |
# File 'lib/liquid/context.rb', line 92 def pop_interrupt @interrupts.pop end |
#push(new_scope = {}) ⇒ Object
Push new local scope on the stack. use Context#stack
instead
109 110 111 112 |
# File 'lib/liquid/context.rb', line 109 def push(new_scope = {}) @scopes.unshift(new_scope) check_overflow end |
#push_interrupt(e) ⇒ Object
push an interrupt to the stack. this interrupt is considered not handled.
87 88 89 |
# File 'lib/liquid/context.rb', line 87 def push_interrupt(e) @interrupts.push(e) end |
#stack(new_scope = {}) ⇒ Object
Pushes a new local scope on the stack, pops it at the end of the block
Example:
context.stack do
context['var'] = 'hi'
end
context['var'] #=> nil
133 134 135 136 137 138 |
# File 'lib/liquid/context.rb', line 133 def stack(new_scope = {}) push(new_scope) yield ensure pop end |
#tag_disabled?(tag_name) ⇒ Boolean
237 238 239 |
# File 'lib/liquid/context.rb', line 237 def tag_disabled?(tag_name) @disabled_tags.fetch(tag_name, 0) > 0 end |
#with_disabled_tags(tag_names) ⇒ Object
226 227 228 229 230 231 232 233 234 235 |
# File 'lib/liquid/context.rb', line 226 def (tag_names) tag_names.each do |name| @disabled_tags[name] = @disabled_tags.fetch(name, 0) + 1 end yield ensure tag_names.each do |name| @disabled_tags[name] -= 1 end end |