sugarcrm 0.8.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|