smarts_api 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smarts_api (0.0.1)
4
+ smarts_api (0.0.3)
5
5
  activesupport
6
6
  typhoeus
7
7
 
data/README.md CHANGED
@@ -1,7 +1,81 @@
1
1
  smarts_api
2
2
  ==========
3
3
 
4
- Ruby API for Sparkling Logic SMARTS
4
+ Ruby API for Sparkling Logic SMARTS
5
5
 
6
+ ## Install
7
+ ```ruby
8
+ gem install smarts_api #use bundle if working in rails
9
+ ```
10
+
11
+ ##Usage
12
+ Create in your ruby app a config/initializers/smarts_api.rb
13
+ ```ruby
14
+ SMARTS_CONFIG = YAML.load_file(Rails.root.join("config","sparkling_logic.yml"))[Rails.env]
15
+ SmartsApi.configure do | config |
16
+ config.base_uri = SMARTS_CONFIG["base_uri"]
17
+ config.app_id = SMARTS_CONFIG["app_id"]
18
+ config.access_key = SMARTS_CONFIG["access_key"]
19
+ config.user_id = SMARTS_CONFIG["user_id"]
20
+ config.pwd = SMARTS_CONFIG["pwd"]
21
+ config.workspace_id = SMARTS_CONFIG["workspace_id"]
22
+ config.project_id = SMARTS_CONFIG["project_id"]
23
+ end
24
+ ```
25
+
26
+ And then you'll need a yml config that looks something like
27
+ ```ruby
28
+ development: &default
29
+ base_uri: http://customers.sparkological.com/DecisionServer/decision-services/deployments/
30
+ app_id: #application ID
31
+ access_key: #SECRET access key
32
+ user_id: #the user id for the application account that has access to SMARTS
33
+ pwd: #account password
34
+ workspace_id: Top/Local #or wherever your workspace is defined.
35
+ project_id: #Something something project name
36
+ ```
37
+
38
+ Finally you can call smarts with
39
+ ```ruby
40
+ SmartsApi.evaluate("Decide if situation is cool", situation, logger=nil)
41
+ ```
42
+
43
+ the evaluate call takes a string parameter identifying the decision to evaluate. the eval_object is any Object, but must respond to the following methods:
44
+ ```ruby
45
+ class Situation
46
+
47
+ def smarts_document
48
+ #generates a JSON document that matches the expected json format of the SMARTS project
49
+ [
50
+ {
51
+ :time_stamp => DateTime.now
52
+ :have_money => Money.any?
53
+ :have_power => Power.significant_amount?
54
+ }
55
+ ]
56
+ end
57
+
58
+ def process_smarts_response(body)
59
+ #takes a JSON document as its parameter, and processes it with whatever rules pertain to this class
60
+ if body["Documents"].first["is_a_cool_situation"]
61
+ User.notify("Your situation is cool!")
62
+ end
63
+ end
64
+
65
+ end
66
+ ```
67
+
68
+
69
+ ##Credits, Contributors
70
+
71
+ Created by [Steve Mitchell](https://github.com/theSteveMitchell)
72
+
73
+ Issues and contributions welcome.
74
+
75
+ ##Disclaimer
76
+ This project and it's creators, contributors, detractors, fans, haters (who, by definition, are always gonna hate), users, and abusers are in no way associated with Sparkling Logic, the innovator and creator of SMARTS™. We have no connection with Sparkling Logic, and are not responsible for any work they do.
77
+
78
+ From http://my.sparklinglogic.com/index.php/what-it-does:
79
+
80
+ Sparkling Logic SMARTS™ is a revolutionary decision management product that provides you with an intuitive and interactive environment that dramatically lowers the learning curve to allow you to immediately start capturing and refining your decision logic. You can combine decision logic based on business policies and expertise with decision logic revealed in your historical data- so you can narrow to the most impactful and high-performance business decision. Collaboration is built into SMARTS so all relevant stakeholders can participate in defining and managing automated decisions.
6
81
 
7
- This project and it's creators, contributors, fans, and haters are in no way associated with Sparkling Logic, the innovator and creator of SMARTS.
@@ -1,7 +1,7 @@
1
1
  class SmartsApi::EvaluateMessage < SmartsApi::Message
2
2
 
3
- def send(session, member, decision)
4
- body = make_form(request_params(session, member, decision))
3
+ def send(session, obj_hash, decision)
4
+ body = make_form(request_params(session, obj_hash, decision))
5
5
  log "Evaluating"
6
6
  response = Typhoeus::Request.post(uri,
7
7
  :method => method,
@@ -20,16 +20,13 @@ class SmartsApi::EvaluateMessage < SmartsApi::Message
20
20
 
21
21
  raise SmartsApi::Error, "Rules Evaluation failed. Returned JSON is blank."
22
22
  end
23
-
24
- log "Updating issues"
25
- member.process_smarts_response body
26
23
  return body
27
24
  end
28
25
 
29
- def request_params(session, member, decision)
26
+ def request_params(session, obj_hash, decision)
30
27
  params = {
31
28
  :appId => SmartsApi::Configuration.app_id,
32
- :reqData => request_document(session, member, decision),
29
+ :reqData => request_document(session, obj_hash, decision),
33
30
  :reqTime => timestamp,
34
31
  :session => session
35
32
  }
@@ -39,9 +36,9 @@ class SmartsApi::EvaluateMessage < SmartsApi::Message
39
36
  return params.merge(signature)
40
37
  end
41
38
 
42
- def request_document(session, member, decision)
39
+ def request_document(session, obj_hash, decision)
43
40
  doc = {:OperationId =>1 , :Header => {:SessionId => session, :DecisionId => decision}, :Body => {:Documents => []}}
44
- doc[:Body][:Documents] = member.smarts_document
41
+ doc[:Body][:Documents] = obj_hash
45
42
  return doc.to_json
46
43
  end
47
44
 
@@ -1,5 +1,5 @@
1
1
  module SmartsApi
2
2
  module Version # :nodoc:
3
- STRING = '0.0.2'
3
+ STRING = '0.0.3'
4
4
  end
5
5
  end
data/lib/smarts_api.rb CHANGED
@@ -18,15 +18,16 @@ module SmartsApi
18
18
  Dir[File.expand_path('../../lib/smarts_api/*.rb', __FILE__)].each {|f| require f}
19
19
  Dir[File.expand_path('../../lib/smarts_api/*/*.rb', __FILE__)].each {|f| require f}
20
20
 
21
- def self.evaluate(decision, obj, logger = nil)
22
- raise SmartsApi::Error.new("Object to be evaluated must define a method 'smarts_document'") unless obj.respond_to?(:smarts_document)
21
+ def self.evaluate(decision, obj_hash, logger = nil)
23
22
  logger.info "processing request for #{obj.class} id=#{obj.id}{" if logger.respond_to?(:info)
24
23
 
25
24
  session = SmartsApi::ConnectMessage.new().send
26
25
  response = SmartsApi::EvaluateMessage.new().
27
- send(session, obj, decision)
26
+ send(session, obj_hash, decision)
28
27
 
29
28
  SmartsApi::DisconnectMessage.new().send(session)
29
+
30
+ return response
30
31
  end
31
32
 
32
33
  end
@@ -7,37 +7,31 @@ describe SmartsApi::EvaluateMessage do
7
7
  SmartsApi::Configuration.access_key = "sshhhh...Secret!"
8
8
  end
9
9
 
10
- let(:eval_class) {
11
- Class.new() do
12
-
13
- def smarts_document
14
- "123"
15
- end
16
-
17
- def process_smarts_response(body)
18
-
19
- end
20
- end
10
+ let(:obj_hash) {
11
+ {:key => "value!!!?"}
21
12
  }
22
13
 
23
- let(:eval_object) {
24
- eval_class.new()
25
- }
26
-
27
- it 'should return session ID if successful' do
14
+ it 'should return request body if successful' do
28
15
 
29
16
  body = "{\"OperationId\":1,\"Header\":{\"SessionId\":\"e3e2b012-e9b6-45e7-a96a-a009ebf0a07a\"},\"Body\":{\"Documents\":[{\"identification\":{\"actor_group\":\"root\",\"actor_id\":3,\"gender\":\"Male\",\"birth_date\":\"1984-12-08T06:00:00Z\"},\"historical_properties\":[{\"weight\":\"150\"}]}]},\"ErrorInfo\":null,\"Metrics\":null,\"Success\":true,\"OperationException\":null}"
30
17
 
31
18
  stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
32
19
  .to_return(:status => 200, :body => body)
33
- SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169", eval_object, "Issues Analysis Decision").should == JSON.parse(body)["Body"]
20
+ SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169", obj_hash, "Issues Analysis Decision").should == {"Documents"=>
21
+ [{"identification"=>
22
+ {"actor_group"=>"root",
23
+ "actor_id"=>3,
24
+ "gender"=>"Male",
25
+ "birth_date"=>"1984-12-08T06:00:00Z"},
26
+ "historical_properties"=>[{"weight"=>"150"}]}]}
27
+
34
28
 
35
29
  end
36
30
 
37
31
  it 'should throw an error if the connection returns an error' do
38
32
  stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
39
33
  .to_return(:status => 200, :body => "{\"OperationId\":0,\"Header\":{\"SessionId\":\"00000000-0000-0000-0000-000000000000\",\"TransactionTime\":\"2012-06-22T21:02:16.642625Z\",\"Workspace\":null,\"DeploymentId\":null,\"DecisionId\":null},\"Body\":null,\"ErrorInfo\":{\"ErrorCode\":\"ServerException\",\"ErrorMessage\":\"Exception during connection\",\"Details\":[\"Invalid API access\"]},\"Metrics\":null,\"Success\":false,\"OperationException\":{\"IsRestException\":true,\"ErrorType\":\"DocApiAccessDeniedException\",\"CompleteStackTrace\":\"Type: DocApiAccessDeniedException\\r\\nMessage: Invalid API access\\r\\nStack Trace:\\r\\n at Splog.Rest.Base.DocRestHttpHandler.VerifyHmacSignature(String method, IEnumerable`1 keys, String signature, String[] paramaters)\\r\\n at Splog.Rest.Decisions.DocRestDecisionService.Connect(String appId, String reqTime, String userId, String pwd, String workspaceId, String reqData, String sign)\\r\\n\\r\\n\",\"ExtraInfo\":null,\"Message\":\"[DecisionServer] Exception connecting to the decision server for session 72950db0-9639-477b-b824-b82ad5122b56\",\"Data\":{}}}")
40
- expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",eval_object, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
34
+ expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",obj_hash, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
41
35
 
42
36
  end
43
37
 
@@ -45,7 +39,7 @@ describe SmartsApi::EvaluateMessage do
45
39
 
46
40
  stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
47
41
  .to_return(:status => 200, :body => "{\"OperationId\":0,\"Header\":{\"SessionId\":\"00000000-0000-0000-0000-000000000000\",\"TransactionTime\":\"2012-06-22T21:02:16.642625Z\",\"Workspace\":null,\"DeploymentId\":null,\"DecisionId\":null},\"Body\":null,\"ErrorInfo\":{\"ErrorCode\":\"ServerException\",\"ErrorMessage\":\"Exception during connection\",\"Details\":[\"Invalid API access\"]},\"Metrics\":null,\"Success\":false,\"OperationException\":{\"IsRestException\":true,\"ErrorType\":\"DocApiAccessDeniedException\",\"CompleteStackTrace\":\"Type: DocApiAccessDeniedException\\r\\nMessage: Invalid API access\\r\\nStack Trace:\\r\\n at Splog.Rest.Base.DocRestHttpHandler.VerifyHmacSignature(String method, IEnumerable`1 keys, String signature, String[] paramaters)\\r\\n at Splog.Rest.Decisions.DocRestDecisionService.Connect(String appId, String reqTime, String userId, String pwd, String workspaceId, String reqData, String sign)\\r\\n\\r\\n\",\"ExtraInfo\":null,\"Message\":\"[DecisionServer] Exception connecting to the decision server for session 72950db0-9639-477b-b824-b82ad5122b56\",\"Data\":{}}}")
48
- expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",eval_object, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
42
+ expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",obj_hash, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
49
43
 
50
44
  end
51
45
 
@@ -53,7 +47,7 @@ describe SmartsApi::EvaluateMessage do
53
47
 
54
48
  stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
55
49
  .to_return(:status => 200)
56
- expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",eval_object, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
50
+ expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",obj_hash, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
57
51
 
58
52
  end
59
53
 
@@ -61,26 +55,16 @@ describe SmartsApi::EvaluateMessage do
61
55
 
62
56
  stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
63
57
  .to_return(:status => 500)
64
- expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",eval_object, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
58
+ expect{SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169",obj_hash, "Issues Analysis Decision")}.to raise_error(SmartsApi::Error)
65
59
 
66
60
  end
67
61
 
68
- it 'should call the document method on the member object' do
69
- eval_object.should_receive(:smarts_document)
70
- body = "{\"OperationId\":1,\"Header\":{\"SessionId\":\"e3e2b012-e9b6-45e7-a96a-a009ebf0a07a\"},\"Body\":{\"Documents\":[{\"identification\":{\"actor_group\":\"root\",\"actor_id\":3,\"gender\":\"Male\",\"birth_date\":\"1984-12-08T06:00:00Z\"},\"historical_properties\":[{\"weight\":\"150\"}]}]},\"ErrorInfo\":null,\"Metrics\":null,\"Success\":true,\"OperationException\":null}"
71
-
72
- stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
73
- .to_return(:status => 200, :body => body)
74
- SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169", eval_object, "Issues Analysis Decision").should == JSON.parse(body)["Body"]
75
- end
76
-
77
- it "should pass the returned message body to the evaluated object for processing" do
62
+ describe "request document" do
63
+ it "include the input hash" do
64
+ SmartsApi::EvaluateMessage.new().request_document("487d2c44-43fe-44d3-988f-ea462af03169", obj_hash, "Issues Analysis Decision").should ==
65
+ "{\"OperationId\":1,\"Header\":{\"SessionId\":\"487d2c44-43fe-44d3-988f-ea462af03169\",\"DecisionId\":\"Issues Analysis Decision\"},\"Body\":{\"Documents\":{\"key\":\"value!!!?\"}}}"
66
+ end
78
67
 
79
- body = "{\"OperationId\":1,\"Header\":{\"SessionId\":\"e3e2b012-e9b6-45e7-a96a-a009ebf0a07a\"},\"Body\":{\"Documents\":[{\"identification\":{\"actor_group\":\"root\",\"actor_id\":3,\"gender\":\"Male\",\"birth_date\":\"1984-12-08T06:00:00Z\"},\"historical_properties\":[{\"weight\":\"150\"}]}]},\"ErrorInfo\":null,\"Metrics\":null,\"Success\":true,\"OperationException\":null}"
80
- eval_object.should_receive(:process_smarts_response).with(JSON.parse(body)["Body"])
81
- stub_http_request(:post, "#{SmartsApi::Configuration.base_uri}evaluate")
82
- .to_return(:status => 200, :body => body)
83
- SmartsApi::EvaluateMessage.new().send("487d2c44-43fe-44d3-988f-ea462af03169", eval_object, "Issues Analysis Decision").should == JSON.parse(body)["Body"]
84
68
  end
85
69
 
86
70
  end
@@ -10,49 +10,26 @@ describe SmartsApi do
10
10
  end
11
11
 
12
12
  describe "expectations on eval object" do
13
+ it 'should accept any hash as a ' do
13
14
 
14
- it 'should raise error and not call connect if obj is nil' do
15
- expect{SmartsApi.evaluate(
16
- "string", nil
17
- )}.to raise_error(SmartsApi::Error, "Object to be evaluated must define a method 'smarts_document'")
18
- end
19
-
20
- it 'should raise error and not call connect if obj does not define the document method' do
21
- RegularClass = Class.new() {}
22
- instance = RegularClass.new
23
- instance.should_not be_nil
24
- expect{SmartsApi.evaluate(
25
- "string", instance
26
- )}.to raise_error(SmartsApi::Error, "Object to be evaluated must define a method 'smarts_document'")
27
- end
28
-
29
- it 'should accept any object that defines the document method' do
30
- EvalClass= Class.new() do
31
- def smarts_document
32
- "EvalClass.Instance 1"
33
- end
34
- end
35
-
36
- instance = EvalClass.new
37
- instance.should_not be_nil
15
+ hash = {:hash? => true}
38
16
 
39
17
  SmartsApi::ConnectMessage.any_instance.should_receive(:send).and_return("session 334")
40
18
  SmartsApi::EvaluateMessage.any_instance.should_receive(:send)
41
19
  SmartsApi::DisconnectMessage.any_instance.should_receive(:send).with("session 334")
42
- SmartsApi.evaluate("string", instance)
20
+ SmartsApi.evaluate("string", hash)
43
21
  end
44
22
  end
45
23
 
46
24
  describe "specifying decision string" do
47
25
  it "should include the decision name and session when sending the evaluate message" do
48
26
 
49
- instance = EvalClass.new
50
- instance.should_not be_nil
27
+ hash = {:hash? => true}
51
28
  SmartsApi::ConnectMessage.any_instance.should_receive(:send).and_return("session 3339")
52
- SmartsApi::EvaluateMessage.any_instance.should_receive(:send).with("session 3339", instance, "Chosen_decision")
29
+ SmartsApi::EvaluateMessage.any_instance.should_receive(:send).with("session 3339", hash, "Chosen_decision")
53
30
  SmartsApi::DisconnectMessage.any_instance.should_receive(:send).with("session 3339")
54
31
 
55
- SmartsApi.evaluate("Chosen_decision", instance)
32
+ SmartsApi.evaluate("Chosen_decision", hash)
56
33
  end
57
34
  end
58
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smarts_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-23 00:00:00.000000000 Z
12
+ date: 2013-09-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: typhoeus
@@ -91,7 +91,7 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
- description: smarts_api-0.0.2
94
+ description: smarts_api-0.0.3
95
95
  email:
96
96
  - theSteveMitchell@gmail.com
97
97
  executables: []