solve360 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -41,17 +41,17 @@ And if you're using environments like Rails:
41
41
 
42
42
  Base attributes are set up for you. Creating is simple:
43
43
 
44
- Solve360::Contact.create("First Name" => "Stephen", "Last Name" => "Bartholomew")
44
+ Solve360::Contact.create(:fields => "First Name" => "Stephen", "Last Name" => "Bartholomew")
45
45
 
46
46
  Custom attributes can be added:
47
47
 
48
- Solve360::Contact.fields do
48
+ Solve360::Contact.map_fields do
49
49
  {"Description" => "custom20394", "Location" => "custom392434"}
50
50
  end
51
51
 
52
52
  and then used:
53
53
 
54
- contact = Solve360::Contact.create("First Name" => "Steve", "Description" => "Web Developer", "Location" => "England")
54
+ contact = Solve360::Contact.create(:fields => "First Name" => "Steve", "Description" => "Web Developer", "Location" => "England")
55
55
  contact.id
56
56
  => The ID of the record created on the CRM
57
57
 
@@ -65,11 +65,23 @@ You can find by the ID of a record on the CRM:
65
65
 
66
66
  Once you have set the attributes on a model you can simply save:
67
67
 
68
- contact.attributes["First Name"] = "Steve"
68
+ contact.fields["First Name"] = "Steve"
69
69
  contact.save
70
70
 
71
71
  If the record does not have an ID it'll be created, otherwise the details will be saved.
72
72
 
73
+ ### Related Items
74
+
75
+ Related items can be access via:
76
+
77
+ contact.related_items
78
+ => {"name" => "Curve21", "id" => "12345"}
79
+
80
+ And added:
81
+
82
+ contact.add_related_item({"name" => "ACME Ltd", "id" => "91284"})
83
+ contact.save
84
+
73
85
  ## Support/Bugs
74
86
 
75
87
  [Lighthouse](http://c21.lighthouseapp.com/projects/38966-solve360/overview)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/lib/solve360.rb CHANGED
@@ -4,6 +4,6 @@ require "active_support/inflector"
4
4
  require "active_support/core_ext/hash"
5
5
 
6
6
 
7
- ["model", "config", "contact", "company"].each do |lib|
7
+ ["item", "config", "contact", "company"].each do |lib|
8
8
  require File.join(File.dirname(__FILE__), "solve360", lib)
9
9
  end
@@ -1,8 +1,8 @@
1
1
  module Solve360
2
2
  class Company
3
- include Solve360::Model
3
+ include Solve360::Item
4
4
 
5
- fields do
5
+ map_fields do
6
6
  {"Billing Address" => "billingaddress",
7
7
  "Company Address" => "mainaddress",
8
8
  "Company Fax" => "fax",
@@ -1,8 +1,8 @@
1
1
  module Solve360
2
2
  class Contact
3
- include Solve360::Model
3
+ include Solve360::Item
4
4
 
5
- fields do
5
+ map_fields do
6
6
  {"Business Address" => "businessaddress",
7
7
  "Business Direct" => "businessphonedirect",
8
8
  "Business Email" => "businessemail",
@@ -0,0 +1,189 @@
1
+ module Solve360
2
+ module Item
3
+
4
+ def self.included(model)
5
+ model.extend ClassMethods
6
+ model.send(:include, HTTParty)
7
+ model.instance_variable_set(:@field_mapping, {})
8
+ end
9
+
10
+ # Base Item fields
11
+ attr_accessor :id, :name, :typeid, :created, :updated, :viewed, :ownership, :flagged
12
+
13
+ # Base item collections
14
+ attr_accessor :fields, :related_items, :related_items_to_add
15
+
16
+ def initialize(attributes = {})
17
+ attributes.symbolize_keys!
18
+
19
+ self.fields = {}
20
+ self.related_items = []
21
+ self.related_items_to_add = []
22
+
23
+ [:fields, :related_items].each do |collection|
24
+ self.send("#{collection}=", attributes[collection]) if attributes[collection]
25
+ attributes.delete collection
26
+ end
27
+
28
+ attributes.each do |key, value|
29
+ self.send("#{key}=", value)
30
+ end
31
+ end
32
+
33
+ # @see Base::map_human_attributes
34
+ def map_human_fields
35
+ self.class.map_human_fields(self.fields)
36
+ end
37
+
38
+ # Save the attributes for the current record to the CRM
39
+ #
40
+ # If the record is new it will be created on the CRM
41
+ #
42
+ # @return [Hash] response values from API
43
+ def save
44
+ response = []
45
+ if new_record?
46
+ response = self.class.request(:post, "/#{self.class.resource_name}", to_request)
47
+ self.id = response["response"]["item"]["id"]
48
+ else
49
+ response = self.class.request(:put, "/#{self.class.resource_name}/#{id}", to_request)
50
+ end
51
+
52
+ related_items.concat(related_items_to_add)
53
+
54
+ response
55
+ end
56
+
57
+ def new_record?
58
+ self.id == nil
59
+ end
60
+
61
+ def to_request
62
+ xml = "<request>"
63
+
64
+ xml << map_human_fields.collect {|key, value| "<#{key}>#{value}</#{key}>"}.join("")
65
+
66
+ if related_items_to_add.size > 0
67
+ xml << "<relateditems>"
68
+
69
+ related_items_to_add.each do |related_item|
70
+ xml << %Q{<add><relatedto><id>#{related_item["id"]}</id></relatedto></add>}
71
+ end
72
+
73
+ xml << "</relateditems>"
74
+ end
75
+ xml << "</request>"
76
+
77
+ xml
78
+ end
79
+
80
+ def add_related_item(item)
81
+ related_items_to_add << item
82
+ end
83
+
84
+ module ClassMethods
85
+
86
+ # Map human map_human_fields to API fields
87
+ #
88
+ # @param [Hash] human mapped fields
89
+ # @example
90
+ # map_attributes("First Name" => "Steve", "Description" => "Web Developer")
91
+ # => {:firstname => "Steve", :custom12345 => "Web Developer"}
92
+ #
93
+ # @return [Hash] API mapped attributes
94
+ #
95
+ def map_human_fields(fields)
96
+ mapped_fields = {}
97
+
98
+ field_mapping.each do |human, api|
99
+ mapped_fields[api] = fields[human] if !fields[human].blank?
100
+ end
101
+
102
+ mapped_fields
103
+ end
104
+
105
+ # As ::map_api_fields but API -> human
106
+ #
107
+ # @param [Hash] API mapped attributes
108
+ # @example
109
+ # map_attributes(:firstname => "Steve", :custom12345 => "Web Developer")
110
+ # => {"First Name" => "Steve", "Description" => "Web Developer"}
111
+ #
112
+ # @return [Hash] human mapped attributes
113
+ def map_api_fields(fields)
114
+ fields.stringify_keys!
115
+
116
+ mapped_fields = {}
117
+
118
+ field_mapping.each do |human, api|
119
+ mapped_fields[human] = fields[api] if !fields[api].blank?
120
+ end
121
+
122
+ mapped_fields
123
+ end
124
+
125
+ # Create a record in the API
126
+ #
127
+ # @param [Hash] field => value as configured in Item::fields
128
+ def create(fields, options = {})
129
+ new_record = self.new(fields)
130
+ new_record.save
131
+ new_record
132
+ end
133
+
134
+ # Find a record
135
+ #
136
+ # @param [Integer] id of the record on the CRM
137
+ def find(id)
138
+ response = request(:get, "/#{resource_name}/#{id}")
139
+
140
+ construct_record_from_response(response)
141
+ end
142
+
143
+ # Send an HTTP request
144
+ #
145
+ # @param [Symbol, String] :get, :post, :put or :delete
146
+ # @param [String] url of the resource
147
+ # @param [String, nil] optional string to send in request body
148
+ def request(verb, uri, body = "")
149
+ send(verb, HTTParty.normalize_base_uri(Solve360::Config.config.url) + uri,
150
+ :headers => {"Content-Type" => "application/xml", "Accepts" => "application/json"},
151
+ :body => body,
152
+ :basic_auth => {:username => Solve360::Config.config.username, :password => Solve360::Config.config.token})
153
+ end
154
+
155
+ def construct_record_from_response(response)
156
+ item = response["response"]["item"]
157
+ item.symbolize_keys!
158
+
159
+ item[:fields] = map_api_fields(item[:fields])
160
+
161
+ record = new(item)
162
+
163
+ if response["response"]["relateditems"]
164
+ related_items = response["response"]["relateditems"]["relatedto"]
165
+
166
+ if related_items.kind_of?(Array)
167
+ record.related_items.concat(related_items)
168
+ else
169
+ record.related_items = [related_items]
170
+ end
171
+ end
172
+
173
+ record
174
+ end
175
+
176
+ def resource_name
177
+ self.name.to_s.demodulize.underscore.pluralize
178
+ end
179
+
180
+ def map_fields(&block)
181
+ @field_mapping.merge! yield
182
+ end
183
+
184
+ def field_mapping
185
+ @field_mapping
186
+ end
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,161 @@
1
+ require File.join(File.dirname(__FILE__), "..", "spec_helper")
2
+
3
+ class Person
4
+ include Solve360::Item
5
+
6
+ map_fields do
7
+ { "Job Title" => "job_title", "Name" => "name" }
8
+ end
9
+ end
10
+
11
+ describe "A Solve360 model" do
12
+ it "should determine model name" do
13
+ Person.resource_name.should == "people"
14
+ end
15
+
16
+ context "more than one model" do
17
+ it "should not pollute map" do
18
+ class Car
19
+ include Solve360::Item
20
+ map_fields do
21
+ { "Doors" => "doors" }
22
+ end
23
+ end
24
+
25
+ Car.field_mapping.keys.include?("Job Title").should be_false
26
+ Person.field_mapping.keys.include?("Doors").should be_false
27
+ end
28
+ end
29
+
30
+ context "XML respresentation" do
31
+ before do
32
+ @person = Person.new(:fields => {"Name" => "Stephen"})
33
+ @person.add_related_item({"name" => "Curve21", "id" => "12345"})
34
+
35
+ @xml = Crack::XML.parse(@person.to_request)
36
+ end
37
+
38
+ it "should contain related items to add" do
39
+ @xml["request"]["relateditems"]["add"]["relatedto"]["id"].should == "12345"
40
+ end
41
+
42
+ it "should contain item fields" do
43
+ @xml["request"]["name"].should == "Stephen"
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "Field mapping" do
49
+ before do
50
+ Person.map_fields do
51
+ {"Interests" => "custom_interests",
52
+ "Department Website" => "custom_deptwebsite",
53
+ "Description" => "custom_description"}
54
+ end
55
+
56
+ @person = Person.new
57
+ end
58
+
59
+ it "should set base map" do
60
+ Person.field_mapping["Job Title"].should == "job_title"
61
+ end
62
+
63
+ it "should set custom map" do
64
+ Person.field_mapping["Interests"].should == "custom_interests"
65
+ end
66
+
67
+ it "should allow setting of values on an instance via field maps" do
68
+ @person.fields["Interests"] = "Coding"
69
+ @person.fields["Interests"].should == "Coding"
70
+ end
71
+
72
+ it "should map human fields to API fields" do
73
+ fields = {"Description" => "A description"}
74
+
75
+ Person.map_human_fields(fields)["custom_description"].should == "A description"
76
+ end
77
+
78
+ it "should map API fields to human fields" do
79
+ fields = {:custom_description => "A description"}
80
+
81
+ Person.map_api_fields(fields)["Description"].should == "A description"
82
+ end
83
+ end
84
+
85
+ describe "Creating a record" do
86
+ context "directly from create" do
87
+ before do
88
+ stub_http_response_with("contacts/create-success.json")
89
+ @contact = Solve360::Contact.create(:fields => {"First Name" => "Catherine"})
90
+ end
91
+
92
+ it "should be valid" do
93
+ @contact.fields["First Name"].should == "Catherine"
94
+ @contact.id.should == "12345"
95
+ end
96
+ end
97
+
98
+ context "creating a new object then saving" do
99
+ before do
100
+ stub_http_response_with("contacts/create-success.json")
101
+ @contact = Solve360::Contact.new(:fields => {"First Name" => "Catherine"})
102
+ @contact.save
103
+ end
104
+
105
+ it "should be valid" do
106
+ @contact.id.should == "12345"
107
+ end
108
+ end
109
+ end
110
+
111
+ describe "Finding a record" do
112
+ context "Successfully" do
113
+ before do
114
+ stub_http_response_with("contacts/find-success.json")
115
+ @contact = Solve360::Contact.find(12345)
116
+ end
117
+
118
+ it "should find existing user" do
119
+ @contact.fields["First Name"].should == "Henry"
120
+ @contact.id.should == "12345"
121
+ end
122
+
123
+ it "should have relations" do
124
+ @contact.related_items.first["name"].should == "Curve21"
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "Updating a record" do
130
+ before do
131
+ @contact = Solve360::Contact.new(:fields => {"First Name" => "Steve"})
132
+
133
+ @contact.id = "12345"
134
+
135
+ stub_http_response_with("contacts/update-success.json")
136
+
137
+ @contact.fields["First Name"] = "Steve"
138
+
139
+ @response = @contact.save
140
+ end
141
+
142
+ it "should be valid" do
143
+ @response["response"]["status"].should == "success"
144
+ end
145
+ end
146
+
147
+ describe "Adding a releated item" do
148
+ before do
149
+ @contact = Solve360::Contact.new(:fields => {"First Name" => "Steve"})
150
+ @contact.id = "12345"
151
+
152
+ stub_http_response_with("contacts/update-success.json")
153
+
154
+ @contact.add_related_item({"name" => "A New Company", "id" => "932334"})
155
+ @contact.save
156
+ end
157
+
158
+ it "should become set after save" do
159
+ @contact.related_items.first["name"].should == "A New Company"
160
+ end
161
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solve360
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Bartholomew
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-16 00:00:00 +01:00
12
+ date: 2009-10-22 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -59,7 +59,7 @@ files:
59
59
  - lib/solve360/company.rb
60
60
  - lib/solve360/config.rb
61
61
  - lib/solve360/contact.rb
62
- - lib/solve360/model.rb
62
+ - lib/solve360/item.rb
63
63
  - spec/api_settings.yml
64
64
  - spec/api_settings.yml.sample
65
65
  - spec/fixtures/contacts/create-success.json
@@ -69,7 +69,7 @@ files:
69
69
  - spec/fixtures/contacts/show-success.json
70
70
  - spec/fixtures/contacts/update-failed.json
71
71
  - spec/fixtures/contacts/update-success.json
72
- - spec/solve360/model_spec.rb
72
+ - spec/solve360/item_spec.rb
73
73
  - spec/spec.opts
74
74
  - spec/spec_helper.rb
75
75
  has_rdoc: true
@@ -101,5 +101,5 @@ signing_key:
101
101
  specification_version: 3
102
102
  summary: Libary for working with the Solve360 CRM API
103
103
  test_files:
104
- - spec/solve360/model_spec.rb
104
+ - spec/solve360/item_spec.rb
105
105
  - spec/spec_helper.rb
@@ -1,141 +0,0 @@
1
- module Solve360
2
- module Model
3
-
4
- def self.included(model)
5
- model.extend ClassMethods
6
- model.send(:include, HTTParty)
7
- model.instance_variable_set(:@fields, {})
8
- end
9
-
10
- attr_accessor :attributes, :id, :relations
11
-
12
- def initialize(attributes = {})
13
- self.attributes = attributes
14
- self.relations = []
15
- self.id = nil
16
- end
17
-
18
- # @see Base::map_human_attributes
19
- def map_human_attributes
20
- self.class.map_human_attributes(self.attributes)
21
- end
22
-
23
- # Save the attributes for the current record to the CRM
24
- #
25
- # If the record is new it will be created on the CRM
26
- #
27
- # @return [Hash] response values from API
28
- def save
29
- if new_record?
30
- new_record = self.class.create(attributes)
31
- self.id = new_record.id
32
- else
33
- self.class.request(:put, "/#{self.class.resource_name}/#{id}", map_human_attributes.to_xml(:root => "request"))
34
- end
35
- end
36
-
37
- def new_record?
38
- self.id == nil
39
- end
40
-
41
- module ClassMethods
42
-
43
- # Map human attributes to API attributes
44
- #
45
- # @param [Hash] human mapped attributes
46
- # @example
47
- # map_attributes("First Name" => "Steve", "Description" => "Web Developer")
48
- # => {:firstname => "Steve", :custom12345 => "Web Developer"}
49
- #
50
- # @return [Hash] API mapped attributes
51
- #
52
- def map_human_attributes(attributes)
53
- mapped_attributes = {}
54
-
55
- fields.each do |human, api|
56
- mapped_attributes[api] = attributes[human] if !attributes[human].blank?
57
- end
58
-
59
- mapped_attributes
60
- end
61
-
62
- # As ::map_human_attributes but API -> human
63
- #
64
- # @param [Hash] API mapped attributes
65
- # @example
66
- # map_attributes(:firstname => "Steve", :custom12345 => "Web Developer")
67
- # => {"First Name" => "Steve", "Description" => "Web Developer"}
68
- #
69
- # @return [Hash] human mapped attributes
70
- def map_api_attributes(attributes)
71
- attributes.stringify_keys!
72
-
73
- mapped_attributes = {}
74
-
75
- fields.each do |human, api|
76
- mapped_attributes[human] = attributes[api] if !attributes[api].blank?
77
- end
78
-
79
- mapped_attributes
80
- end
81
-
82
- # Create a record in the API
83
- #
84
- # @param [Hash] field => value as configured in Model::fields
85
- def create(attributes, options = {})
86
- response = request(:post, "/#{resource_name}", map_human_attributes(attributes).to_xml(:root => "request"))
87
-
88
- construct_record_from_response(response)
89
- end
90
-
91
- # Find a record
92
- #
93
- # @param [Integer] id of the record on the CRM
94
- def find(id)
95
- response = request(:get, "/#{resource_name}/#{id}")
96
-
97
- construct_record_from_response(response)
98
- end
99
-
100
- # Send an HTTP request
101
- #
102
- # @param [Symbol, String] :get, :post, :put or :delete
103
- # @param [String] url of the resource
104
- # @param [String, nil] optional string to send in request body
105
- def request(verb, uri, body = "")
106
- send(verb, HTTParty.normalize_base_uri(Solve360::Config.config.url) + uri,
107
- :headers => {"Content-Type" => "application/xml", "Accepts" => "application/json"},
108
- :body => body,
109
- :basic_auth => {:username => Solve360::Config.config.username, :password => Solve360::Config.config.token})
110
- end
111
-
112
- def construct_record_from_response(response)
113
- attributes = map_api_attributes(response["response"]["item"]["fields"])
114
- record = new(attributes)
115
-
116
- related_to = response["response"]["relateditems"]["relatedto"]
117
-
118
- if related_to.kind_of?(Array)
119
- record.relations.concat(related_to)
120
- else
121
- record.relations << related_to
122
- end
123
-
124
- record.id = response["response"]["item"]["id"].to_i
125
- record
126
- end
127
-
128
- def resource_name
129
- self.name.to_s.demodulize.underscore.pluralize
130
- end
131
-
132
- def fields(&block)
133
- if block_given?
134
- @fields.merge! yield
135
- else
136
- @fields
137
- end
138
- end
139
- end
140
- end
141
- end
@@ -1,128 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "..", "spec_helper")
2
-
3
- class Person
4
- include Solve360::Model
5
-
6
- fields do
7
- { "Job Title" => "job_title" }
8
- end
9
- end
10
-
11
- describe "A Solve360 model" do
12
- it "should determine model name" do
13
- Person.resource_name.should == "people"
14
- end
15
-
16
- context "more than one model" do
17
- it "should not pollute map" do
18
- class Car
19
- include Solve360::Model
20
- fields do
21
- { "Doors" => "doors" }
22
- end
23
- end
24
-
25
- Car.fields.keys.include?("Job Title").should be_false
26
- Person.fields.keys.include?("Doors").should be_false
27
- end
28
- end
29
- end
30
-
31
- describe "Field mapping" do
32
- before do
33
- Person.fields do
34
- {"Interests" => "custom_interests",
35
- "Department Website" => "custom_deptwebsite",
36
- "Description" => "custom_description"}
37
- end
38
-
39
- @person = Person.new
40
- end
41
-
42
- it "should set base map" do
43
- Person.fields["Job Title"].should == "job_title"
44
- end
45
-
46
- it "should set custom map" do
47
- Person.fields["Interests"].should == "custom_interests"
48
- end
49
-
50
- it "should allow setting of values on an instance via field maps" do
51
- @person.attributes["Interests"] = "Coding"
52
- @person.attributes["Interests"].should == "Coding"
53
- end
54
-
55
- it "should map human map to API map" do
56
- attributes = {"Description" => "A description"}
57
-
58
- Person.map_human_attributes(attributes)["custom_description"].should == "A description"
59
- end
60
-
61
- it "should map API map to human map" do
62
- attributes = {:custom_description => "A description"}
63
-
64
- Person.map_api_attributes(attributes)["Description"].should == "A description"
65
- end
66
- end
67
-
68
- describe "Creating a record" do
69
- context "directly from create" do
70
- before do
71
- stub_http_response_with("contacts/create-success.json")
72
- @contact = Solve360::Contact.create("First Name" => "Catherine")
73
- end
74
-
75
- it "should be valid" do
76
- @contact.attributes["First Name"].should == "Catherine"
77
- @contact.id.should == 12345
78
- end
79
- end
80
-
81
- context "creating a new object then saving" do
82
- before do
83
- stub_http_response_with("contacts/create-success.json")
84
- @contact = Solve360::Contact.new("First Name" => "Catherine")
85
- @contact.save
86
- end
87
-
88
- it "should be valid" do
89
- @contact.id.should == 12345
90
- end
91
- end
92
- end
93
-
94
- describe "Finding a record" do
95
- context "Successfully" do
96
- before do
97
- stub_http_response_with("contacts/find-success.json")
98
- @contact = Solve360::Contact.find(12345)
99
- end
100
-
101
- it "should find existing user" do
102
- @contact.attributes["First Name"].should == "Henry"
103
- @contact.id.should == 12345
104
- end
105
-
106
- it "should have relations" do
107
- @contact.relations.first["name"].should == "Curve21"
108
- end
109
- end
110
- end
111
-
112
- describe "Updating a record" do
113
- before do
114
- @contact = Solve360::Contact.new("First Name" => "Steve")
115
-
116
- @contact.id = 12345
117
-
118
- stub_http_response_with("contacts/update-success.json")
119
-
120
- @contact.attributes["First Name"] = "Steve"
121
-
122
- @response = @contact.save
123
- end
124
-
125
- it "should be valid" do
126
- @response["response"]["status"].should == "success"
127
- end
128
- end