sugarcrm 0.8.2 → 0.9.0
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.rdoc +58 -19
- data/Rakefile +1 -4
- data/VERSION +1 -1
- data/lib/sugarcrm.rb +7 -4
- data/lib/sugarcrm/associations.rb +2 -0
- data/lib/sugarcrm/associations/association_collection.rb +143 -0
- data/lib/sugarcrm/associations/association_methods.rb +92 -0
- data/lib/sugarcrm/attributes.rb +4 -0
- data/lib/sugarcrm/attributes/attribute_methods.rb +131 -0
- data/lib/sugarcrm/attributes/attribute_serializers.rb +55 -0
- data/lib/sugarcrm/attributes/attribute_typecast.rb +39 -0
- data/lib/sugarcrm/attributes/attribute_validations.rb +37 -0
- data/lib/sugarcrm/base.rb +77 -21
- data/lib/sugarcrm/connection.rb +3 -137
- data/lib/sugarcrm/connection/api/get_entry_list.rb +1 -1
- data/lib/sugarcrm/connection/api/get_note_attachment.rb +0 -1
- data/lib/sugarcrm/connection/api/set_relationship.rb +3 -0
- data/lib/sugarcrm/connection/connection.rb +144 -0
- data/lib/sugarcrm/{request.rb → connection/request.rb} +2 -10
- data/lib/sugarcrm/{response.rb → connection/response.rb} +10 -4
- data/lib/sugarcrm/exceptions.rb +14 -26
- data/lib/sugarcrm/module.rb +19 -18
- data/test/connection/test_get_entry.rb +5 -5
- data/test/connection/test_get_module_fields.rb +1 -1
- data/test/connection/test_set_relationship.rb +13 -21
- data/test/helper.rb +1 -1
- data/test/test_association_collection.rb +12 -0
- data/test/test_associations.rb +33 -0
- data/test/test_connection.rb +0 -7
- data/test/test_module.rb +1 -1
- data/test/test_sugarcrm.rb +16 -8
- metadata +22 -28
- data/lib/sugarcrm/association_methods.rb +0 -46
- data/lib/sugarcrm/attribute_methods.rb +0 -170
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestAssociations < Test::Unit::TestCase
|
4
|
+
context "A SugarCRM::Base instance" do
|
5
|
+
should "return an email address when sent #email_addresses" do
|
6
|
+
u = SugarCRM::User.find("seed_sarah_id")
|
7
|
+
assert_equal "sarah@example.com", u.email_addresses.first.email_address
|
8
|
+
end
|
9
|
+
|
10
|
+
should "utilize the association cache" do
|
11
|
+
u = SugarCRM::User.find(1)
|
12
|
+
u.email_addresses
|
13
|
+
assert u.association_cached? :email_addresses
|
14
|
+
end
|
15
|
+
|
16
|
+
should "permit adding a record to an association collection (such as #meetings << Meeting.new)" do
|
17
|
+
u = SugarCRM::User.find(1)
|
18
|
+
m = SugarCRM::Meeting.new
|
19
|
+
m.date_start = DateTime.now
|
20
|
+
m.duration_hours = 0.5
|
21
|
+
m.name = "Yet Another Stupid Meeting"
|
22
|
+
u.meetings << m
|
23
|
+
assert u.meetings.include?(m)
|
24
|
+
assert_equal [m], u.meetings.added
|
25
|
+
assert u.save!
|
26
|
+
u = SugarCRM::User.find(1)
|
27
|
+
assert u.meetings.include?(m)
|
28
|
+
assert u.meetings.delete(m)
|
29
|
+
assert u.meetings.save!
|
30
|
+
assert !u.meetings.include?(m)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/test_connection.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
#require 'connection/test_login'
|
4
|
-
#require 'connection/test_get_available_modules'
|
5
|
-
#require 'connection/test_get_module_fields'
|
6
|
-
#require 'connection/test_get_entry'
|
7
|
-
#require 'connection/test_get_entries'
|
8
|
-
#require 'connection/test_get_entry_list'
|
9
|
-
|
10
3
|
class TestConnection < Test::Unit::TestCase
|
11
4
|
context "A SugarCRM::Connection instance" do
|
12
5
|
setup do
|
data/test/test_module.rb
CHANGED
@@ -12,7 +12,7 @@ class TestModule < Test::Unit::TestCase
|
|
12
12
|
end
|
13
13
|
|
14
14
|
should "return required fields when #required_fields" do
|
15
|
-
assert SugarCRM::User._module.required_fields.include?
|
15
|
+
assert SugarCRM::User._module.required_fields.include? :user_name
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/test/test_sugarcrm.rb
CHANGED
@@ -17,6 +17,10 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
17
17
|
assert_equal "Users", SugarCRM::User._module.name
|
18
18
|
end
|
19
19
|
|
20
|
+
should "return the module fields" do
|
21
|
+
assert_instance_of ActiveSupport::HashWithIndifferentAccess, SugarCRM::Account._module.fields
|
22
|
+
end
|
23
|
+
|
20
24
|
should "responsd to self#methods" do
|
21
25
|
assert_instance_of Array, SugarCRM::User.new.methods
|
22
26
|
end
|
@@ -48,9 +52,11 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
48
52
|
end
|
49
53
|
|
50
54
|
should "not save a record that is missing required attributes" do
|
55
|
+
SugarCRM.connection.debug = false
|
51
56
|
u = SugarCRM::User.new
|
52
57
|
u.last_name = "Test"
|
53
58
|
assert !u.save
|
59
|
+
SugarCRM.connection.debug = false
|
54
60
|
assert_raise SugarCRM::InvalidRecord do
|
55
61
|
u.save!
|
56
62
|
end
|
@@ -67,6 +73,7 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
67
73
|
u.status = "Active"
|
68
74
|
assert_equal "Test", u.modified_attributes[:first_name][:new]
|
69
75
|
assert u.save!
|
76
|
+
assert !u.new?
|
70
77
|
m = SugarCRM::User.find_by_first_name_and_last_name("Test", "User")
|
71
78
|
m.title = "Test User"
|
72
79
|
assert m.save!
|
@@ -74,13 +81,19 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
74
81
|
#SugarCRM.connection.debug = false
|
75
82
|
end
|
76
83
|
|
84
|
+
should "support finding first instance (sorted by attribute)" do
|
85
|
+
account = SugarCRM::Account.first({
|
86
|
+
:order_by => 'name'
|
87
|
+
})
|
88
|
+
assert_instance_of SugarCRM::Account, account
|
89
|
+
end
|
90
|
+
|
77
91
|
should "support searching based on conditions" do
|
78
92
|
accounts = SugarCRM::Account.all({
|
79
|
-
:conditions => { :billing_address_postalcode => ["> '70000'", "< '
|
93
|
+
:conditions => { :billing_address_postalcode => ["> '70000'", "< '79999'" ] },
|
80
94
|
:limit => '10',
|
81
95
|
:order_by => 'billing_address_postalcode'
|
82
96
|
})
|
83
|
-
assert_instance_of Array, accounts
|
84
97
|
assert_instance_of SugarCRM::Account, accounts.first
|
85
98
|
end
|
86
99
|
|
@@ -93,11 +106,6 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
93
106
|
assert_equal u.user_name, "admin"
|
94
107
|
end
|
95
108
|
|
96
|
-
should "return an email address when sent #email_addresses" do
|
97
|
-
u = SugarCRM::User.find("seed_sarah_id")
|
98
|
-
assert_equal "sarah@example.com", u.email_addresses.first.email_address
|
99
|
-
end
|
100
|
-
|
101
109
|
should "return an array of records when sent #find([id1, id2, id3])" do
|
102
110
|
users = SugarCRM::User.find(["seed_sarah_id", 1])
|
103
111
|
assert_equal "Administrator", users.last.title
|
@@ -107,7 +115,7 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
107
115
|
u = SugarCRM::User.find_by_user_name("sarah")
|
108
116
|
assert_equal "sarah@example.com", u.email_addresses.first.email_address
|
109
117
|
end
|
110
|
-
|
118
|
+
|
111
119
|
end
|
112
120
|
|
113
121
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Carl Hicks
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-29 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -32,24 +32,10 @@ dependencies:
|
|
32
32
|
version: "0"
|
33
33
|
type: :development
|
34
34
|
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: json
|
37
|
-
prerelease: false
|
38
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 3
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
47
|
-
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
35
|
- !ruby/object:Gem::Dependency
|
50
36
|
name: activesupport
|
51
37
|
prerelease: false
|
52
|
-
requirement: &
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
53
39
|
none: false
|
54
40
|
requirements:
|
55
41
|
- - ">="
|
@@ -60,11 +46,8 @@ dependencies:
|
|
60
46
|
- 0
|
61
47
|
version: "3.0"
|
62
48
|
type: :runtime
|
63
|
-
version_requirements: *
|
64
|
-
description:
|
65
|
-
I've implemented all of the basic API calls that SugarCRM supports, and am actively building an abstraction layer
|
66
|
-
on top of the basic API methods. The end result will be to provide ActiveRecord style finders and first class
|
67
|
-
objects. Some of this functionality is included today.
|
49
|
+
version_requirements: *id002
|
50
|
+
description: "A less clunky way to interact with SugarCRM via REST. Instead of SugarCRM.connection.get_entry(\"Users\", \"1\") you could use SugarCRM::User.find(1). There is support for collections \xC3\xA0 la SugarCRM::User.find(1).email_addresses, or SugarCRM::Contact.first.meetings << new_meeting. ActiveRecord style finders are in place, with limited support for conditions and joins."
|
68
51
|
email: carl.hicks@gmail.com
|
69
52
|
executables: []
|
70
53
|
|
@@ -80,8 +63,14 @@ files:
|
|
80
63
|
- Rakefile
|
81
64
|
- VERSION
|
82
65
|
- lib/sugarcrm.rb
|
83
|
-
- lib/sugarcrm/
|
84
|
-
- lib/sugarcrm/
|
66
|
+
- lib/sugarcrm/associations.rb
|
67
|
+
- lib/sugarcrm/associations/association_collection.rb
|
68
|
+
- lib/sugarcrm/associations/association_methods.rb
|
69
|
+
- lib/sugarcrm/attributes.rb
|
70
|
+
- lib/sugarcrm/attributes/attribute_methods.rb
|
71
|
+
- lib/sugarcrm/attributes/attribute_serializers.rb
|
72
|
+
- lib/sugarcrm/attributes/attribute_typecast.rb
|
73
|
+
- lib/sugarcrm/attributes/attribute_validations.rb
|
85
74
|
- lib/sugarcrm/base.rb
|
86
75
|
- lib/sugarcrm/connection.rb
|
87
76
|
- lib/sugarcrm/connection/api/get_available_modules.rb
|
@@ -108,13 +97,14 @@ files:
|
|
108
97
|
- lib/sugarcrm/connection/api/set_note_attachment.rb
|
109
98
|
- lib/sugarcrm/connection/api/set_relationship.rb
|
110
99
|
- lib/sugarcrm/connection/api/set_relationships.rb
|
100
|
+
- lib/sugarcrm/connection/connection.rb
|
111
101
|
- lib/sugarcrm/connection/helper.rb
|
102
|
+
- lib/sugarcrm/connection/request.rb
|
103
|
+
- lib/sugarcrm/connection/response.rb
|
112
104
|
- lib/sugarcrm/dynamic_finder_match.rb
|
113
105
|
- lib/sugarcrm/exceptions.rb
|
114
106
|
- lib/sugarcrm/module.rb
|
115
107
|
- lib/sugarcrm/module_methods.rb
|
116
|
-
- lib/sugarcrm/request.rb
|
117
|
-
- lib/sugarcrm/response.rb
|
118
108
|
- test/connection/test_get_available_modules.rb
|
119
109
|
- test/connection/test_get_entries.rb
|
120
110
|
- test/connection/test_get_entry.rb
|
@@ -128,6 +118,8 @@ files:
|
|
128
118
|
- test/connection/test_logout.rb
|
129
119
|
- test/connection/test_set_relationship.rb
|
130
120
|
- test/helper.rb
|
121
|
+
- test/test_association_collection.rb
|
122
|
+
- test/test_associations.rb
|
131
123
|
- test/test_connection.rb
|
132
124
|
- test/test_module.rb
|
133
125
|
- test/test_response.rb
|
@@ -180,6 +172,8 @@ test_files:
|
|
180
172
|
- test/connection/test_logout.rb
|
181
173
|
- test/connection/test_set_relationship.rb
|
182
174
|
- test/helper.rb
|
175
|
+
- test/test_association_collection.rb
|
176
|
+
- test/test_associations.rb
|
183
177
|
- test/test_connection.rb
|
184
178
|
- test/test_module.rb
|
185
179
|
- test/test_response.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module SugarCRM; module AssociationMethods
|
2
|
-
|
3
|
-
module ClassMethods
|
4
|
-
# Returns an array of the module link fields
|
5
|
-
def associations_from_module_link_fields
|
6
|
-
self._module.link_fields.keys
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
# Generates the association proxy methods for related modules
|
11
|
-
def define_association_methods
|
12
|
-
return if association_methods_generated?
|
13
|
-
@associations.each do |k|
|
14
|
-
self.class.module_eval %Q?
|
15
|
-
def #{k}
|
16
|
-
query_association :#{k}
|
17
|
-
end
|
18
|
-
def #{k}=(value)
|
19
|
-
update_association :#{k},value
|
20
|
-
end
|
21
|
-
?
|
22
|
-
end
|
23
|
-
self.class.association_methods_generated = true
|
24
|
-
end
|
25
|
-
|
26
|
-
#
|
27
|
-
# {"email_addresses"=>
|
28
|
-
# {"name"=>"email_addresses",
|
29
|
-
# "module"=>"EmailAddress",
|
30
|
-
# "bean_name"=>"EmailAddress",
|
31
|
-
# "relationship"=>"users_email_addresses",
|
32
|
-
# "type"=>"link"},
|
33
|
-
#
|
34
|
-
def query_association(association)
|
35
|
-
collection = SugarCRM.connection.get_relationships(
|
36
|
-
self.class._module.name,
|
37
|
-
self.id,
|
38
|
-
association.to_s
|
39
|
-
)
|
40
|
-
end
|
41
|
-
|
42
|
-
def update_association(association, value)
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
end; end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
module SugarCRM; module AttributeMethods
|
2
|
-
|
3
|
-
module ClassMethods
|
4
|
-
# Returns a hash of the module fields from the module
|
5
|
-
def attributes_from_module_fields
|
6
|
-
fields = {}.with_indifferent_access
|
7
|
-
self._module.fields.keys.sort.each do |k|
|
8
|
-
fields[k.to_s] = nil
|
9
|
-
end
|
10
|
-
fields
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Determines if attributes have been changed
|
15
|
-
def changed?
|
16
|
-
@modified_attributes.length > 0
|
17
|
-
end
|
18
|
-
|
19
|
-
# Is this a new record?
|
20
|
-
def new?
|
21
|
-
@id.blank?
|
22
|
-
end
|
23
|
-
|
24
|
-
# Converts the attributes hash into format recognizable by Sugar
|
25
|
-
# { :last_name => "Smith"}
|
26
|
-
# becomes
|
27
|
-
# { :last_name => {:name => "last_name", :value => "Smith"}}
|
28
|
-
def serialize_attributes
|
29
|
-
attr_hash = {}
|
30
|
-
@attributes.each_pair do |name,value|
|
31
|
-
attr_hash[name] = serialize_attribute(name,value)
|
32
|
-
end
|
33
|
-
attr_hash[:id] = serialize_id unless new?
|
34
|
-
attr_hash
|
35
|
-
end
|
36
|
-
|
37
|
-
# Converts the modified_attributes hash into format recognizable by Sugar
|
38
|
-
# { :last_name => {:old => "Smit", :new => "Smith"}}
|
39
|
-
# becomes
|
40
|
-
# { :last_name => {:name => "last_name", :value => "Smith"}}
|
41
|
-
def serialize_modified_attributes
|
42
|
-
attr_hash = {}
|
43
|
-
@modified_attributes.each_pair do |name,hash|
|
44
|
-
attr_hash[name] = serialize_attribute(name,hash[:new])
|
45
|
-
end
|
46
|
-
attr_hash[:id] = serialize_id unless new?
|
47
|
-
attr_hash
|
48
|
-
end
|
49
|
-
|
50
|
-
# Checks to see if we have all the neccessary attributes
|
51
|
-
def valid?
|
52
|
-
valid = true
|
53
|
-
self.class._module.required_fields.each do |attribute|
|
54
|
-
case attr_type_for(attribute)
|
55
|
-
when "bool"
|
56
|
-
case @attributes[attribute]
|
57
|
-
when TrueClass
|
58
|
-
next
|
59
|
-
when FalseClass
|
60
|
-
next
|
61
|
-
else
|
62
|
-
@errors.add "#{attribute} must be true or false"
|
63
|
-
valid = false
|
64
|
-
end
|
65
|
-
else
|
66
|
-
if @attributes[attribute].blank?
|
67
|
-
@errors.add "#{attribute} cannot be blank"
|
68
|
-
valid = false
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
valid
|
73
|
-
end
|
74
|
-
|
75
|
-
# List the required attributes for save
|
76
|
-
def required_attributes
|
77
|
-
self.class._module.required_fields
|
78
|
-
end
|
79
|
-
|
80
|
-
# Serializes the id
|
81
|
-
def serialize_id
|
82
|
-
{:name => "id", :value => @id.to_s}
|
83
|
-
end
|
84
|
-
|
85
|
-
# Un-typecasts the attribute - false becomes 0
|
86
|
-
def serialize_attribute(name,value)
|
87
|
-
attr_value = value
|
88
|
-
case attr_type_for(name)
|
89
|
-
when "bool"
|
90
|
-
attr_value = 0
|
91
|
-
attr_value = 1 if value
|
92
|
-
end
|
93
|
-
{:name => name, :value => attr_value}
|
94
|
-
end
|
95
|
-
|
96
|
-
# Generates get/set methods for keys in the attributes hash
|
97
|
-
def define_attribute_methods
|
98
|
-
return if attribute_methods_generated?
|
99
|
-
@attributes.each_pair do |k,v|
|
100
|
-
self.class.module_eval %Q?
|
101
|
-
def #{k}
|
102
|
-
read_attribute :#{k}
|
103
|
-
end
|
104
|
-
def #{k}=(value)
|
105
|
-
write_attribute :#{k},value
|
106
|
-
end
|
107
|
-
?
|
108
|
-
end
|
109
|
-
self.class.attribute_methods_generated = true
|
110
|
-
end
|
111
|
-
|
112
|
-
# Returns an <tt>#inspect</tt>-like string for the value of the
|
113
|
-
# attribute +attr_name+. String attributes are elided after 50
|
114
|
-
# characters, and Date and Time attributes are returned in the
|
115
|
-
# <tt>:db</tt> format. Other attributes return the value of
|
116
|
-
# <tt>#inspect</tt> without modification.
|
117
|
-
#
|
118
|
-
# person = Person.create!(:name => "David Heinemeier Hansson " * 3)
|
119
|
-
#
|
120
|
-
# person.attribute_for_inspect(:name)
|
121
|
-
# # => '"David Heinemeier Hansson David Heinemeier Hansson D..."'
|
122
|
-
#
|
123
|
-
# person.attribute_for_inspect(:created_at)
|
124
|
-
# # => '"2009-01-12 04:48:57"'
|
125
|
-
def attribute_for_inspect(attr_name)
|
126
|
-
value = read_attribute(attr_name)
|
127
|
-
if value.is_a?(String) && value.length > 50
|
128
|
-
"#{value[0..50]}...".inspect
|
129
|
-
elsif value.is_a?(Date) || value.is_a?(Time)
|
130
|
-
%("#{value.to_s(:db)}")
|
131
|
-
else
|
132
|
-
value.inspect
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
protected
|
137
|
-
|
138
|
-
# Returns the attribute type for a given attribute
|
139
|
-
def attr_type_for(attribute)
|
140
|
-
field = self.class._module.fields[attribute]
|
141
|
-
return false unless field
|
142
|
-
field["type"]
|
143
|
-
end
|
144
|
-
|
145
|
-
# Attempts to typecast each attribute based on the module field type
|
146
|
-
def typecast_attributes
|
147
|
-
@attributes.each_pair do |name,value|
|
148
|
-
attr_type = attr_type_for(name)
|
149
|
-
next unless attr_type
|
150
|
-
case attr_type
|
151
|
-
when "bool"
|
152
|
-
@attributes[name] = (value == "1")
|
153
|
-
end
|
154
|
-
end
|
155
|
-
@attributes
|
156
|
-
end
|
157
|
-
|
158
|
-
# Wrapper around attributes hash
|
159
|
-
def read_attribute(key)
|
160
|
-
@attributes[key]
|
161
|
-
end
|
162
|
-
|
163
|
-
# Wrapper around attributes hash
|
164
|
-
def write_attribute(key, value)
|
165
|
-
@modified_attributes[key] = { :old => @attributes[key].to_s, :new => value }
|
166
|
-
@attributes[key] = value
|
167
|
-
end
|
168
|
-
|
169
|
-
end; end
|
170
|
-
|