mirror of
https://github.com/Fishwaldo/huginn.git
synced 2025-03-15 19:31:26 +00:00
Add as_object Liquid filter
The `as_object` returns the received data/object as is without casting it to a string like liquid normally does. It can be used as a JSONPath replacement or to emit result of a Liquid filter chain as an array. `catch` and `throw` needs to be used to break out of Liquid render chain. Liquid aggregates the output of every expression an array and [joins](https://github.com/Shopify/liquid/blob/v3.0.6/lib/liquid/block.rb#L147) it together that join makes it impossible to get anything else than a string out of a Liquid template.
This commit is contained in:
parent
4469213425
commit
d2cbd04ac8
5 changed files with 96 additions and 9 deletions
|
@ -18,6 +18,11 @@ module LiquidDroppable
|
|||
yield [name, __send__(name)]
|
||||
}
|
||||
end
|
||||
|
||||
def as_json
|
||||
return {} unless defined?(self.class::METHODS)
|
||||
Hash[self.class::METHODS.map { |m| [m, send(m).as_json]}]
|
||||
end
|
||||
end
|
||||
|
||||
included do
|
||||
|
@ -33,12 +38,10 @@ module LiquidDroppable
|
|||
self.class::Drop.new(self)
|
||||
end
|
||||
|
||||
class MatchDataDrop < Liquid::Drop
|
||||
def initialize(object)
|
||||
@object = object
|
||||
end
|
||||
class MatchDataDrop < Drop
|
||||
METHODS = %w[pre_match post_match names size]
|
||||
|
||||
%w[pre_match post_match names size].each { |attr|
|
||||
METHODS.each { |attr|
|
||||
define_method(attr) {
|
||||
@object.__send__(attr)
|
||||
}
|
||||
|
@ -64,7 +67,9 @@ module LiquidDroppable
|
|||
require 'uri'
|
||||
|
||||
class URIDrop < Drop
|
||||
URI::Generic::COMPONENT.each { |attr|
|
||||
METHODS = URI::Generic::COMPONENT
|
||||
|
||||
METHODS.each { |attr|
|
||||
define_method(attr) {
|
||||
@object.__send__(attr)
|
||||
}
|
||||
|
|
|
@ -92,7 +92,9 @@ module LiquidInterpolatable
|
|||
|
||||
def interpolate_string(string, self_object = nil)
|
||||
interpolate_with(self_object) do
|
||||
Liquid::Template.parse(string).render!(interpolation_context)
|
||||
catch :as_object do
|
||||
Liquid::Template.parse(string).render!(interpolation_context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -225,6 +227,25 @@ module LiquidInterpolatable
|
|||
JSON.dump(input)
|
||||
end
|
||||
|
||||
# Returns a Ruby object
|
||||
#
|
||||
# It can be used as a JSONPath replacement for Agents that only support Liquid:
|
||||
#
|
||||
# Event: {"something": {"nested": {"data": 1}}}
|
||||
# Liquid: {{something.nested | as_object}}
|
||||
# Returns: {"data": 1}
|
||||
#
|
||||
# Splitting up a string with Liquid filters and return the Array:
|
||||
#
|
||||
# Event: {"data": "A,B,C"}}
|
||||
# Liquid: {{data | split: ',' | as_object}}
|
||||
# Returns: ['A', 'B', 'C']
|
||||
#
|
||||
# as_object ALWAYS has be the last filter in a Liquid expression!
|
||||
def as_object(object)
|
||||
throw :as_object, object.as_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logger
|
||||
|
|
|
@ -443,7 +443,7 @@ class AgentDrop
|
|||
@object.short_type
|
||||
end
|
||||
|
||||
[
|
||||
METHODS = [
|
||||
:name,
|
||||
:type,
|
||||
:options,
|
||||
|
@ -456,7 +456,9 @@ class AgentDrop
|
|||
:disabled,
|
||||
:keep_events_for,
|
||||
:propagate_immediately,
|
||||
].each { |attr|
|
||||
]
|
||||
|
||||
METHODS.each { |attr|
|
||||
define_method(attr) {
|
||||
@object.__send__(attr)
|
||||
} unless method_defined?(attr)
|
||||
|
|
|
@ -119,4 +119,8 @@ class EventDrop
|
|||
def _location_
|
||||
@object.location
|
||||
end
|
||||
|
||||
def as_json
|
||||
{location: _location_.as_json, agent: @object.agent.to_liquid.as_json, payload: @payload.as_json, created_at: created_at.as_json}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -264,4 +264,59 @@ describe LiquidInterpolatable::Filters do
|
|||
expect(agent.interpolated['cleaned']).to eq('FOObar ZOObar')
|
||||
end
|
||||
end
|
||||
|
||||
context 'as_object' do
|
||||
let(:agent) { Agents::InterpolatableAgent.new(name: "test") }
|
||||
|
||||
it 'returns an array that was splitted in liquid tags' do
|
||||
agent.interpolation_context['something'] = 'test,string,abc'
|
||||
agent.options['array'] = "{{something | split: ',' | as_object}}"
|
||||
expect(agent.interpolated['array']).to eq(['test', 'string', 'abc'])
|
||||
end
|
||||
|
||||
it 'returns an object that was not modified in liquid' do
|
||||
agent.interpolation_context['something'] = {'nested' => {'abc' => 'test'}}
|
||||
agent.options['object'] = "{{something.nested | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq({"abc" => 'test'})
|
||||
end
|
||||
|
||||
context 'as_json' do
|
||||
def ensure_safety(obj)
|
||||
JSON.parse(JSON.dump(obj))
|
||||
end
|
||||
|
||||
it 'it converts "complex" objects' do
|
||||
agent.interpolation_context['something'] = {'nested' => Service.new}
|
||||
agent.options['object'] = "{{something | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq({'nested'=> ensure_safety(Service.new.as_json)})
|
||||
end
|
||||
|
||||
it 'works with AgentDrops' do
|
||||
agent.interpolation_context['something'] = agent
|
||||
agent.options['object'] = "{{something | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq(ensure_safety(agent.to_liquid.as_json.stringify_keys))
|
||||
end
|
||||
|
||||
it 'works with EventDrops' do
|
||||
event = Event.new(payload: {some: 'payload'}, agent: agent, created_at: Time.now)
|
||||
agent.interpolation_context['something'] = event
|
||||
agent.options['object'] = "{{something | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq(ensure_safety(event.to_liquid.as_json.stringify_keys))
|
||||
end
|
||||
|
||||
it 'works with MatchDataDrops' do
|
||||
match = "test string".match(/\A(?<word>\w+)\s(.+?)\z/)
|
||||
agent.interpolation_context['something'] = match
|
||||
agent.options['object'] = "{{something | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq(ensure_safety(match.to_liquid.as_json.stringify_keys))
|
||||
end
|
||||
|
||||
it 'works with URIDrops' do
|
||||
uri = URI.parse("https://google.com?q=test")
|
||||
agent.interpolation_context['something'] = uri
|
||||
agent.options['object'] = "{{something | as_object}}"
|
||||
expect(agent.interpolated['object']).to eq(ensure_safety(uri.to_liquid.as_json.stringify_keys))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue