sugarcrm 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/README.rdoc +58 -19
  2. data/Rakefile +1 -4
  3. data/VERSION +1 -1
  4. data/lib/sugarcrm.rb +7 -4
  5. data/lib/sugarcrm/associations.rb +2 -0
  6. data/lib/sugarcrm/associations/association_collection.rb +143 -0
  7. data/lib/sugarcrm/associations/association_methods.rb +92 -0
  8. data/lib/sugarcrm/attributes.rb +4 -0
  9. data/lib/sugarcrm/attributes/attribute_methods.rb +131 -0
  10. data/lib/sugarcrm/attributes/attribute_serializers.rb +55 -0
  11. data/lib/sugarcrm/attributes/attribute_typecast.rb +39 -0
  12. data/lib/sugarcrm/attributes/attribute_validations.rb +37 -0
  13. data/lib/sugarcrm/base.rb +77 -21
  14. data/lib/sugarcrm/connection.rb +3 -137
  15. data/lib/sugarcrm/connection/api/get_entry_list.rb +1 -1
  16. data/lib/sugarcrm/connection/api/get_note_attachment.rb +0 -1
  17. data/lib/sugarcrm/connection/api/set_relationship.rb +3 -0
  18. data/lib/sugarcrm/connection/connection.rb +144 -0
  19. data/lib/sugarcrm/{request.rb → connection/request.rb} +2 -10
  20. data/lib/sugarcrm/{response.rb → connection/response.rb} +10 -4
  21. data/lib/sugarcrm/exceptions.rb +14 -26
  22. data/lib/sugarcrm/module.rb +19 -18
  23. data/test/connection/test_get_entry.rb +5 -5
  24. data/test/connection/test_get_module_fields.rb +1 -1
  25. data/test/connection/test_set_relationship.rb +13 -21
  26. data/test/helper.rb +1 -1
  27. data/test/test_association_collection.rb +12 -0
  28. data/test/test_associations.rb +33 -0
  29. data/test/test_connection.rb +0 -7
  30. data/test/test_module.rb +1 -1
  31. data/test/test_sugarcrm.rb +16 -8
  32. metadata +22 -28
  33. data/lib/sugarcrm/association_methods.rb +0 -46
  34. 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
@@ -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
@@ -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? "user_name"
15
+ assert SugarCRM::User._module.required_fields.include? :user_name
16
16
  end
17
17
  end
18
18
  end
@@ -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'", "< '72000'" ] },
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
- - 8
9
- - 2
10
- version: 0.8.2
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-14 00:00:00 -08:00
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: &id003 !ruby/object:Gem::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: *id003
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/association_methods.rb
84
- - lib/sugarcrm/attribute_methods.rb
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
-