sugarcrm 0.9.12 → 0.9.13

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -38,7 +38,10 @@ A less clunky way to interact with SugarCRM via REST.
38
38
  SugarCRM.modules
39
39
 
40
40
  # Retrieve a User by user_name
41
- SugarCRM::User.find_by_user_name("admin")
41
+ users = SugarCRM::User.find_by_user_name("admin")
42
+
43
+ # Return a User instance's SugarCRM URL (also works for any other module instance)
44
+ users.url
42
45
 
43
46
  # Update a User's title
44
47
  u = SugarCRM::User.find_by_first_name_and_last_name("Will", "Westin")
@@ -95,6 +98,9 @@ A less clunky way to interact with SugarCRM via REST.
95
98
  a.contacts.delete(c)
96
99
  a.save # or a.contacts.save
97
100
 
101
+ # Retrieve the number of accounts in CRM with 'Inc' in their name
102
+ SugarCRM::Account.count(:conditions => {:name => "LIKE '%Inc'"})
103
+
98
104
  # Look up the Case with the smallest case number
99
105
  SugarCRM::Case.first({
100
106
  :order_by => 'case_number'
@@ -116,6 +122,12 @@ A less clunky way to interact with SugarCRM via REST.
116
122
  SugarCRM::Account.all({
117
123
  :conditions => { :name => "LIKE '%Fund%'" } # note that SQL operators must be uppercase
118
124
  })
125
+
126
+ # Use block to iterate over results: print all account names
127
+ SugarCRM::Account.all{|a| puts a.name } # note: this method will be much quicker than SugarCRM::Account.all.each{|a| puts a.name }
128
+ # because records are passed to the block as they get fetched from SugarCRM (whereas `each`
129
+ # will fetch all records, and only then pass them to the block). This will make a major difference
130
+ # in resource use and execution time if you're dealing with many records.
119
131
 
120
132
  # Look up the fields for a given module
121
133
  SugarCRM::Module.find("Accounts").fields
@@ -149,7 +161,9 @@ Note: this gem requires Rails 3 as it depends on Active Support >= 3.
149
161
  4. Run `rails g sugarcrm:config`
150
162
  5. Edit the configuration file in `config/sugarcrm.yml` to match your environment
151
163
 
152
- Example app here: https://github.com/davidsulc/sugar_on_rails_basic
164
+ Example apps:
165
+ * https://github.com/davidsulc/sugar_on_rails_basic
166
+ * https://github.com/davidsulc/dev_zone_basic_rails_app
153
167
 
154
168
  == USING A CONFIGURATION FILE
155
169
 
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ Jeweler::Tasks.new do |gem|
18
18
  gem.homepage = "http://github.com/chicks/sugarcrm"
19
19
  gem.authors = ["Carl Hicks", "David Sulc"]
20
20
  gem.executables = ['sugarcrm']
21
- gem.files = FileList['./lib/**/*', './*'].exclude("*.lock").to_a
21
+ gem.files = FileList['./lib/**/*', './*'].exclude("*.lock", "*.tmproj").to_a
22
22
  end
23
23
  Jeweler::RubygemsDotOrgTasks.new
24
24
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.12
1
+ 0.9.13
@@ -145,7 +145,7 @@ module SugarCRM; module AttributeMethods
145
145
  # sets the id if it's a new record
146
146
  def save_modified_attributes!
147
147
  # Complain if we aren't valid
148
- raise InvalidRecord, errors.to_a.join(", ") if !valid?
148
+ raise InvalidRecord, @errors.full_messages.join(", ") unless valid?
149
149
  # Send the save request
150
150
  response = self.class.session.connection.set_entry(self.class._module.name, serialize_modified_attributes)
151
151
  # Complain if we don't get a parseable response back
@@ -1,11 +1,30 @@
1
1
  module SugarCRM; module AttributeValidations
2
2
  # Checks to see if we have all the neccessary attributes
3
3
  def valid?
4
- @errors = Set.new
4
+ @errors = ActiveSupport::HashWithIndifferentAccess.new
5
+
5
6
  self.class._module.required_fields.each do |attribute|
6
7
  valid_attribute?(attribute)
7
8
  end
8
- @errors.length == 0
9
+
10
+ # for rails compatibility
11
+ def @errors.full_messages
12
+ # After removing attributes without errors, flatten the error hash, repeating the name of the attribute before each message:
13
+ # e.g. {'name' => ['cannot be blank', 'is too long'], 'website' => ['is not valid']}
14
+ # will become 'name cannot be blank, name is too long, website is not valid
15
+ self.inject([]){|memo, obj| memo.concat(obj[1].inject([]){|m, o| m << "#{obj[0].to_s.humanize} #{o}" })}
16
+ end
17
+
18
+ # Rails needs each attribute to be present in the error hash (if the attribute has no error, it has [] as a value)
19
+ # Redefine the [] method for the errors hash to return [] instead of nil is the hash doesn't contain the key
20
+ class << @errors
21
+ alias :old_key_lookup :[]
22
+ def [](key)
23
+ old_key_lookup(key) || Array.new
24
+ end
25
+ end
26
+
27
+ @errors.size == 0
9
28
  end
10
29
 
11
30
  protected
@@ -21,7 +40,7 @@ module SugarCRM; module AttributeValidations
21
40
  validate_class_for(attribute, [Fixnum, Float])
22
41
  else
23
42
  if @attributes[attribute].blank?
24
- @errors.add "#{attribute} cannot be blank"
43
+ add_error(attribute, "cannot be blank")
25
44
  end
26
45
  end
27
46
  end
@@ -30,8 +49,14 @@ module SugarCRM; module AttributeValidations
30
49
  # returns true if they match, otherwise adds an entry to the @errors collection, and returns false
31
50
  def validate_class_for(attribute, class_array)
32
51
  return true if class_array.include? @attributes[attribute].class
33
- @errors.add "#{attribute} must be a #{class_array.join(" or ")} object (not #{@attributes[attribute].class})"
52
+ add_error(attribute, "must be a #{class_array.join(" or ")} object (not #{@attributes[attribute].class})")
34
53
  false
35
54
  end
36
55
 
56
+ # Add an error to the hash
57
+ def add_error(attribute, message)
58
+ @errors[attribute] ||= []
59
+ @errors[attribute] = @errors[attribute] << message unless @errors[attribute].include? message
60
+ @errors
61
+ end
37
62
  end; end
data/lib/sugarcrm/base.rb CHANGED
@@ -25,7 +25,7 @@ module SugarCRM; class Base
25
25
  attr :errors, true
26
26
 
27
27
  class << self # Class methods
28
- def find(*args)
28
+ def find(*args, &block)
29
29
  options = args.extract_options!
30
30
  options = {:order_by => 'date_entered'}.merge(options)
31
31
  validate_find_options(options)
@@ -35,39 +35,44 @@ module SugarCRM; class Base
35
35
  find_initial(options)
36
36
  when :last
37
37
  begin
38
- options[:order_by] = reverse_order_clause(options[:order_by])
38
+ options[:order_by] = reverse_order_clause(options[:order_by].to_s)
39
39
  rescue Exception => e
40
40
  raise
41
41
  end
42
42
  find_initial(options)
43
43
  when :all
44
- Array.wrap(find_every(options)).compact
44
+ Array.wrap(find_every(options, &block)).compact
45
45
  else
46
- find_from_ids(args, options)
46
+ find_from_ids(args, options, &block)
47
47
  end
48
48
  end
49
49
 
50
50
  # return the connection to the correct SugarCRM server (there can be several)
51
51
  def connection
52
- self.parent.session.connection
52
+ self.session.connection
53
+ end
54
+
55
+ def count(options={})
56
+ query = query_from_options(options)
57
+ connection.get_entries_count(self._module.name, query, options)['result_count'].to_i
53
58
  end
54
59
 
55
60
  # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
56
61
  # same arguments to this method as you can to <tt>find(:first)</tt>.
57
- def first(*args)
58
- find(:first, *args)
62
+ def first(*args, &block)
63
+ find(:first, *args, &block)
59
64
  end
60
65
 
61
66
  # A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
62
67
  # same arguments to this method as you can to <tt>find(:last)</tt>.
63
- def last(*args)
64
- find(:last, *args)
68
+ def last(*args, &block)
69
+ find(:last, *args, &block)
65
70
  end
66
71
 
67
72
  # This is an alias for find(:all). You can pass in all the same arguments to this method as you can
68
73
  # to find(:all)
69
- def all(*args)
70
- find(:all, *args)
74
+ def all(*args, &block)
75
+ find(:all, *args, &block)
71
76
  end
72
77
 
73
78
  # Creates an object (or multiple objects) and saves it to SugarCRM if validations pass.
@@ -102,11 +107,11 @@ module SugarCRM; class Base
102
107
  object
103
108
  end
104
109
  end
105
-
106
110
  end
107
111
 
108
112
  # Creates an instance of a Module Class, i.e. Account, User, Contact, etc.
109
113
  def initialize(attributes={}, &block)
114
+ @errors = {}
110
115
  @modified_attributes = {}
111
116
  merge_attributes(attributes.with_indifferent_access)
112
117
  clear_association_cache
@@ -131,7 +136,7 @@ module SugarCRM; class Base
131
136
  # Saves the current object, checks that required fields are present.
132
137
  # returns true or false
133
138
  def save
134
- return false if !changed?
139
+ return false if !(new_record? || changed?)
135
140
  return false if !valid?
136
141
  begin
137
142
  save!
@@ -156,6 +161,12 @@ module SugarCRM; class Base
156
161
  params[:deleted]= {:name => "deleted", :value => "1"}
157
162
  @attributes[:deleted] = (self.class.connection.set_entry(self.class._module.name, params).class == Hash)
158
163
  end
164
+ alias :destroy :delete
165
+
166
+ # Returns if the record is persisted, i.e. it’s not a new record and it was not destroyed
167
+ def persisted?
168
+ !(new_record? || destroyed?)
169
+ end
159
170
 
160
171
  # Reloads the record from SugarCRM
161
172
  def reload!
@@ -178,16 +189,39 @@ module SugarCRM; class Base
178
189
  end
179
190
  alias :eql? :==
180
191
 
181
- def update_attribute(name, value)
192
+ def update_attribute!(name, value)
182
193
  self.send("#{name}=".to_sym, value)
183
- self.save
194
+ self.save!
184
195
  end
185
196
 
186
- def update_attributes(attributes)
197
+ def update_attribute(name, value)
198
+ begin
199
+ update_attribute!(name, value)
200
+ rescue
201
+ return false
202
+ end
203
+ true
204
+ end
205
+
206
+ def update_attributes!(attributes)
187
207
  attributes.each do |name, value|
188
208
  self.send("#{name}=".to_sym, value)
189
209
  end
190
- self.save
210
+ self.save!
211
+ end
212
+
213
+ def update_attributes(attributes)
214
+ begin
215
+ update_attributes!(attributes)
216
+ rescue
217
+ return false
218
+ end
219
+ true
220
+ end
221
+
222
+ # Returns the URL (in string format) where the module instance is available in CRM
223
+ def url
224
+ "#{SugarCRM.session.config[:base_url]}/index.php?module=#{self.class._module}&action=DetailView&record=#{self.id}"
191
225
  end
192
226
 
193
227
  # Delegates to id in order to allow two records of the same type and id to work with something like:
@@ -197,7 +231,7 @@ module SugarCRM; class Base
197
231
  end
198
232
 
199
233
  def pretty_print(pp)
200
- pp.text self.inspect, 0
234
+ pp.text self.inspect.to_s, 0
201
235
  end
202
236
 
203
237
  def attribute_methods_generated?
@@ -208,6 +242,31 @@ module SugarCRM; class Base
208
242
  self.class.association_methods_generated
209
243
  end
210
244
 
245
+ def to_key
246
+ new_record? ? nil : [ id ]
247
+ end
248
+
249
+ def to_param
250
+ id.to_s
251
+ end
252
+
253
+ def is_a?(klass)
254
+ superclasses.include? klass
255
+ end
256
+ alias :kind_of? :is_a?
257
+ alias :=== :is_a?
258
+
259
+ private
260
+ def superclasses
261
+ return @superclasses if @superclasses
262
+ @superclasses = [self.class]
263
+ current_class = self.class
264
+ while current_class.respond_to? :superclass
265
+ @superclasses << (current_class = current_class.superclass)
266
+ end
267
+ @superclasses
268
+ end
269
+
211
270
  Base.class_eval do
212
271
  extend FinderMethods::ClassMethods
213
272
  include AttributeMethods
@@ -21,6 +21,10 @@ module SugarCRM; class Request
21
21
  self
22
22
  end
23
23
 
24
+ def bytesize
25
+ self.to_s.bytesize
26
+ end
27
+
24
28
  def length
25
29
  self.to_s.length
26
30
  end
@@ -80,6 +80,7 @@ module SugarCRM; class Response
80
80
  # Takes a hash like { "first_name" => {"name" => "first_name", "value" => "John"}}
81
81
  # And flattens it into {"first_name" => "John"}
82
82
  def flatten(list)
83
+ raise ArgumentError, list[0]['value'] if list[0] && list[0]['name'] == 'warning'
83
84
  raise ArgumentError, 'method parameter must respond to #each_pair' unless list.respond_to? :each_pair
84
85
  flat_list = {}
85
86
  list.each_pair do |k,v|
@@ -11,7 +11,7 @@ module SugarCRM; class ConnectionPool
11
11
  # The mutex used to synchronize pool access
12
12
  @connection_mutex = Monitor.new
13
13
  @queue = @connection_mutex.new_cond
14
- @timeout = config_timeout || 5
14
+ @timeout = config_timeout || 10
15
15
 
16
16
  # default max pool size to 5
17
17
  @size = config_pool_size || default_pool_size
@@ -8,7 +8,7 @@ module SugarCRM; module FinderMethods
8
8
  result
9
9
  end
10
10
 
11
- def find_from_ids(ids, options)
11
+ def find_from_ids(ids, options, &block)
12
12
  expects_array = ids.first.kind_of?(Array)
13
13
  return ids.first if expects_array && ids.first.empty?
14
14
 
@@ -21,7 +21,7 @@ module SugarCRM; module FinderMethods
21
21
  result = find_one(ids.first, options)
22
22
  expects_array ? [ result ] : result
23
23
  else
24
- find_some(ids, options)
24
+ find_some(ids, options, &block)
25
25
  end
26
26
  end
27
27
 
@@ -34,7 +34,7 @@ module SugarCRM; module FinderMethods
34
34
  end
35
35
  end
36
36
 
37
- def find_some(ids, options)
37
+ def find_some(ids, options, &block)
38
38
  result = connection.get_entries(self._module.name, ids, {:fields => self._module.fields.keys})
39
39
 
40
40
  # Determine expected size from limit and offset, not just ids.size.
@@ -51,67 +51,73 @@ module SugarCRM; module FinderMethods
51
51
  end
52
52
 
53
53
  if result.size == expected_size
54
+ if block_given?
55
+ result.each{|r|
56
+ yield r
57
+ }
58
+ end
54
59
  result
55
60
  else
56
61
  raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions} (found #{result.size} results, but was looking for #{expected_size})"
57
62
  end
58
63
  end
59
64
 
60
- def find_every(options)
61
- find_by_sql(options)
65
+ def find_every(options, &block)
66
+ find_by_sql(options, &block)
62
67
  end
63
-
64
- def find_by_sql(options)
65
- # SugarCRM REST API has a bug where, when :limit and :offset options are passed simultaneously, :limit is considered to be the smallest of the two, and :offset is the larger
66
- # in addition to allowing querying of large datasets while avoiding timeouts,
68
+
69
+ # the number of records we retrieve with each query
70
+ # it is kept small to avoid timeout issues
71
+ SLICE_SIZE = 5
72
+ SLICE_SIZE.freeze
73
+ # results accumulator stores the results we have fetched so far, recursively
74
+ def find_by_sql(options, results_accumulator=nil, &block)
75
+ # SugarCRM REST API has a bug where, when :limit and :offset options are passed simultaneously,
76
+ # :limit is considered to be the smallest of the two, and :offset is the larger
77
+ # In addition to allowing querying of large datasets while avoiding timeouts (by fetching results in small slices),
67
78
  # this implementation fixes the :limit - :offset bug so that it behaves correctly
79
+
80
+ offset = options[:offset].to_i >= 1 ? options[:offset].to_i : nil
81
+
82
+ # if many results are requested (i.e. multiple result slices), we call this function recursively
83
+ # this array keeps track of which slice we are retrieving (by updating the :offset and :limit options)
68
84
  local_options = {}
69
- options.keys.each{|k|
70
- local_options[k] = options[k]
71
- }
72
- local_options.delete(:offset) if local_options[:offset] == 0
73
-
74
- # store the number of records wanted by user, as we'll overwrite :limit option to obtain several slices of records (to avoid timeout issues)
75
- nb_to_fetch = local_options[:limit]
76
- nb_to_fetch = nb_to_fetch.to_i if nb_to_fetch
77
- offset_value = local_options[:offset] || 10 # arbitrary value, must be bigger than :limit used (see comment above)
78
- offset_value = offset_value.to_i
79
- offset_value.freeze
80
- initial_limit = nb_to_fetch.nil? ? offset_value : [offset_value, nb_to_fetch].min # how many records should be fetched on first pass
81
85
  # ensure results are ordered so :limit and :offset option behave in a deterministic fashion
82
- local_options = { :order_by => :id }.merge(local_options)
83
- local_options.update(:limit => initial_limit) # override original argument
84
-
85
- # get first slice of results
86
- # note: to work around a SugarCRM REST API bug, the :limit option must always be smaller than the :offset option
87
- # this is the reason this first query is separate (not in the loop): the initial query has a larger limit, so that we can then use the loop
88
- # with :limit always smaller than :offset
89
- results = connection.get_entry_list(self._module.name, query_from_options(local_options), local_options)
90
- return nil unless results
91
- results = Array.wrap(results)
92
-
93
- limit_value = [5, offset_value].min # arbitrary value, must be smaller than :offset used (see comment above)
94
- limit_value.freeze
95
- local_options = { :order_by => :id }.merge(local_options)
96
- local_options.update(:limit => limit_value)
97
-
98
- # a portion of the results has already been queried
99
- # update or set the :offset value to reflect this
100
- local_options[:offset] ||= results.size
101
- local_options[:offset] += offset_value
102
-
103
- # continue fetching results until we either
104
- # a) have as many results as the user wants (specified via the original :limit option)
105
- # b) there are no more results matching the criteria
106
- while result_slice = connection.get_entry_list(self._module.name, query_from_options(local_options), local_options)
107
- results.concat(Array.wrap(result_slice))
108
- # make sure we don't return more results than the user requested (via original :limit option)
109
- if nb_to_fetch && results.size >= nb_to_fetch
110
- return results.slice(0, nb_to_fetch)
111
- end
112
- local_options[:offset] += local_options[:limit] # update :offset as we get more records
86
+ local_options[:order_by] = :id unless options[:order_by]
87
+
88
+ # we must ensure limit <= offset (due to bug mentioned above)
89
+ if offset
90
+ local_options[:limit] = [offset.to_i, SLICE_SIZE].min
91
+ local_options[:offset] = offset if offset
92
+ else
93
+ local_options[:limit] = options[:limit] ? [options[:limit].to_i, SLICE_SIZE].min : SLICE_SIZE
94
+ end
95
+ local_options[:limit] = [local_options[:limit], options[:limit]].min if options[:limit] # don't retrieve more records than required
96
+ local_options = options.merge(local_options)
97
+
98
+ query = query_from_options(local_options)
99
+ result_slice = connection.get_entry_list(self._module.name, query, local_options)
100
+ return results_accumulator unless result_slice
101
+
102
+ result_slice_array = Array.wrap(result_slice)
103
+ if block_given?
104
+ result_slice_array.each{|r| yield r }
105
+ else
106
+ results_accumulator = [] unless results_accumulator
107
+ results_accumulator = results_accumulator.concat(result_slice_array)
108
+ end
109
+
110
+ # adjust options to take into account records that were already retrieved
111
+ updated_options = {:offset => options[:offset].to_i + result_slice_array.size}
112
+ updated_options[:limit] = (options[:limit] ? options[:limit] - result_slice_array.size : nil)
113
+ updated_options = options.merge(updated_options)
114
+
115
+ # have we retrieved all the records?
116
+ if (updated_options[:limit] && updated_options[:limit] < 1) || local_options[:limit] > result_slice_array.size
117
+ return results_accumulator
118
+ else
119
+ find_by_sql(updated_options, results_accumulator, &block)
113
120
  end
114
- results
115
121
  end
116
122
 
117
123
  def query_from_options(options)
@@ -16,7 +16,7 @@ module SugarCRM; class Session
16
16
 
17
17
  setup_connection
18
18
  register_namespace
19
- connect_and_add_session
19
+ connect(@config[:base_url], @config[:username], @config[:password], @config[:options])
20
20
  end
21
21
 
22
22
  # Creates a new session from the credentials present in a file
@@ -66,6 +66,7 @@ module SugarCRM; class Session
66
66
  SugarCRM::Module.deregister_all(self)
67
67
  @connection_pool = SugarCRM::ConnectionPool.new(self)
68
68
  SugarCRM::Module.register_all(self)
69
+ SugarCRM.add_session(self)
69
70
  load_extensions
70
71
  true
71
72
  end
@@ -195,11 +196,6 @@ module SugarCRM; class Session
195
196
  def load_extensions
196
197
  self.class.validate_path @extensions_path
197
198
  Dir[File.join(@extensions_path, '**', '*.rb').to_s].each { |f| load(f) }
198
- end
199
-
200
- def connect_and_add_session
201
- connect(@config[:base_url], @config[:username], @config[:password], @config[:options])
202
- SugarCRM.add_session(self)
203
199
  end
204
200
 
205
201
  # Returns hash containing only keys/values relating to connection pool options. These are removed from parameter hash.
data/sugarcrm.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{sugarcrm}
8
- s.version = "0.9.12"
8
+ s.version = "0.9.13"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Carl Hicks", "David Sulc"]
12
- s.date = %q{2011-03-02}
12
+ s.date = %q{2011-04-06}
13
13
  s.default_executable = %q{sugarcrm}
14
14
  s.email = %q{carl.hicks@gmail.com}
15
15
  s.executables = ["sugarcrm"]
@@ -78,12 +78,11 @@ Gem::Specification.new do |s|
78
78
  "./lib/sugarcrm/module.rb",
79
79
  "./lib/sugarcrm/module_methods.rb",
80
80
  "./lib/sugarcrm/session.rb",
81
- "./sugarcrm.gemspec",
82
- "./sugarcrm.tmproj"
81
+ "./sugarcrm.gemspec"
83
82
  ]
84
83
  s.homepage = %q{http://github.com/chicks/sugarcrm}
85
84
  s.require_paths = ["lib"]
86
- s.rubygems_version = %q{1.3.7}
85
+ s.rubygems_version = %q{1.6.2}
87
86
  s.summary = %q{A less clunky way to interact with SugarCRM via REST.}
88
87
  s.test_files = [
89
88
  "test/connection/test_get_available_modules.rb",
@@ -106,6 +105,7 @@ Gem::Specification.new do |s|
106
105
  "test/test_associations.rb",
107
106
  "test/test_connection.rb",
108
107
  "test/test_connection_pool.rb",
108
+ "test/test_finders.rb",
109
109
  "test/test_module.rb",
110
110
  "test/test_response.rb",
111
111
  "test/test_session.rb",
@@ -113,7 +113,6 @@ Gem::Specification.new do |s|
113
113
  ]
114
114
 
115
115
  if s.respond_to? :specification_version then
116
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
117
116
  s.specification_version = 3
118
117
 
119
118
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -18,13 +18,13 @@ class TestConnectionPool < ActiveSupport::TestCase
18
18
  end
19
19
 
20
20
  should "be able to specify its timeout" do
21
- assert_equal 5, SugarCRM.session.connection_pool.timeout # test default
21
+ default_timeout = SugarCRM.session.connection_pool.timeout
22
22
 
23
23
  config = SugarCRM.session.config
24
- sess = SugarCRM::Session.new(config[:base_url], config[:username], config[:password], {:connection_pool => {:wait_timeout => 3}})
24
+ sess = SugarCRM::Session.new(config[:base_url], config[:username], config[:password], {:connection_pool => {:wait_timeout => default_timeout+1}})
25
25
 
26
26
  begin
27
- assert_equal 3, sess.connection_pool.timeout
27
+ assert_equal default_timeout+1, sess.connection_pool.timeout
28
28
  ensure
29
29
  sess.disconnect!
30
30
  end