sugarcrm 0.9.9 → 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +9 -14
- data/Rakefile +2 -10
- data/VERSION +1 -1
- data/lib/sugarcrm.rb +1 -0
- data/lib/sugarcrm/associations/association.rb +91 -29
- data/lib/sugarcrm/associations/association_methods.rb +1 -2
- data/lib/sugarcrm/associations/associations.rb +10 -16
- data/lib/sugarcrm/attributes/attribute_typecast.rb +7 -0
- data/lib/sugarcrm/connection/api/get_available_modules.rb +1 -1
- data/lib/sugarcrm/connection/api/get_document_revision.rb +2 -2
- data/lib/sugarcrm/connection/api/get_entries.rb +5 -5
- data/lib/sugarcrm/connection/api/get_entries_count.rb +4 -4
- data/lib/sugarcrm/connection/api/get_entry.rb +5 -5
- data/lib/sugarcrm/connection/api/get_entry_list.rb +9 -9
- data/lib/sugarcrm/connection/api/get_module_fields.rb +2 -2
- data/lib/sugarcrm/connection/api/get_note_attachment.rb +3 -3
- data/lib/sugarcrm/connection/api/get_relationships.rb +8 -8
- data/lib/sugarcrm/connection/api/get_report_entries.rb +3 -3
- data/lib/sugarcrm/connection/api/get_user_id.rb +1 -1
- data/lib/sugarcrm/connection/api/get_user_team_id.rb +1 -1
- data/lib/sugarcrm/connection/api/logout.rb +2 -2
- data/lib/sugarcrm/connection/api/seamless_login.rb +1 -1
- data/lib/sugarcrm/connection/api/search_by_module.rb +5 -5
- data/lib/sugarcrm/connection/api/set_campaign_merge.rb +3 -3
- data/lib/sugarcrm/connection/api/set_document_revision.rb +3 -3
- data/lib/sugarcrm/connection/api/set_entries.rb +3 -3
- data/lib/sugarcrm/connection/api/set_entry.rb +3 -3
- data/lib/sugarcrm/connection/api/set_note_attachment.rb +24 -2
- data/lib/sugarcrm/connection/api/set_relationship.rb +7 -7
- data/lib/sugarcrm/connection/api/set_relationships.rb +5 -5
- data/lib/sugarcrm/connection/connection.rb +3 -1
- data/lib/sugarcrm/environment.rb +16 -1
- data/test/connection/test_get_entry_list.rb +1 -1
- data/test/connection/test_set_note_attachment.rb +17 -0
- data/test/helper.rb +1 -1
- data/test/test_associations.rb +98 -0
- data/test/test_environment.rb +7 -0
- data/test/test_sugarcrm.rb +0 -52
- metadata +29 -36
- data/test/test_association.rb +0 -18
data/README.rdoc
CHANGED
@@ -6,13 +6,7 @@ REST Bindings for SugarCRM!
|
|
6
6
|
|
7
7
|
== SUMMARY:
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
== Description:
|
12
|
-
|
13
|
-
A less clunky way to interact with SugarCRM via REST.
|
14
|
-
|
15
|
-
Instead of SugarCRM.connection.get_entry("Users", "1") you could use SugarCRM::User.find(1). There is support for collections à 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.
|
9
|
+
A less clunky way to interact with SugarCRM via REST.
|
16
10
|
|
17
11
|
== FEATURES/PROBLEMS:
|
18
12
|
|
@@ -145,12 +139,13 @@ Instead of SugarCRM.connection.get_entry("Users", "1") you could use SugarCRM::U
|
|
145
139
|
|
146
140
|
== USING A CONFIGURATION FILE
|
147
141
|
|
148
|
-
If you want to use a configuration file instead of always specifying the url, username, and password to connect to SugarCRM, you can
|
142
|
+
If you want to use a configuration file instead of always specifying the url, username, and password to connect to SugarCRM, you can add your credentials to one (or more) of
|
149
143
|
|
150
|
-
*
|
151
|
-
*
|
152
|
-
*
|
153
|
-
*
|
144
|
+
* `/etc/sugarcrm.yaml`
|
145
|
+
* `~/.sugarcrm.yaml` (i.e. your home directory on Linux and Mac OSX)
|
146
|
+
* a `sugarcrm.yaml` file at the root of you Windows home directory (execute `ENV['USERPROFILE']` in Ruby to see which directory should contain the file)
|
147
|
+
* `config/sugarcrm.yaml` (will need to be copied each time you upgrade or reinstall the gem)
|
148
|
+
* a YAML file and call `SugarCRM::Environment.load_config` followed by the absolute path to your configuration file
|
154
149
|
|
155
150
|
If there are several configuration files, they are loaded sequentially in the order above and will overwrite previous values (if present). This allows you to (e.g.) have a config file in `/etc/sugarcrm.yaml` with system-wide configuration information (such as the url where SugarCRM is located) and/or defaults. Each developer/user can then have his personal configuration file in `~/.sugarcrm.yaml` with his own username and password. A developer could also specify a different location for the SugarCRM instance (e.g. a local testing instance) in his configuration file, which will take precedence over the value in `/etc/sugarcrm.yaml`.
|
156
151
|
|
@@ -175,9 +170,9 @@ An example, accompanied by instructions, can be found in the `config/sugarcrm.ya
|
|
175
170
|
|
176
171
|
4. You now have full access to the gem's functionality, e.g. `puts SugarCRM::Account.first.name`
|
177
172
|
|
178
|
-
==
|
173
|
+
== EXTENDING THE GEM
|
179
174
|
|
180
|
-
If you want to
|
175
|
+
If you want to extend the gem's capabilities (e.g. to add methods specific to your environment), you can either
|
181
176
|
|
182
177
|
* drop your `*.rb` files in `lib/sugarcrm/extensions/` (see the README in that folder)
|
183
178
|
|
data/Rakefile
CHANGED
@@ -13,11 +13,10 @@ require 'jeweler'
|
|
13
13
|
Jeweler::Tasks.new do |gem|
|
14
14
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
15
|
gem.name = "sugarcrm"
|
16
|
-
gem.summary = %Q{
|
17
|
-
gem.description = %Q{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 a 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.}
|
16
|
+
gem.summary = %Q{A less clunky way to interact with SugarCRM via REST.}
|
18
17
|
gem.email = "carl.hicks@gmail.com"
|
19
18
|
gem.homepage = "http://github.com/chicks/sugarcrm"
|
20
|
-
gem.authors = ["Carl Hicks"]
|
19
|
+
gem.authors = ["Carl Hicks", "David Sulc"]
|
21
20
|
end
|
22
21
|
Jeweler::RubygemsDotOrgTasks.new
|
23
22
|
|
@@ -28,13 +27,6 @@ Rake::TestTask.new(:test) do |test|
|
|
28
27
|
test.verbose = true
|
29
28
|
end
|
30
29
|
|
31
|
-
#require 'rcov/rcovtask'
|
32
|
-
#Rcov::RcovTask.new do |test|
|
33
|
-
# test.libs << 'test'
|
34
|
-
# test.pattern = 'test/**/test_*.rb'
|
35
|
-
# test.verbose = true
|
36
|
-
#end
|
37
|
-
|
38
30
|
task :default => :test
|
39
31
|
|
40
32
|
require 'rake/rdoctask'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.10
|
data/lib/sugarcrm.rb
CHANGED
@@ -1,21 +1,30 @@
|
|
1
1
|
module SugarCRM
|
2
|
-
|
2
|
+
|
3
|
+
# Associations are middlemen between the object that holds the association, known as the @owner,
|
4
|
+
# and the actual associated object, known as the @target. Methods are added to the @owner that
|
5
|
+
# allow access to the association collection, and are held in @proxy_methods. The cardinality
|
6
|
+
# of the association is available in @cardinality, and the actual relationship details are held
|
7
|
+
# in @relationship.
|
3
8
|
class Association
|
4
9
|
attr :owner, true
|
5
10
|
attr :target, true
|
6
11
|
attr :link_field, true
|
12
|
+
attr :relationship, true
|
7
13
|
attr :attributes, true
|
8
|
-
attr :
|
14
|
+
attr :proxy_methods, true
|
15
|
+
attr :cardinality, true
|
9
16
|
|
10
|
-
#
|
17
|
+
# Creates a new instance of an Association
|
11
18
|
def initialize(owner,link_field,opts={})
|
12
19
|
@options = { :define_methods? => true }.merge! opts
|
13
20
|
@owner = owner
|
14
21
|
check_valid_owner
|
15
22
|
@link_field = link_field
|
16
23
|
@attributes = owner.link_fields[link_field]
|
24
|
+
@relationship = relationship_for(@attributes["relationship"])
|
17
25
|
@target = resolve_target
|
18
|
-
@
|
26
|
+
@proxy_methods = define_methods if @options[:define_methods?]
|
27
|
+
@cardinality = resolve_cardinality
|
19
28
|
self
|
20
29
|
end
|
21
30
|
|
@@ -28,6 +37,27 @@ module SugarCRM
|
|
28
37
|
false
|
29
38
|
end
|
30
39
|
|
40
|
+
def ==(comparison_object)
|
41
|
+
comparison_object.instance_of?(self.class) &&
|
42
|
+
@target.class == comparison_object.class &&
|
43
|
+
@link_field == comparison_object.link_field
|
44
|
+
end
|
45
|
+
alias :eql? :==
|
46
|
+
|
47
|
+
def hash
|
48
|
+
"#{@target.class}##{@link_field}".hash
|
49
|
+
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"#<SugarCRM::Association @proxy_methods=[#{@proxy_methods.join(", ")}], " +
|
57
|
+
"@link_field=\"#{@link_field}\", @target=#{@target}, @owner=#{@owner.class}, " +
|
58
|
+
"@cardinality=#{@cardinality}>"
|
59
|
+
end
|
60
|
+
|
31
61
|
protected
|
32
62
|
|
33
63
|
def check_valid_owner
|
@@ -36,7 +66,6 @@ module SugarCRM
|
|
36
66
|
end
|
37
67
|
|
38
68
|
# Attempts to determine the class of the target in the association
|
39
|
-
# TODO: Write tests for this.
|
40
69
|
def resolve_target
|
41
70
|
# Use the link_field name first
|
42
71
|
klass = @link_field.singularize.camelize
|
@@ -46,47 +75,80 @@ module SugarCRM
|
|
46
75
|
module_name = SugarCRM::Module.find(@attributes["module"])
|
47
76
|
return "SugarCRM::#{module_name.klass}".constantize if SugarCRM.const_defined? module_name.klass
|
48
77
|
end
|
49
|
-
# Use the
|
78
|
+
# Use the "relationship" target
|
50
79
|
if @attributes["relationship"].length > 0
|
51
|
-
klass =
|
80
|
+
klass = @relationship[:target][:name].singularize.camelize
|
52
81
|
return "SugarCRM::#{klass}".constantize if SugarCRM.const_defined? klass
|
53
82
|
end
|
54
83
|
false
|
55
84
|
end
|
56
85
|
|
86
|
+
# Defines methods for accessing the association target on the owner class.
|
87
|
+
# If the link_field name includes the owner class name, it is stripped before
|
88
|
+
# creating the method. If this occurs, we also create an alias to the stripped
|
89
|
+
# method using the full link_field name.
|
90
|
+
def define_methods
|
91
|
+
methods = []
|
92
|
+
pretty_name = @relationship[:target][:name]
|
93
|
+
methods << define_method(@link_field)
|
94
|
+
methods << define_alias(pretty_name, @link_field) if pretty_name != @link_field
|
95
|
+
methods
|
96
|
+
end
|
97
|
+
|
57
98
|
# Generates the association proxy method for related module
|
58
99
|
def define_method(link_field)
|
100
|
+
raise ArgumentException, "argument cannot be nil" if link_field.nil?
|
101
|
+
if (@owner.respond_to? link_field.to_sym) && @owner.debug
|
102
|
+
warn "Warning: Overriding method: #{@owner.class}##{link_field}"
|
103
|
+
end
|
59
104
|
@owner.class.module_eval %Q?
|
60
105
|
def #{link_field}
|
61
106
|
query_association :#{link_field}
|
62
107
|
end
|
63
108
|
?
|
109
|
+
link_field
|
64
110
|
end
|
65
111
|
|
66
|
-
# Defines
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
112
|
+
# Defines a method alias. Checks to see if a method is already defined.
|
113
|
+
def define_alias(alias_name, method_name)
|
114
|
+
@owner.class.module_eval %Q?
|
115
|
+
alias :#{alias_name} :#{method_name}
|
116
|
+
?
|
117
|
+
alias_name
|
118
|
+
end
|
119
|
+
|
120
|
+
# This method breaks the relationship into parts and returns them
|
121
|
+
def relationship_for(relationship)
|
122
|
+
# We need to run both regexes, because the plurality of the @owner module name is
|
123
|
+
# important
|
124
|
+
plural_regex = /((.*)_)?(#{Regexp.quote(@owner.class._module.name.downcase)})(_(.*))?/
|
125
|
+
singular_regex = /((.*)_)?(#{Regexp.quote(@owner.class._module.name.downcase.singularize)})(_(.*))?/
|
126
|
+
# Break the loop if we match
|
127
|
+
[plural_regex, singular_regex].each {|r| break if relationship.match(r)}
|
128
|
+
# Assign sane values to things if we didnt match
|
129
|
+
o = $3
|
130
|
+
o = @owner.class._module.name.downcase if o.nil? || o.empty?
|
131
|
+
t = [$2, $5].compact.join('_')
|
132
|
+
t = @link_field if t.nil? || t.empty?
|
133
|
+
# Look up the cardinality
|
134
|
+
o_c, t_c = cardinality_for(o,t)
|
135
|
+
{:owner => {:name => o, :cardinality => o_c},
|
136
|
+
:target => {:name => t, :cardinality => t_c}}
|
137
|
+
end
|
138
|
+
|
139
|
+
# Determines if the provided string is plural or singular
|
140
|
+
# Plurality == Cardinality
|
141
|
+
def cardinality_for(*args)
|
142
|
+
args.inject([]) {|results,arg|
|
143
|
+
result = :many
|
144
|
+
result = :one if arg.singularize == arg
|
145
|
+
results << result
|
146
|
+
}
|
81
147
|
end
|
82
148
|
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
def humanized_link_name(link_field)
|
87
|
-
# the module name is used to function properly with modules containing '_' (e.g. a custom module abc_sale : custom modules need a prefix (abc here) so they will always have a '_' in their table name)
|
88
|
-
return link_field unless link_field.to_s =~ /((.*)_)?#{Regexp.quote(@owner.class._module.name.downcase)}(_(.*))?/
|
89
|
-
[$2, $4].compact.join('_')
|
149
|
+
# TODO: Add Tests for This
|
150
|
+
def resolve_cardinality
|
151
|
+
"#{@relationship[:owner][:cardinality]}_to_#{@relationship[:target][:cardinality]}".to_sym
|
90
152
|
end
|
91
153
|
|
92
154
|
end
|
@@ -38,7 +38,7 @@ module SugarCRM; module AssociationMethods
|
|
38
38
|
"Couldn't associate #{self.class._module.name}: #{self.id} -> #{t}: #{t.id}!"
|
39
39
|
end
|
40
40
|
# We need to update the association cache for any changes we make.
|
41
|
-
if opts[:delete]
|
41
|
+
if opts[:delete] == 1
|
42
42
|
update_association_cache_for(association.link_field, t, :delete)
|
43
43
|
t.update_association_cache_for(association.link_field, self, :delete)
|
44
44
|
else
|
@@ -51,7 +51,6 @@ module SugarCRM; module AssociationMethods
|
|
51
51
|
alias :relate! :associate!
|
52
52
|
|
53
53
|
# Removes a relationship between the current object and the target object
|
54
|
-
# TODO: Write a test for this.
|
55
54
|
def disassociate!(target)
|
56
55
|
associate!(target,{:delete => 1})
|
57
56
|
end
|
@@ -19,6 +19,13 @@ module SugarCRM
|
|
19
19
|
self
|
20
20
|
end
|
21
21
|
|
22
|
+
# Returns the proxy methods of all the associations in the collection
|
23
|
+
def proxy_methods
|
24
|
+
@associations.inject([]) { |pm,a|
|
25
|
+
pm = pm | a.proxy_methods
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
22
29
|
# Looks up an association by object, link_field, or method.
|
23
30
|
# Raises an exception if not found
|
24
31
|
def find!(target)
|
@@ -32,26 +39,13 @@ module SugarCRM
|
|
32
39
|
# Returns false if not found
|
33
40
|
def find(association)
|
34
41
|
begin
|
35
|
-
find!
|
42
|
+
find!(association)
|
36
43
|
rescue InvalidAssociation
|
37
44
|
false
|
38
45
|
end
|
39
46
|
end
|
40
|
-
|
41
|
-
|
42
|
-
self
|
43
|
-
end
|
44
|
-
|
45
|
-
def to_s
|
46
|
-
methods = []
|
47
|
-
@associations.each do |a|
|
48
|
-
a.methods.each do |m|
|
49
|
-
methods << m
|
50
|
-
end
|
51
|
-
end
|
52
|
-
"[#{methods.join(', ')}]"
|
53
|
-
end
|
54
|
-
|
47
|
+
alias :include? :find
|
48
|
+
|
55
49
|
# delegate undefined methods to the @collection array
|
56
50
|
# E.g. contact.cases should behave like an array and allow `length`, `size`, `each`, etc.
|
57
51
|
def method_missing(method_name, *args, &block)
|
@@ -18,6 +18,13 @@ module SugarCRM; module AttributeTypeCast
|
|
18
18
|
# skip primary key columns
|
19
19
|
next if name == "id"
|
20
20
|
attr_type = attr_type_for(name)
|
21
|
+
|
22
|
+
# empty attributes should stay empty (e.g. an empty int field shouldn't be typecast as 0)
|
23
|
+
if [:datetime, :datetimecombo, :int].include? attr_type && (value.nil? || value == '')
|
24
|
+
@attributes[name] = nil
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
21
28
|
case attr_type
|
22
29
|
when :bool
|
23
30
|
@attributes[name] = (value == "1")
|
@@ -10,11 +10,11 @@ module SugarCRM; class Connection
|
|
10
10
|
|
11
11
|
json = <<-EOF
|
12
12
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
"session": "#{@session}",
|
14
|
+
"module_name": "#{module_name}",
|
15
|
+
"ids": #{ids.to_json},
|
16
|
+
"select_fields": #{resolve_fields(module_name, options[:fields])},
|
17
|
+
"link_name_to_fields_array": #{options[:link_fields].to_json}
|
18
18
|
}
|
19
19
|
EOF
|
20
20
|
json.gsub!(/^\s{6}/,'')
|
@@ -8,10 +8,10 @@ module SugarCRM; class Connection
|
|
8
8
|
|
9
9
|
json = <<-EOF
|
10
10
|
{
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
"session": "#{@session}",
|
12
|
+
"module_name": "#{module_name}",
|
13
|
+
"query": "#{query}",
|
14
|
+
"deleted": #{options[:deleted]}
|
15
15
|
}
|
16
16
|
EOF
|
17
17
|
json.gsub!(/^\s{6}/,'')
|
@@ -9,11 +9,11 @@ module SugarCRM; class Connection
|
|
9
9
|
|
10
10
|
json = <<-EOF
|
11
11
|
{
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
"session": "#{@session}",
|
13
|
+
"module_name": "#{module_name}",
|
14
|
+
"id": "#{id}",
|
15
|
+
"select_fields": #{resolve_fields(module_name, options[:fields])},
|
16
|
+
"link_name_to_fields_array": #{options[:link_fields]}
|
17
17
|
}
|
18
18
|
EOF
|
19
19
|
|
@@ -14,15 +14,15 @@ module SugarCRM; class Connection
|
|
14
14
|
|
15
15
|
json = <<-EOF
|
16
16
|
{
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
"session": "#{@session}",
|
18
|
+
"module_name": "#{module_name}",
|
19
|
+
"query": "#{query}",
|
20
|
+
"order_by": "#{options[:order_by]}",
|
21
|
+
"offset": "#{options[:offset]}",
|
22
|
+
"select_fields": #{resolve_fields(module_name, options[:fields])},
|
23
|
+
"link_name_to_fields_array": #{options[:link_fields].to_json},
|
24
|
+
"max_results": "#{options[:limit]}",
|
25
|
+
"deleted": #{options[:deleted]}
|
26
26
|
}
|
27
27
|
EOF
|
28
28
|
json.gsub!(/^\s{6}/,'')
|
@@ -4,11 +4,11 @@ module SugarCRM; class Connection
|
|
4
4
|
login! unless logged_in?
|
5
5
|
json = <<-EOF
|
6
6
|
{
|
7
|
-
|
8
|
-
|
7
|
+
"session": "#{@session}",
|
8
|
+
"id": "#{id}"
|
9
9
|
}
|
10
10
|
EOF
|
11
11
|
json.gsub!(/^\s{6}/,'')
|
12
|
-
send!(:get_note_attachment, json)
|
12
|
+
send!(:get_note_attachment, json)["note_attachment"]
|
13
13
|
end
|
14
14
|
end; end
|
@@ -13,14 +13,14 @@ module SugarCRM; class Connection
|
|
13
13
|
|
14
14
|
json = <<-EOF
|
15
15
|
{
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
"session": "#{@session}",
|
17
|
+
"module_name": "#{module_name}",
|
18
|
+
"module_id": "#{id}",
|
19
|
+
"link_field_name": "#{related_to.downcase}",
|
20
|
+
"related_module_query": "#{options[:query]}",
|
21
|
+
"related_fields": #{resolve_related_fields(module_name, related_to)},
|
22
|
+
"related_module_link_name_to_fields_array": #{options[:link_fields].to_json},
|
23
|
+
"deleted": #{options[:deleted]}
|
24
24
|
}
|
25
25
|
EOF
|
26
26
|
json.gsub!(/^\s{6}/,'')
|
@@ -6,9 +6,9 @@ module SugarCRM; class Connection
|
|
6
6
|
|
7
7
|
json = <<-EOF
|
8
8
|
{
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
"session": "#{@session}",
|
10
|
+
"ids": #{ids.to_json},
|
11
|
+
"select_fields": "#{options[:select_fields].to_json}"
|
12
12
|
}
|
13
13
|
EOF
|
14
14
|
json.gsub!(/^\s{6}/,'')
|
@@ -12,11 +12,11 @@ module SugarCRM; class Connection
|
|
12
12
|
|
13
13
|
json = <<-EOF
|
14
14
|
{
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
"session": "#{@session}",
|
16
|
+
"search_string": "#{search_string}",
|
17
|
+
"modules": "#{modules}",
|
18
|
+
"offset": #{options[:offset]},
|
19
|
+
"max_results": #{options[:limit]}
|
20
20
|
}
|
21
21
|
EOF
|
22
22
|
json.gsub!(/^\s{6}/,'')
|
@@ -4,9 +4,9 @@ module SugarCRM; class Connection
|
|
4
4
|
login! unless logged_in?
|
5
5
|
json = <<-EOF
|
6
6
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
"session": "#{@session}",
|
8
|
+
"targets": #{targets.to_json},
|
9
|
+
"campaign-id": "#{campaign_id}"
|
10
10
|
}
|
11
11
|
EOF
|
12
12
|
json.gsub!(/^\s{6}/,'')
|
@@ -4,9 +4,9 @@ module SugarCRM; class Connection
|
|
4
4
|
login! unless logged_in?
|
5
5
|
json = <<-EOF
|
6
6
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
"session": "#{@session}",
|
8
|
+
"document_revision": "#{revision}",
|
9
|
+
"id": #{id}
|
10
10
|
}
|
11
11
|
EOF
|
12
12
|
json.gsub!(/^\s{6}/,'')
|
@@ -4,9 +4,9 @@ module SugarCRM; class Connection
|
|
4
4
|
login! unless logged_in?
|
5
5
|
json = <<-EOF
|
6
6
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
"session": "#{@session}",
|
8
|
+
"module_name": "#{module_name}",
|
9
|
+
"name_value_list": #{name_value_lists.to_json}
|
10
10
|
}
|
11
11
|
EOF
|
12
12
|
json.gsub!(/^\s{6}/,'')
|
@@ -4,9 +4,9 @@ module SugarCRM; class Connection
|
|
4
4
|
login! unless logged_in?
|
5
5
|
json = <<-EOF
|
6
6
|
{
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
"session": "#{@session}",
|
8
|
+
"module_name": "#{module_name}",
|
9
|
+
"name_value_list": #{name_value_list.to_json}
|
10
10
|
}
|
11
11
|
EOF
|
12
12
|
json.gsub!(/^\s{6}/,'')
|
@@ -1,3 +1,25 @@
|
|
1
1
|
module SugarCRM; class Connection
|
2
|
-
#
|
3
|
-
|
2
|
+
# Creates or updates an attachment on a note
|
3
|
+
def set_note_attachment(id, filename, file, opts={})
|
4
|
+
options = {
|
5
|
+
:module_id => '',
|
6
|
+
:module_name => ''
|
7
|
+
}.merge! opts
|
8
|
+
|
9
|
+
login! unless logged_in?
|
10
|
+
json = <<-EOF
|
11
|
+
{
|
12
|
+
"session": "#{@session}",
|
13
|
+
"note": {
|
14
|
+
"id": "#{id}",
|
15
|
+
"filename": "#{filename}",
|
16
|
+
"file": "#{Base64.encode64(file)}",
|
17
|
+
"related_module_id": "#{options[:module_id]}",
|
18
|
+
"related_module_name": "#{options[:module_name]}"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
EOF
|
22
|
+
json.gsub!(/^\s{6}/,'')
|
23
|
+
send!(:set_note_attachment, json)
|
24
|
+
end
|
25
|
+
end; end
|
@@ -9,13 +9,13 @@ module SugarCRM; class Connection
|
|
9
9
|
raise ArgumentError, "related_ids must be an Array" unless related_ids.class == Array
|
10
10
|
json = <<-EOF
|
11
11
|
{
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
"session": "#{@session}",
|
13
|
+
"module_name": "#{module_name}",
|
14
|
+
"module_id": "#{module_id}",
|
15
|
+
"link_field_name": "#{link_field_name}",
|
16
|
+
"related_ids": #{related_ids.to_json},
|
17
|
+
"name_value_list": #{options[:name_value_list].to_json},
|
18
|
+
"delete": #{options[:delete]}
|
19
19
|
}
|
20
20
|
EOF
|
21
21
|
json.gsub!(/^\s{6}/,'')
|
@@ -9,11 +9,11 @@ module SugarCRM; class Connection
|
|
9
9
|
|
10
10
|
json = <<-EOF
|
11
11
|
{
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
"session": "#{@session}",
|
13
|
+
"module_names": "#{module_names.to_json}",
|
14
|
+
"module_ids": #{module_ids.to_json},
|
15
|
+
"link_field_names": #{link_field_names.to_json},
|
16
|
+
"related_ids": #{related_ids.to_json}
|
17
17
|
}
|
18
18
|
EOF
|
19
19
|
json.gsub!(/^\s{6}/,'')
|
@@ -29,7 +29,9 @@ module SugarCRM; class Connection
|
|
29
29
|
resolve_url
|
30
30
|
login!
|
31
31
|
# make sure the environment singleton gets loaded
|
32
|
-
|
32
|
+
if @options[:load_environment] # prevent loops when Environment tries to log in automatically
|
33
|
+
SugarCRM::Environment.update_config({:base_url => url, :username => user, :password => pass})
|
34
|
+
end
|
33
35
|
self
|
34
36
|
end
|
35
37
|
|
data/lib/sugarcrm/environment.rb
CHANGED
@@ -9,7 +9,7 @@ module SugarCRM; class Environment
|
|
9
9
|
@config = {}
|
10
10
|
|
11
11
|
# see README for reasoning behind the priorization
|
12
|
-
|
12
|
+
config_file_paths.each{|path|
|
13
13
|
load_config path if File.exists? path
|
14
14
|
}
|
15
15
|
extensions_folder = File.join(File.dirname(__FILE__), 'extensions')
|
@@ -28,6 +28,14 @@ module SugarCRM; class Environment
|
|
28
28
|
@config[k.to_sym] = v
|
29
29
|
}
|
30
30
|
end
|
31
|
+
@config
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_config(params)
|
35
|
+
params.each{|k,v|
|
36
|
+
@config[k.to_sym] = v
|
37
|
+
}
|
38
|
+
@config
|
31
39
|
end
|
32
40
|
|
33
41
|
# load all the monkey patch extension files in the provided folder
|
@@ -42,6 +50,13 @@ module SugarCRM; class Environment
|
|
42
50
|
end
|
43
51
|
|
44
52
|
private
|
53
|
+
def config_file_paths
|
54
|
+
# see README for reasoning behind the priorization
|
55
|
+
paths = ['/etc/sugarcrm.yaml', File.expand_path('~/.sugarcrm.yaml'), File.join(File.dirname(__FILE__), 'config', 'sugarcrm.yaml')]
|
56
|
+
paths.insert(1, File.join(ENV['USERPROFILE'], 'sugarcrm.yaml')) if ENV['USERPROFILE']
|
57
|
+
paths
|
58
|
+
end
|
59
|
+
|
45
60
|
def validate_path(path)
|
46
61
|
raise "Invalid path: #{path}" unless File.exists? path
|
47
62
|
end
|
@@ -18,7 +18,7 @@ class TestGetEntryList < Test::Unit::TestCase
|
|
18
18
|
"Users",
|
19
19
|
"users.deleted = 0"
|
20
20
|
)
|
21
|
-
assert_equal "
|
21
|
+
assert_equal "admin", users.first.user_name
|
22
22
|
end
|
23
23
|
should "return an object when #get_entry_list" do
|
24
24
|
assert_instance_of Array, @response
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSetNoteAttachment < Test::Unit::TestCase
|
4
|
+
context "A SugarCRM.connection" do
|
5
|
+
should "Add an attachment to a Note" do
|
6
|
+
SugarCRM.connect(URL, USER, PASS, {:debug => false})
|
7
|
+
n = SugarCRM::Note.new
|
8
|
+
n.name = "A Test Note"
|
9
|
+
assert n.save
|
10
|
+
file = File.read("test/config_test.yaml")
|
11
|
+
assert SugarCRM.connection.set_note_attachment(n.id, "config_test.yaml", file)
|
12
|
+
attachment = SugarCRM.connection.get_note_attachment(n.id)
|
13
|
+
assert Base64.decode64(attachment["file"]) == file
|
14
|
+
assert n.delete
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/test/helper.rb
CHANGED
data/test/test_associations.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestAssociations < Test::Unit::TestCase
|
4
|
+
context "A SugarCRM::Associations class" do
|
5
|
+
should "Return an array of Association objects when self#register(SugarCRM::User.new)" do
|
6
|
+
associations = SugarCRM::Associations.register(SugarCRM::User.new)
|
7
|
+
assert associations.include? "email_addresses"
|
8
|
+
assert associations.proxy_methods.include? "email_addresses"
|
9
|
+
end
|
10
|
+
end
|
4
11
|
context "A SugarCRM::Base instance" do
|
5
12
|
should "return an email address when sent #email_addresses" do
|
6
13
|
u = SugarCRM::User.find("seed_sarah_id")
|
@@ -37,5 +44,96 @@ class TestAssociations < Test::Unit::TestCase
|
|
37
44
|
a = SugarCRM::Account.first
|
38
45
|
assert_instance_of SugarCRM::User, a.created_by_link.first
|
39
46
|
end
|
47
|
+
|
48
|
+
should "create relationships with associate!" do
|
49
|
+
a = SugarCRM::Account.first
|
50
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
51
|
+
|
52
|
+
nb_contacts = a.contacts.size
|
53
|
+
a.associate!(c)
|
54
|
+
assert_equal nb_contacts + 1, a.contacts.size # test association_cache is updated
|
55
|
+
|
56
|
+
assert_equal nb_contacts + 1, SugarCRM::Account.first.contacts.size # test relationship is created in Sugar
|
57
|
+
|
58
|
+
assert c.delete
|
59
|
+
end
|
60
|
+
|
61
|
+
should "destroy relationships with disassociate!" do
|
62
|
+
a = SugarCRM::Account.first
|
63
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
64
|
+
|
65
|
+
a.associate!(c)
|
66
|
+
nb_contacts = a.contacts.size
|
67
|
+
a.disassociate!(c)
|
68
|
+
assert_equal nb_contacts - 1, a.contacts.size # test association_cache is updated
|
69
|
+
|
70
|
+
assert_equal nb_contacts - 1, SugarCRM::Account.first.contacts.size # test relationship is destroyed in Sugar
|
71
|
+
|
72
|
+
assert c.delete
|
73
|
+
end
|
74
|
+
|
75
|
+
should "not destroy a relationship if associate! is called with {:delete => 0}" do
|
76
|
+
a = SugarCRM::Account.first
|
77
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
78
|
+
|
79
|
+
a.associate!(c)
|
80
|
+
nb_contacts = a.contacts.size
|
81
|
+
a.associate!(c, {:delete => 0})
|
82
|
+
assert_equal nb_contacts, a.contacts.size
|
83
|
+
|
84
|
+
assert c.delete
|
85
|
+
end
|
86
|
+
|
87
|
+
should "update association cache on associate! only if association changes" do
|
88
|
+
a = SugarCRM::Account.first
|
89
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
90
|
+
|
91
|
+
nb_contacts = a.contacts.size
|
92
|
+
a.associate!(c)
|
93
|
+
assert_equal nb_contacts + 1, a.contacts.size
|
94
|
+
a.associate!(c)
|
95
|
+
assert_equal nb_contacts + 1, a.contacts.size # should not change: already associated
|
96
|
+
|
97
|
+
assert c.delete
|
98
|
+
end
|
99
|
+
|
100
|
+
should "update association cache on << only if association changes" do
|
101
|
+
a = SugarCRM::Account.first
|
102
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
103
|
+
|
104
|
+
nb_contacts = a.contacts.size
|
105
|
+
a.contacts << c
|
106
|
+
assert_equal nb_contacts + 1, a.contacts.size
|
107
|
+
a.contacts << c
|
108
|
+
assert_equal nb_contacts + 1, a.contacts.size # should not change: already associated
|
109
|
+
|
110
|
+
assert c.delete
|
111
|
+
end
|
112
|
+
|
113
|
+
should "update association cache for both sides of the relationship when calling associate!" do
|
114
|
+
a = SugarCRM::Account.first
|
115
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
116
|
+
|
117
|
+
nb_contacts = a.contacts.size
|
118
|
+
nb_accounts = c.accounts.size
|
119
|
+
a.associate!(c)
|
120
|
+
assert_equal nb_contacts + 1, a.contacts.size
|
121
|
+
assert_equal nb_accounts + 1, c.accounts.size
|
122
|
+
|
123
|
+
assert c.delete
|
124
|
+
end
|
125
|
+
|
126
|
+
should "update association cache for both sides of the relationship when calling <<" do
|
127
|
+
a = SugarCRM::Account.first
|
128
|
+
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
129
|
+
|
130
|
+
nb_contacts = a.contacts.size
|
131
|
+
nb_accounts = c.accounts.size
|
132
|
+
a.contacts << c
|
133
|
+
assert_equal nb_contacts + 1, a.contacts.size
|
134
|
+
assert_equal nb_accounts + 1, c.accounts.size
|
135
|
+
|
136
|
+
assert c.delete
|
137
|
+
end
|
40
138
|
end
|
41
139
|
end
|
data/test/test_environment.rb
CHANGED
@@ -33,6 +33,13 @@ class TestEnvironment < Test::Unit::TestCase
|
|
33
33
|
SugarCRM::Environment.load_config File.join(File.dirname(__FILE__), 'config_test.yaml')
|
34
34
|
assert SugarCRM.connection.logged_in?
|
35
35
|
end
|
36
|
+
|
37
|
+
should "update the login credentials on connection" do
|
38
|
+
SugarCRM.connect!(URL, USER, PASS)
|
39
|
+
{:base_url => URL, :username => USER, :password => PASS}.each{|k,v|
|
40
|
+
assert_equal v, SugarCRM::Environment.config[k]
|
41
|
+
}
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
45
|
end
|
data/test/test_sugarcrm.rb
CHANGED
@@ -182,58 +182,6 @@ class TestSugarCRM < Test::Unit::TestCase
|
|
182
182
|
assert a.delete
|
183
183
|
end
|
184
184
|
|
185
|
-
should "update association cache on associate! only if association changes" do
|
186
|
-
a = SugarCRM::Account.first
|
187
|
-
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
188
|
-
|
189
|
-
nb_contacts = a.contacts.size
|
190
|
-
a.associate!(c)
|
191
|
-
assert_equal nb_contacts + 1, a.contacts.size
|
192
|
-
a.associate!(c)
|
193
|
-
assert_equal nb_contacts + 1, a.contacts.size # should not change: already associated
|
194
|
-
|
195
|
-
c.delete
|
196
|
-
end
|
197
|
-
|
198
|
-
should "update association cache on << only if association changes" do
|
199
|
-
a = SugarCRM::Account.first
|
200
|
-
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
201
|
-
|
202
|
-
nb_contacts = a.contacts.size
|
203
|
-
a.contacts << c
|
204
|
-
assert_equal nb_contacts + 1, a.contacts.size
|
205
|
-
a.contacts << c
|
206
|
-
assert_equal nb_contacts + 1, a.contacts.size # should not change: already associated
|
207
|
-
|
208
|
-
c.delete
|
209
|
-
end
|
210
|
-
|
211
|
-
should "update association cache for both sides of the relationship when calling associate!" do
|
212
|
-
a = SugarCRM::Account.first
|
213
|
-
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
214
|
-
|
215
|
-
nb_contacts = a.contacts.size
|
216
|
-
nb_accounts = c.accounts.size
|
217
|
-
a.associate!(c)
|
218
|
-
assert_equal nb_contacts + 1, a.contacts.size
|
219
|
-
assert_equal nb_accounts + 1, c.accounts.size
|
220
|
-
|
221
|
-
c.delete
|
222
|
-
end
|
223
|
-
|
224
|
-
should "update association cache for both sides of the relationship when calling <<" do
|
225
|
-
a = SugarCRM::Account.first
|
226
|
-
c = SugarCRM::Contact.create(:last_name => 'Doe')
|
227
|
-
|
228
|
-
nb_contacts = a.contacts.size
|
229
|
-
nb_accounts = c.accounts.size
|
230
|
-
a.contacts << c
|
231
|
-
assert_equal nb_contacts + 1, a.contacts.size
|
232
|
-
assert_equal nb_accounts + 1, c.accounts.size
|
233
|
-
|
234
|
-
c.delete
|
235
|
-
end
|
236
|
-
|
237
185
|
should "support saving of records with special characters in them" do
|
238
186
|
a = SugarCRM::Account.new
|
239
187
|
a.name = "COHEN, WEISS & SIMON LLP"
|
metadata
CHANGED
@@ -1,114 +1,108 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sugarcrm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 41
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
8
|
+
- 10
|
9
|
+
version: 0.9.10
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Carl Hicks
|
13
|
+
- David Sulc
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-06 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
22
|
name: activesupport
|
25
|
-
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
24
|
none: false
|
27
25
|
requirements:
|
28
26
|
- - ">="
|
29
27
|
- !ruby/object:Gem::Version
|
30
|
-
hash: 7
|
31
28
|
segments:
|
32
29
|
- 3
|
33
30
|
- 0
|
34
31
|
- 0
|
35
32
|
version: 3.0.0
|
36
|
-
requirement: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
33
|
type: :runtime
|
39
34
|
prerelease: false
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
40
37
|
name: i18n
|
41
|
-
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
39
|
none: false
|
43
40
|
requirements:
|
44
41
|
- - ">="
|
45
42
|
- !ruby/object:Gem::Version
|
46
|
-
hash: 3
|
47
43
|
segments:
|
48
44
|
- 0
|
49
45
|
version: "0"
|
50
|
-
requirement: *id002
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
46
|
type: :runtime
|
53
47
|
prerelease: false
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
54
50
|
name: json
|
55
|
-
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
52
|
none: false
|
57
53
|
requirements:
|
58
54
|
- - ">="
|
59
55
|
- !ruby/object:Gem::Version
|
60
|
-
hash: 3
|
61
56
|
segments:
|
62
57
|
- 0
|
63
58
|
version: "0"
|
64
|
-
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
|
-
type: :development
|
59
|
+
type: :runtime
|
67
60
|
prerelease: false
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
68
63
|
name: shoulda
|
69
|
-
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
65
|
none: false
|
71
66
|
requirements:
|
72
67
|
- - ">="
|
73
68
|
- !ruby/object:Gem::Version
|
74
|
-
hash: 3
|
75
69
|
segments:
|
76
70
|
- 0
|
77
71
|
version: "0"
|
78
|
-
requirement: *id004
|
79
|
-
- !ruby/object:Gem::Dependency
|
80
72
|
type: :development
|
81
73
|
prerelease: false
|
74
|
+
version_requirements: *id004
|
75
|
+
- !ruby/object:Gem::Dependency
|
82
76
|
name: bundler
|
83
|
-
|
77
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
78
|
none: false
|
85
79
|
requirements:
|
86
80
|
- - ~>
|
87
81
|
- !ruby/object:Gem::Version
|
88
|
-
hash: 23
|
89
82
|
segments:
|
90
83
|
- 1
|
91
84
|
- 0
|
92
85
|
- 0
|
93
86
|
version: 1.0.0
|
94
|
-
requirement: *id005
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
87
|
type: :development
|
97
88
|
prerelease: false
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
98
91
|
name: jeweler
|
99
|
-
|
92
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
100
93
|
none: false
|
101
94
|
requirements:
|
102
95
|
- - ~>
|
103
96
|
- !ruby/object:Gem::Version
|
104
|
-
hash: 7
|
105
97
|
segments:
|
106
98
|
- 1
|
107
99
|
- 5
|
108
100
|
- 2
|
109
101
|
version: 1.5.2
|
110
|
-
|
111
|
-
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: *id006
|
105
|
+
description:
|
112
106
|
email: carl.hicks@gmail.com
|
113
107
|
executables: []
|
114
108
|
|
@@ -185,10 +179,10 @@ files:
|
|
185
179
|
- test/connection/test_get_user_team_id.rb
|
186
180
|
- test/connection/test_login.rb
|
187
181
|
- test/connection/test_logout.rb
|
182
|
+
- test/connection/test_set_note_attachment.rb
|
188
183
|
- test/connection/test_set_relationship.rb
|
189
184
|
- test/extensions_test/patch.rb
|
190
185
|
- test/helper.rb
|
191
|
-
- test/test_association.rb
|
192
186
|
- test/test_association_collection.rb
|
193
187
|
- test/test_associations.rb
|
194
188
|
- test/test_connection.rb
|
@@ -210,7 +204,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
210
204
|
requirements:
|
211
205
|
- - ">="
|
212
206
|
- !ruby/object:Gem::Version
|
213
|
-
hash:
|
207
|
+
hash: 957398452548061165
|
214
208
|
segments:
|
215
209
|
- 0
|
216
210
|
version: "0"
|
@@ -219,7 +213,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
213
|
requirements:
|
220
214
|
- - ">="
|
221
215
|
- !ruby/object:Gem::Version
|
222
|
-
hash: 3
|
223
216
|
segments:
|
224
217
|
- 0
|
225
218
|
version: "0"
|
@@ -229,7 +222,7 @@ rubyforge_project:
|
|
229
222
|
rubygems_version: 1.3.7
|
230
223
|
signing_key:
|
231
224
|
specification_version: 3
|
232
|
-
summary:
|
225
|
+
summary: A less clunky way to interact with SugarCRM via REST.
|
233
226
|
test_files:
|
234
227
|
- test/connection/test_get_available_modules.rb
|
235
228
|
- test/connection/test_get_entries.rb
|
@@ -242,10 +235,10 @@ test_files:
|
|
242
235
|
- test/connection/test_get_user_team_id.rb
|
243
236
|
- test/connection/test_login.rb
|
244
237
|
- test/connection/test_logout.rb
|
238
|
+
- test/connection/test_set_note_attachment.rb
|
245
239
|
- test/connection/test_set_relationship.rb
|
246
240
|
- test/extensions_test/patch.rb
|
247
241
|
- test/helper.rb
|
248
|
-
- test/test_association.rb
|
249
242
|
- test/test_association_collection.rb
|
250
243
|
- test/test_associations.rb
|
251
244
|
- test/test_connection.rb
|
data/test/test_association.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
#TODO: Figure out how to test this.
|
2
|
-
|
3
|
-
|
4
|
-
# That code works, but what didn't work:
|
5
|
-
# document.tasks.size
|
6
|
-
# document.associate!(task)
|
7
|
-
# document.tasks.size
|
8
|
-
# This seems to be fixed in HEAD in my repo. I haven't pushed the changes to your repo, because I don't really see why commit https://github.com/davidsulc/sugarcrm/commit/228375348c9113324370afa0aca4120eb117d3e1 fixes the issue...
|
9
|
-
# Also, I fixed this case
|
10
|
-
# document.tasks.size
|
11
|
-
# document.associate!(task)
|
12
|
-
# document.tasks.size # => 1 (correct)
|
13
|
-
# document.associate!(task)
|
14
|
-
# document.tasks.size # => 2 (incorrect: should remain 1)
|
15
|
-
# One thing we should look into is
|
16
|
-
# document.associate!(task)
|
17
|
-
# document.tasks.size # => 1
|
18
|
-
# task.documents.size # => 0 (should be 1)
|