123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- module LiquidInterpolatable
- extend ActiveSupport::Concern
- included do
- validate :validate_interpolation
- end
- def valid?(context = nil)
- super
- rescue Liquid::Error
- errors.empty?
- end
- def validate_interpolation
- interpolated
- rescue Liquid::Error => e
- errors.add(:options, "has an error with Liquid templating: #{e.message}")
- false
- end
- # Return the current interpolation context. Use this in your Agent
- # class to manipulate interpolation context for user.
- #
- # For example, to provide local variables:
- #
- # # Create a new scope to define variables in:
- # interpolation_context.stack {
- # interpolation_context['_something_'] = 42
- # # And user can say "{{_something_}}" in their options.
- # value = interpolated['some_key']
- # }
- #
- def interpolation_context
- @interpolation_context ||= Context.new(self)
- end
- # Take the given object as "self" in the current interpolation
- # context while running a given block.
- #
- # The most typical use case for this is to evaluate options for each
- # received event like this:
- #
- # def receive(incoming_events)
- # incoming_events.each do |event|
- # interpolate_with(event) do
- # # Handle each event based on "interpolated" options.
- # end
- # end
- # end
- def interpolate_with(self_object)
- case self_object
- when nil
- yield
- else
- context = interpolation_context
- begin
- context.environments.unshift(self_object.to_liquid)
- yield
- ensure
- context.environments.shift
- end
- end
- end
- def interpolate_options(options, self_object = nil)
- interpolate_with(self_object) do
- case options
- when String
- interpolate_string(options)
- when ActiveSupport::HashWithIndifferentAccess, Hash
- options.each_with_object(ActiveSupport::HashWithIndifferentAccess.new) { |(key, value), memo|
- memo[key] = interpolate_options(value)
- }
- when Array
- options.map { |value| interpolate_options(value) }
- else
- options
- end
- end
- end
- def interpolated(self_object = nil)
- interpolate_with(self_object) do
- (@interpolated_cache ||= {})[[options, interpolation_context]] ||=
- interpolate_options(options)
- end
- end
- def interpolate_string(string, self_object = nil)
- interpolate_with(self_object) do
- Liquid::Template.parse(string).render!(interpolation_context)
- end
- end
- class Context < Liquid::Context
- def initialize(agent)
- super({}, {}, { agent: agent }, true)
- end
- def hash
- [@environments, @scopes, @registers].hash
- end
- def eql?(other)
- other.environments == @environments &&
- other.scopes == @scopes &&
- other.registers == @registers
- end
- end
- require 'uri'
- module Filters
- # Percent encoding for URI conforming to RFC 3986.
- # Ref: http://tools.ietf.org/html/rfc3986#page-12
- def uri_escape(string)
- CGI.escape(string) rescue string
- end
- # Parse an input into a URI object, optionally resolving it
- # against a base URI if given.
- #
- # A URI object will have the following properties: scheme,
- # userinfo, host, port, registry, path, opaque, query, and
- # fragment.
- def to_uri(uri, base_uri = nil)
- if base_uri
- URI(base_uri) + uri.to_s
- else
- URI(uri.to_s)
- end
- rescue URI::Error
- nil
- end
- # Escape a string for use in XPath expression
- def to_xpath(string)
- subs = string.to_s.scan(/\G(?:\A\z|[^"]+|[^']+)/).map { |x|
- case x
- when /"/
- %Q{'#{x}'}
- else
- %Q{"#{x}"}
- end
- }
- if subs.size == 1
- subs.first
- else
- 'concat(' << subs.join(', ') << ')'
- end
- end
- end
- Liquid::Template.register_filter(LiquidInterpolatable::Filters)
- module Tags
- class Credential < Liquid::Tag
- def initialize(tag_name, name, tokens)
- super
- @credential_name = name.strip
- end
- def render(context)
- credential = context.registers[:agent].credential(@credential_name)
- raise "No user credential named '#{@credential_name}' defined" if credential.nil?
- credential
- end
- end
- end
- Liquid::Template.register_tag('credential', LiquidInterpolatable::Tags::Credential)
- end
|