@@ -7,28 +7,31 @@ module Agents |
||
| 7 | 7 |
For example if you have an event like |
| 8 | 8 |
|
| 9 | 9 |
{
|
| 10 |
- :content => {
|
|
| 11 |
- :text => "Lorem ipsum dolor sit amet" |
|
| 10 |
+ :high => {
|
|
| 11 |
+ :celsius => "18", |
|
| 12 |
+ :fahreinheit => "64" |
|
| 12 | 13 |
}, |
| 13 |
- :fields => "consectetur adipisicing elit", |
|
| 14 |
+ :conditions => "Rain showers", |
|
| 14 | 15 |
:data => "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." |
| 15 | 16 |
} |
| 16 | 17 |
|
| 17 | 18 |
|
| 18 |
- And other agents which are receiving this event, say, Twilio Agent expects `message` key , and Digest Email Agent which expects a `subject` key, then you can reformat this event by filling `Options` in the following way. |
|
| 19 |
+ And other agents which are receiving this event, say, Twilio Agent expects `message` key , and Digest Email Agent which expects a `subject` key, then you can reformat this event by filling `Instructions` in the following way. |
|
| 19 | 20 |
|
| 20 |
- message => $.content.text |
|
| 21 |
- subject => $.fields |
|
| 21 |
+ message => "Today's conditions look like <$.conditions> and high temperaure is going to be <$.high.celsius> degree Celsius."" |
|
| 22 |
+ subject => "$.data" |
|
| 22 | 23 |
|
| 23 |
- Values must be provided in JSONPath. You can add as many keys as you like. |
|
| 24 |
+ JSONPaths must be between < and > . Make sure you dont use this symbols anywhere else. You can add as many keys as you like. |
|
| 24 | 25 |
|
| 25 |
- Then, event generated by Event Formatting Agent will be like |
|
| 26 |
+ Event generated by Event Formatting Agent will be like |
|
| 26 | 27 |
|
| 27 | 28 |
{
|
| 28 |
- :message => "Lorem ipsum dolor sit amet" |
|
| 29 |
- :subject => "consectetur adipisicing elit" |
|
| 29 |
+ :message => "Today's conditions look like Rain showers and high temperaure is going to be 18 degree Celsius" |
|
| 30 |
+ :subject => "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." |
|
| 30 | 31 |
} |
| 31 | 32 |
|
| 33 |
+ `Mode` can only be `merge` or `clean`. If you want to retain original contents of events and only add add new keys, then use `merge` mode else use `clean` mode. |
|
| 34 |
+ |
|
| 32 | 35 |
MD |
| 33 | 36 |
|
| 34 | 37 |
event_description <<-MD |
@@ -36,9 +39,18 @@ module Agents |
||
| 36 | 39 |
User defined |
| 37 | 40 |
MD |
| 38 | 41 |
|
| 42 |
+ def validate_options |
|
| 43 |
+ errors.add(:base,"instructions,mode,skip_agent and skip_created_at , all need to be present.") unless options[:instructions].present? and options[:mode].present? and options[:skip_agent].present? and options[:skip_created_at].present? |
|
| 44 |
+ end |
|
| 45 |
+ |
|
| 39 | 46 |
def default_options |
| 40 | 47 |
{
|
| 41 |
- :message => "$.data.fields.content" |
|
| 48 |
+ :instructions => {
|
|
| 49 |
+ :message => "You received a text <$.text> from <$.fields.from>", |
|
| 50 |
+ :content => "Looks like the weather is going to be <$.fields.weather>"}, |
|
| 51 |
+ :mode => "clean", |
|
| 52 |
+ :skip_agent => "false", |
|
| 53 |
+ :skip_created_at => "false" |
|
| 42 | 54 |
} |
| 43 | 55 |
end |
| 44 | 56 |
|
@@ -46,14 +58,16 @@ module Agents |
||
| 46 | 58 |
true |
| 47 | 59 |
end |
| 48 | 60 |
|
| 61 |
+ def value_constructor(value,payload) |
|
| 62 |
+ value.gsub(/<[^>]+>/).each {|jsonpath| Utils.values_at(payload,jsonpath[1..-2]).first.to_s}
|
|
| 63 |
+ end |
|
| 64 |
+ |
|
| 49 | 65 |
def receive(incoming_events) |
| 50 | 66 |
incoming_events.each do |event| |
| 51 |
- formatted_event = {}
|
|
| 52 |
- options.each_pair do |key,value| |
|
| 53 |
- formatted_event[key] = Utils.values_at event.payload,value |
|
| 54 |
- end |
|
| 55 |
- formatted_event[:agent] = Agent.find(event.agent_id).type.slice! 8..-1 |
|
| 56 |
- formatted_event[:created_at] = event.created_at |
|
| 67 |
+ formatted_event = options[:mode].to_s == "merge" ? event.payload : {}
|
|
| 68 |
+ options[:instructions].each_pair {|key,value| formatted_event[key] = value_constructor value, event.payload}
|
|
| 69 |
+ formatted_event[:agent] = Agent.find(event.agent_id).type.slice!(8..-1) unless options[:skip_agent].to_s == "true" |
|
| 70 |
+ formatted_event[:created_at] = event.created_at unless options[:skip_created_at].to_s == "true" |
|
| 57 | 71 |
create_event :payload => formatted_event |
| 58 | 72 |
end |
| 59 | 73 |
end |
@@ -44,7 +44,8 @@ module Agents |
||
| 44 | 44 |
create_event :payload => {:content => content,
|
| 45 | 45 |
:valence => sent_values[0], |
| 46 | 46 |
:arousal => sent_values[1], |
| 47 |
- :dominance => sent_values[2]} |
|
| 47 |
+ :dominance => sent_values[2], |
|
| 48 |
+ :original_event => event.payload} |
|
| 48 | 49 |
end |
| 49 | 50 |
end |
| 50 | 51 |
end |
@@ -0,0 +1,119 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+describe Agents::EventFormattingAgent do |
|
| 4 |
+ before do |
|
| 5 |
+ @valid_params = {
|
|
| 6 |
+ :name => "somename", |
|
| 7 |
+ :options => {
|
|
| 8 |
+ :instructions => {
|
|
| 9 |
+ :message => "Received <$.content.text.*> from <$.content.name> .", |
|
| 10 |
+ :subject => "Weather looks like <$.conditions>" |
|
| 11 |
+ }, |
|
| 12 |
+ :mode => "clean", |
|
| 13 |
+ :skip_agent => "false", |
|
| 14 |
+ :skip_created_at => "false" |
|
| 15 |
+ } |
|
| 16 |
+ } |
|
| 17 |
+ @checker = Agents::EventFormattingAgent.new(@valid_params) |
|
| 18 |
+ @checker.user = users(:jane) |
|
| 19 |
+ @checker.save! |
|
| 20 |
+ |
|
| 21 |
+ @event = Event.new |
|
| 22 |
+ @event.agent = agents(:jane_weather_agent) |
|
| 23 |
+ @event.created_at = Time.now |
|
| 24 |
+ @event.payload = {
|
|
| 25 |
+ :content => {
|
|
| 26 |
+ :text => "Some Lorem Ipsum", |
|
| 27 |
+ :name => "somevalue" |
|
| 28 |
+ }, |
|
| 29 |
+ :conditions => "someothervalue" |
|
| 30 |
+ } |
|
| 31 |
+ end |
|
| 32 |
+ |
|
| 33 |
+ describe "#receive" do |
|
| 34 |
+ it "checks if clean mode is working fine" do |
|
| 35 |
+ @checker.receive([@event]) |
|
| 36 |
+ Event.last.payload[:content].should == nil |
|
| 37 |
+ end |
|
| 38 |
+ |
|
| 39 |
+ it "checks if merge mode is working fine" do |
|
| 40 |
+ @checker.options[:mode] = "merge" |
|
| 41 |
+ @checker.receive([@event]) |
|
| 42 |
+ Event.last.payload[:content].should_not == nil |
|
| 43 |
+ end |
|
| 44 |
+ |
|
| 45 |
+ it "checks if skip_agent is working fine" do |
|
| 46 |
+ @checker.receive([@event]) |
|
| 47 |
+ Event.last.payload[:agent].should == "WeatherAgent" |
|
| 48 |
+ @checker.options[:skip_agent] = "true" |
|
| 49 |
+ @checker.receive([@event]) |
|
| 50 |
+ Event.last.payload[:agent].should == nil |
|
| 51 |
+ end |
|
| 52 |
+ |
|
| 53 |
+ it "checks if skip_created_at is working fine" do |
|
| 54 |
+ @checker.receive([@event]) |
|
| 55 |
+ Event.last.payload[:created_at].should_not == nil |
|
| 56 |
+ @checker.options[:skip_created_at] = "true" |
|
| 57 |
+ @checker.receive([@event]) |
|
| 58 |
+ Event.last.payload[:created_at].should == nil |
|
| 59 |
+ end |
|
| 60 |
+ |
|
| 61 |
+ it "checks if instructions are working fine" do |
|
| 62 |
+ @checker.receive([@event]) |
|
| 63 |
+ Event.last.payload[:message].should == "Received Some Lorem Ipsum from somevalue ." |
|
| 64 |
+ Event.last.payload[:subject].should == "Weather looks like someothervalue" |
|
| 65 |
+ end |
|
| 66 |
+ |
|
| 67 |
+ it "checks if it can handle multiple events" do |
|
| 68 |
+ event1 = Event.new |
|
| 69 |
+ event1.agent = agents(:bob_weather_agent) |
|
| 70 |
+ event1.payload = {
|
|
| 71 |
+ :content => {
|
|
| 72 |
+ :text => "Some Lorem Ipsum", |
|
| 73 |
+ :name => "somevalue" |
|
| 74 |
+ }, |
|
| 75 |
+ :conditions => "someothervalue" |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ event2 = Event.new |
|
| 79 |
+ event2.agent = agents(:bob_weather_agent) |
|
| 80 |
+ event2.payload = {
|
|
| 81 |
+ :content => {
|
|
| 82 |
+ :text => "Some Lorem Ipsum", |
|
| 83 |
+ :name => "somevalue" |
|
| 84 |
+ }, |
|
| 85 |
+ :conditions => "someothervalue" |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ lambda {
|
|
| 89 |
+ @checker.receive([event2,event1]) |
|
| 90 |
+ }.should change { Event.count }.by(2)
|
|
| 91 |
+ end |
|
| 92 |
+ end |
|
| 93 |
+ |
|
| 94 |
+ describe "validation" do |
|
| 95 |
+ before do |
|
| 96 |
+ @checker.should be_valid |
|
| 97 |
+ end |
|
| 98 |
+ |
|
| 99 |
+ it "should validate presence of instructions" do |
|
| 100 |
+ @checker.options[:instructions] = "" |
|
| 101 |
+ @checker.should_not be_valid |
|
| 102 |
+ end |
|
| 103 |
+ |
|
| 104 |
+ it "should validate presence of mode" do |
|
| 105 |
+ @checker.options[:mode] = "" |
|
| 106 |
+ @checker.should_not be_valid |
|
| 107 |
+ end |
|
| 108 |
+ |
|
| 109 |
+ it "should validate presence of skip_agent" do |
|
| 110 |
+ @checker.options[:skip_agent] = "" |
|
| 111 |
+ @checker.should_not be_valid |
|
| 112 |
+ end |
|
| 113 |
+ |
|
| 114 |
+ it "should validate presence of skip_created_at" do |
|
| 115 |
+ @checker.options[:skip_created_at] = "" |
|
| 116 |
+ @checker.should_not be_valid |
|
| 117 |
+ end |
|
| 118 |
+ end |
|
| 119 |
+end |
@@ -0,0 +1,76 @@ |
||
| 1 |
+require 'spec_helper' |
|
| 2 |
+ |
|
| 3 |
+describe Agents::SentimentAgent do |
|
| 4 |
+ before do |
|
| 5 |
+ @valid_params = {
|
|
| 6 |
+ :name => "somename", |
|
| 7 |
+ :options => {
|
|
| 8 |
+ :content => "$.message", |
|
| 9 |
+ :expected_receive_period_in_days => 1 |
|
| 10 |
+ } |
|
| 11 |
+ } |
|
| 12 |
+ |
|
| 13 |
+ @checker = Agents::SentimentAgent.new(@valid_params) |
|
| 14 |
+ @checker.user = users(:jane) |
|
| 15 |
+ @checker.save! |
|
| 16 |
+ |
|
| 17 |
+ @event = Event.new |
|
| 18 |
+ @event.agent = agents(:jane_weather_agent) |
|
| 19 |
+ @event.payload = {
|
|
| 20 |
+ :message => "value1" |
|
| 21 |
+ } |
|
| 22 |
+ @event.save! |
|
| 23 |
+ end |
|
| 24 |
+ |
|
| 25 |
+ describe "#working?" do |
|
| 26 |
+ it "checks if events have been received within expected receive period" do |
|
| 27 |
+ @checker.should_not be_working |
|
| 28 |
+ Agents::SentimentAgent.async_receive @checker.id, [@event.id] |
|
| 29 |
+ @checker.reload.should be_working |
|
| 30 |
+ two_days_from_now = 2.days.from_now |
|
| 31 |
+ stub(Time).now { two_days_from_now }
|
|
| 32 |
+ @checker.reload.should_not be_working |
|
| 33 |
+ end |
|
| 34 |
+ end |
|
| 35 |
+ |
|
| 36 |
+ describe "validation" do |
|
| 37 |
+ before do |
|
| 38 |
+ @checker.should be_valid |
|
| 39 |
+ end |
|
| 40 |
+ |
|
| 41 |
+ it "should validate presence of content key" do |
|
| 42 |
+ @checker.options[:content] = nil |
|
| 43 |
+ @checker.should_not be_valid |
|
| 44 |
+ end |
|
| 45 |
+ |
|
| 46 |
+ it "should validate presence of expected_receive_period_in_days key" do |
|
| 47 |
+ @checker.options[:expected_receive_period_in_days] = nil |
|
| 48 |
+ @checker.should_not be_valid |
|
| 49 |
+ end |
|
| 50 |
+ end |
|
| 51 |
+ |
|
| 52 |
+ describe "#receive" do |
|
| 53 |
+ it "checks if content key is working fine" do |
|
| 54 |
+ @checker.receive([@event]) |
|
| 55 |
+ Event.last.payload[:content].should == "value1" |
|
| 56 |
+ Event.last.payload[:original_event].should == {:message => "value1"}
|
|
| 57 |
+ end |
|
| 58 |
+ it "should handle multiple events" do |
|
| 59 |
+ event1 = Event.new |
|
| 60 |
+ event1.agent = agents(:bob_weather_agent) |
|
| 61 |
+ event1.payload = {
|
|
| 62 |
+ :message => "The quick brown fox jumps over the lazy dog" |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ event2 = Event.new |
|
| 66 |
+ event2.agent = agents(:jane_weather_agent) |
|
| 67 |
+ event2.payload = {
|
|
| 68 |
+ :message => "The quick brown fox jumps over the lazy dog" |
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ lambda {
|
|
| 72 |
+ @checker.receive([@event,event1,event2]) |
|
| 73 |
+ }.should change { Event.count }.by(3)
|
|
| 74 |
+ end |
|
| 75 |
+ end |
|
| 76 |
+end |