Last active
January 3, 2016 22:59
-
-
Save KenYN/8532462 to your computer and use it in GitHub Desktop.
This is a rough outline of how a Scenario for https://github.com/cantino/huginn might be implemented. Note that the Schedule class is left as an exercise to the reader.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Scenario < ActiveRecord::Base | |
has_many :agents, :dependent => :destroy, :inverse_of => :scenario | |
belongs_to :schedule, :inverse_of => :scenarios | |
belongs_to :user | |
attr_accessible :description, :name, :scenario | |
# XML description of scenario - not in DB! | |
attr_accessor :scenario | |
# Create a set of rules from the passed in parameters. | |
# @param current_user the current user | |
# @param params POST parameters - note that params[:scenario] defines the current scenario | |
def self.create(current_user, params) | |
new_scenario = Scenario.new(params[:scenario]) | |
new_scenario.schedule_id = params[:schedule_id] | |
new_scenario.create_scenario(current_user) | |
end | |
# Create a set of rules for the current user and the stored :scenario. | |
# @param current_user the current user | |
def create_scenario(current_user) | |
# Load up the XML description | |
scenario_file = Nokogiri::XML(scenario) | |
# Create all agents for each <agent> | |
agent_list = Hash.new() | |
scenario_file.xpath('/scenario/agent').each do |agent_node| | |
new_agent = create_agent(current_user, agent_node) | |
new_agent.scenario = self | |
# Add in the default options, unless they overwrite explicitly-set options | |
new_agent.options.reverse_merge!(new_agent.default_options) | |
# Final initialization chance | |
new_agent.after_xml_creation | |
agent_list[agent_node.attr('id')] = new_agent | |
end | |
ActiveRecord::Base.transaction do | |
# Save agents - must do this here to generate agent_ids for links | |
agent_list.each_value &:save! | |
# Create all links for each <link> | |
link_list = Hash.new() | |
scenario_file.xpath('/scenario/link').each do |link_node| | |
link_list[link_node.attr('id')] = create_link(agent_list, link_node) | |
end | |
# Save links | |
link_list.each_value &:save! | |
# Finally save myself | |
self.user = current_user | |
save! | |
return self | |
end | |
end | |
# Create an agent | |
# @param current_user the current user | |
# @param agent_node XML node describing the agent to create | |
# @return new Agent object | |
def create_agent(current_user, agent_node) | |
# Create the Agent | |
new_agent = agent_node.attr("agent").to_s.constantize.new | |
# Add a name | |
new_agent.name = agent_node.attr("name").to_s | |
# Add a schedule, if present | |
schedule = agent_node.attr("schedule") | |
new_agent.schedule = schedule.to_s if schedule.present? | |
# Set the owner | |
new_agent.user = current_user | |
# Add the arguments | |
Array(agent_node.xpath("./agent_setting")).each {|tag| new_agent.options[tag.attr("option")] = tag.attr("value") unless tag.attr("option").nil? } | |
# And return the new agent | |
return new_agent | |
end | |
# Create a link | |
# @param current_agents the agents created earlier | |
# @param link_node XML node describing the link to create | |
# @return new Link object | |
def create_link(current_agents, link_node) | |
# Create the link | |
new_link = Link.new(:source_id => current_agents[link_node.attr("source")].id, | |
:receiver_id => current_agents[link_node.attr("sink")].id) | |
# And return the new link | |
return new_link | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: UTF-8 | |
class ScenariosController < ApplicationController | |
def new | |
@scenario = Scenario.new() | |
@scenario.name = "My first scenario" | |
@scenario.description = "My first scenario description" | |
@scenario.scenario = <<SAMPLE_XML | |
<scenario name="#{@scenario.name}" description="#{@scenario.description}"> | |
<agent id="one" name="Weather trigger agent" agent="Agents::WeatherAgent"> | |
<agent_setting option="api_key" value="abcd"/> | |
<agent_setting option="location" value="94103"/> | |
</agent> | |
<agent id="two" name="Adioso trigger agent" agent="Agents::AdiosoAgent"> | |
<agent_setting option="from" value="New York"/> | |
<agent_setting option="to" value="Chicago"/> | |
</agent> | |
<agent id="three" name="Sendmail agent" agent="Agents::SendEmailAgent"> | |
<agent_setting option="to" value="[email protected]"/> | |
<agent_setting option="subject" value="Nice weather for a trip"/> | |
</agent> | |
<agent id="four" name="Twitter action" agent="Agents::TwitterPublishAgent"> | |
<agent_setting option="message_path" value="Off to #Chicago"/> | |
<agent_setting option="username" value="me"/> | |
</agent> | |
<link id="one" source="one" sink="four"/> | |
<link id="two" source="two" sink="three"/> | |
<link id="three" source="one" sink="three"/> | |
</scenario> | |
SAMPLE_XML | |
@schedule = current_user.schedules.find(params[:schedule_id]) | |
end | |
# Create a new scenario | |
def create | |
# Create the scenario | |
# Note: current_user comes from Devise, and is only available in Controllers and Views, | |
# not models, so that's why we have to pass it in here | |
new_scenario = Scenario.create(current_user, params) | |
# And bung us back up to the top page | |
respond_to do |format| | |
format.html do | |
redirect_to schedule_scenarios_path(params[:schedule_id]) | |
end | |
format.js do | |
render json: new_scenario | |
end | |
end | |
end | |
# Destroy a scenario | |
def destroy | |
@scenario = current_user.scenarios.find(params[:id]) | |
@scenario.destroy | |
respond_to do |format| | |
format.html { redirect_to schedule_scenarios_path(params[:schedule_id]) } | |
format.json { head :no_content } | |
end | |
end | |
# View a list of scenarios | |
def index | |
@schedule_id = params[:schedule_id] | |
if @schedule_id.present? && @schedule_id != -1 | |
@schedule = current_user.schedules.find(@schedule_id) | |
@scenarios = @schedule.scenarios.page(params[:page]) | |
else | |
@scenarios = current_user.scenarios.page(params[:page]) | |
end | |
respond_to do |format| | |
format.html | |
format.json { render json: @scenarios } | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment