Merge pull request #1716 from dsander/liquid-as-object

Add as_object Liquid filter
This commit is contained in:
Dominik Sander 2016-10-14 12:53:24 +02:00 committed by GitHub
commit 005f01a4ad
5 changed files with 96 additions and 9 deletions

View file

@ -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)
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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