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 +16 -2
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/sugarcrm/attributes/attribute_methods.rb +1 -1
- data/lib/sugarcrm/attributes/attribute_validations.rb +29 -4
- data/lib/sugarcrm/base.rb +77 -18
- data/lib/sugarcrm/connection/request.rb +4 -0
- data/lib/sugarcrm/connection/response.rb +1 -0
- data/lib/sugarcrm/connection_pool.rb +1 -1
- data/lib/sugarcrm/finders/finder_methods.rb +59 -53
- data/lib/sugarcrm/session.rb +2 -6
- data/sugarcrm.gemspec +5 -6
- data/test/test_connection_pool.rb +3 -3
- data/test/test_finders.rb +183 -0
- data/test/test_sugarcrm.rb +73 -140
- metadata +34 -25
- data/sugarcrm.tmproj +0 -952
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
|
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.
|
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.
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
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
|
@@ -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 ||
|
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
|
-
|
65
|
-
|
66
|
-
|
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 =
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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)
|
data/lib/sugarcrm/session.rb
CHANGED
@@ -16,7 +16,7 @@ module SugarCRM; class Session
|
|
16
16
|
|
17
17
|
setup_connection
|
18
18
|
register_namespace
|
19
|
-
|
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.
|
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-
|
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.
|
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
|
-
|
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 =>
|
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
|
27
|
+
assert_equal default_timeout+1, sess.connection_pool.timeout
|
28
28
|
ensure
|
29
29
|
sess.disconnect!
|
30
30
|
end
|