sugarcrm 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.6
1
+ 0.9.7
@@ -2,7 +2,6 @@ module SugarCRM
2
2
  # A class for handling association collections. Basically just an extension of Array
3
3
  # doesn't actually load the records from Sugar until you invoke one of the public methods
4
4
  class AssociationCollection
5
- include Enumerable
6
5
 
7
6
  # creates a new instance of an AssociationCollection
8
7
  # Owner is the parent object, and association is the target
@@ -32,18 +31,7 @@ module SugarCRM
32
31
  def reload
33
32
  load_associated_records
34
33
  end
35
-
36
- def each(&block)
37
- load
38
- @collection.each(&block)
39
- end
40
-
41
- # we should probably delegate this
42
- def length
43
- load
44
- @collection.length
45
- end
46
-
34
+
47
35
  # return any added elements
48
36
  def added
49
37
  load
@@ -83,6 +71,13 @@ module SugarCRM
83
71
  end
84
72
  alias :add :<<
85
73
 
74
+ # delegate undefined methods to the @collection array
75
+ # E.g. contact.cases should behave like an array and allow `length`, `size`, `each`, etc.
76
+ def method_missing(method_name, *args, &block)
77
+ load
78
+ @collection.send(method_name.to_sym, *args, &block)
79
+ end
80
+
86
81
  def save
87
82
  begin
88
83
  save!
@@ -123,14 +118,7 @@ module SugarCRM
123
118
  # user would be the owner, and EmailAddress.new() is the target
124
119
  def associate!(target, opts={})
125
120
  #target.save! if target.new?
126
- response = SugarCRM.connection.set_relationship(
127
- @owner.class._module.name, @owner.id,
128
- target.class._module.table_name, [target.id],
129
- opts
130
- )
131
- raise AssociationFailed,
132
- "Couldn't associate #{@owner.class._module.name}: #{@owner.id} -> #{target.class._module.table_name}:#{target.id}!" if response["failed"] > 0
133
- true
121
+ @owner.associate!(target, [target.id], opts)
134
122
  end
135
123
 
136
124
  # Removes a relationship between the current object and the target
@@ -20,6 +20,30 @@ module SugarCRM; module AssociationMethods
20
20
  false
21
21
  end
22
22
 
23
+ # Creates a relationship between the current object and the target
24
+ # The current instance and target records will have a relationship set
25
+ # i.e. account.associate!(contact) wyould link account and contact
26
+ # In contrast to using account.contacts << contact, this method doesn't load the relationships
27
+ # before setting the new relationship.
28
+ # This method is useful when certain modules have many links to other modules: not loading the
29
+ # relationships allows one ot avoid a Timeout::Error
30
+ def associate!(target, target_ids=[], opts={})
31
+ if self.class._module.custom_module? || target.class._module.custom_module?
32
+ link_field = get_link_field(target)
33
+ else
34
+ link_field = target.class._module.table_name
35
+ end
36
+ target_ids = [target.id] if target_ids.size < 1
37
+ response = SugarCRM.connection.set_relationship(
38
+ self.class._module.name, self.id,
39
+ link_field, target_ids,
40
+ opts
41
+ )
42
+ raise AssociationFailed,
43
+ "Couldn't associate #{self.class._module.name}: #{self.id} -> #{target.class._module.table_name}:#{target.id}!" if response["failed"] > 0
44
+ true
45
+ end
46
+
23
47
  protected
24
48
 
25
49
  def save_modified_associations
@@ -70,5 +94,15 @@ module SugarCRM; module AssociationMethods
70
94
  @association_cache[association] = collection
71
95
  collection
72
96
  end
97
+
98
+ # return the link field involving a relationship with a custom module
99
+ def get_link_field(other)
100
+ this_table_name = self.class._module.custom_module? ? self.class._module.name : self.class._module.table_name
101
+ that_table_name = other.class._module.custom_module? ? other.class._module.name : other.class._module.table_name
102
+ # the link field will contain the name of both modules
103
+ link_field = self.associations.detect{|a| a == [this_table_name, that_table_name].join('_') || a == [that_table_name, this_table_name].join('_')}
104
+ raise "Unable to determine link field between #{self.class._module.name}: #{self.id} and #{other.class._module.table_name}:#{other.id}" unless link_field
105
+ link_field
106
+ end
73
107
 
74
108
  end; end
data/lib/sugarcrm/base.rb CHANGED
@@ -41,12 +41,7 @@ module SugarCRM; class Base
41
41
  when :first
42
42
  find_initial(options)
43
43
  when :all
44
- results = find_every(options)
45
- if results
46
- Array.wrap(results)
47
- else
48
- []
49
- end
44
+ Array.wrap(find_every(options)).compact
50
45
  else
51
46
  find_from_ids(args, options)
52
47
  end
@@ -158,7 +153,7 @@ module SugarCRM; class Base
158
153
 
159
154
  def find_by_sql(options)
160
155
  query = query_from_options(options)
161
- SugarCRM.connection.get_entry_list(self._module.name, query, options)
156
+ SugarCRM.connection.get_entry_list(self._module.name, query, options) || nil # return nil instead of false if no results are found
162
157
  end
163
158
 
164
159
  def query_from_options(options)
@@ -342,6 +337,18 @@ module SugarCRM; class Base
342
337
  end
343
338
  alias :eql? :==
344
339
 
340
+ def update_attribute(name, value)
341
+ self.send("#{name}=".to_sym, value)
342
+ self.save
343
+ end
344
+
345
+ def update_attributes(attributes)
346
+ attributes.each do |name, value|
347
+ self.send("#{name}=".to_sym, value)
348
+ end
349
+ self.save
350
+ end
351
+
345
352
  # Delegates to id in order to allow two records of the same type and id to work with something like:
346
353
  # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
347
354
  def hash
@@ -20,7 +20,7 @@ module SugarCRM
20
20
  # custom attributes are contained in a table named after the module, with a '_cstm' suffix
21
21
  # the module's table name must be tableized for the modules that ship with SugarCRM
22
22
  # for custom modules (created in the Studio), table name don't need to be tableized: the name passed to the constructor is already tableized
23
- unless name.downcase == name # this module is a custom module (custom module names are all lower_case, whereas SugarCRM modules are CamelCase
23
+ unless self.custom_module?
24
24
  @custom_table_name = @table_name + "_cstm"
25
25
  else
26
26
  @custom_table_name = name + "_cstm"
@@ -32,6 +32,12 @@ module SugarCRM
32
32
  self
33
33
  end
34
34
 
35
+ # return true if this module was created in the SugarCRM Studio (i.e. it is not part of the modules that
36
+ # ship in the dfault SugarCRM configuration
37
+ def custom_module?
38
+ name.downcase == name # custom module names are all lower_case, whereas SugarCRM modules are CamelCase
39
+ end
40
+
35
41
  # Returns the fields associated with the module
36
42
  def fields
37
43
  return @fields if fields_registered?
@@ -4,6 +4,8 @@ class TestAssociations < Test::Unit::TestCase
4
4
  context "A SugarCRM::Base instance" do
5
5
  should "return an email address when sent #email_addresses" do
6
6
  u = SugarCRM::User.find("seed_sarah_id")
7
+ assert_instance_of SugarCRM::AssociationCollection, u.email_addresses
8
+ assert_instance_of SugarCRM::EmailAddress, u.email_addresses.first
7
9
  assert_equal "sarah@example.com", u.email_addresses.first.email_address
8
10
  end
9
11
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sugarcrm
3
3
  version: !ruby/object:Gem::Version
4
- hash: 55
4
+ hash: 53
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 6
10
- version: 0.9.6
9
+ - 7
10
+ version: 0.9.7
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: 2011-01-11 00:00:00 -08:00
18
+ date: 2011-01-15 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency