activesp 0.0.1 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,38 +1,101 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
1
26
  module ActiveSP
2
27
 
3
28
  class Folder < Item
4
29
 
30
+ # See {Base#key}
31
+ # @return [String]
5
32
  def key
6
- encode_key("F", [parent.key, @id])
33
+ encode_key("F", [@list.key, @id])
7
34
  end
8
35
 
9
- def items(options = {})
10
- @list.items(options.merge(:folder => self))
36
+ def is_folder?
37
+ false
11
38
  end
12
39
 
40
+ # Returns the list of items in this folder
41
+ # @param [Hash] options See {List#each_item}, :folder option has no effect
42
+ # @return [Array<Item>]
43
+ def each_item(options = {}, &blk)
44
+ @list.each_item(options.merge(:folder => self), &blk)
45
+ end
46
+ association :items
47
+
48
+ def each_folder(options = {}, &blk)
49
+ @list.each_folder(options.merge(:folder => self), &blk)
50
+ end
51
+ association :folders do
52
+ def create(parameters = {})
53
+ @object.create_folder(parameters)
54
+ end
55
+ end
56
+
57
+ def create_folder(parameters = {})
58
+ @list.create_folder(parameters.merge(:folder => absolute_url))
59
+ end
60
+
61
+ def each_document(options = {}, &blk)
62
+ @list.each_document(options.merge(:folder => self), &blk)
63
+ end
64
+ association :documents do
65
+ def create(parameters = {})
66
+ @object.create_document(parameters)
67
+ end
68
+ end
69
+
70
+ def create_document(parameters = {})
71
+ @list.create_document(parameters.merge(:folder => absolute_url))
72
+ end
73
+
74
+ # Returns the item with the given name
75
+ # @param [String] name
76
+ # @return [Item]
13
77
  def item(name)
14
78
  query = Builder::XmlMarkup.new.Query do |xml|
15
79
  xml.Where do |xml|
16
80
  xml.Eq do |xml|
17
81
  xml.FieldRef(:Name => "FileLeafRef")
18
- xml.Value(name, :Type => "String")
82
+ xml.Value(name, :Type => "Text")
19
83
  end
20
84
  end
21
85
  end
22
86
  items(:query => query).first
23
87
  end
24
88
 
25
- def /(name)
26
- item(name)
27
- end
89
+ alias / item
28
90
 
29
- undef attachments
30
- undef content_urls
91
+ undef content
31
92
 
93
+ # @private
32
94
  def to_s
33
95
  "#<ActiveSP::Folder url=#{url}>"
34
96
  end
35
97
 
98
+ # @private
36
99
  alias inspect to_s
37
100
 
38
101
  end
@@ -1,21 +1,90 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
1
26
  module ActiveSP
2
27
 
28
+ # This class represents the field definitions for objects in SharePoint for which the
29
+ # fields cannot be changed and are thus not represented by an object in SharePoint.
30
+ # These include fields of sites, lists, users, grouos, roles, content types and fields.
31
+ # The interface of this class is not as complete as the interface if a Field, mainly
32
+ # because it does not make much sense to do so
3
33
  class GhostField
4
34
 
5
35
  include Util
6
36
 
37
+ # @private
7
38
  attr_reader :Name, :internal_type, :Mult, :ReadOnly
8
39
 
40
+ # @private
9
41
  def initialize(name, type, mult, read_only)
10
42
  @Name, @internal_type, @Mult, @ReadOnly = name, type, mult, read_only
11
43
  end
12
44
 
45
+ # @private
13
46
  def Type
14
47
  translate_internal_type(self)
15
48
  end
16
49
 
50
+ # Returns the attributes of this object as a Hash
51
+ # @return [Hash{String => Integer, Float, String, Time, Boolean, Base}]
17
52
  def attributes
18
- @attributes ||= {
53
+ original_attributes.dup
54
+ end
55
+
56
+ # Returns the value of the attribute of the given name, or nil if this object does not have an attribute by the given name
57
+ # @param [String] name The name of the attribute
58
+ # @return [Integer, Float, String, Time, Boolean, Base]
59
+ def attribute(name)
60
+ current_attributes[name]
61
+ end
62
+
63
+ # Returns whether or not this object has an attribute with the given name
64
+ # @param [String] name The name of the attribute
65
+ # @return [Boolean]
66
+ def has_attribute?(name)
67
+ current_attributes.has_key?(name)
68
+ end
69
+
70
+ # See {Base#method_missing}
71
+ def method_missing(m, *a, &b)
72
+ ms = m.to_s
73
+ if a.length == 0 && has_attribute?(ms)
74
+ attribute(ms)
75
+ else
76
+ super
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def current_attributes
83
+ original_attributes
84
+ end
85
+
86
+ def original_attributes
87
+ @original_attributes ||= {
19
88
  "ColName" => @Name,
20
89
  "DisplayName" => @Name,
21
90
  "Mult" => @Mult,
@@ -1,3 +1,28 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
1
26
  module ActiveSP
2
27
 
3
28
  class Group < Base
@@ -7,35 +32,49 @@ module ActiveSP
7
32
  include Util
8
33
  include InSite
9
34
 
10
- # attr_reader :name
11
-
12
35
  persistent { |site, name, *a| [site.connection, [:group, name]] }
36
+ # @private
13
37
  def initialize(site, name)
14
38
  @site, @name = site, name
15
39
  end
16
40
 
41
+ # See {Base#key}
42
+ # @return [String]
17
43
  def key
18
44
  encode_key("G", [@name])
19
45
  end
20
46
 
47
+ # Returns the list of users in this group
48
+ # @return [User]
21
49
  def users
22
50
  call("UserGroup", "get_user_collection_from_group", "groupName" => @name).xpath("//spdir:User", NS).map do |row|
23
51
  attributes = clean_attributes(row.attributes)
24
52
  User.new(@site, attributes["LoginName"])
25
53
  end
26
54
  end
27
- cache :users, :dup => true
55
+ cache :users, :dup => :always
56
+
57
+ # Returns false. The same method is present on {Role} where it returns true. Roles and groups can generally be
58
+ # duck-typed, and this method is there for the rare case where you do need to make the distinction
59
+ # @return [Boolean]
60
+ def is_role?
61
+ false
62
+ end
28
63
 
64
+ # See {Base#save}
65
+ # @return [void]
66
+ def save
67
+ p untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes)
68
+ end
69
+
70
+ # @private
29
71
  def to_s
30
72
  "#<ActiveSP::Group name=#{@name}>"
31
73
  end
32
74
 
75
+ # @private
33
76
  alias inspect to_s
34
77
 
35
- def is_role?
36
- false
37
- end
38
-
39
78
  private
40
79
 
41
80
  def data
data/lib/activesp/item.rb CHANGED
@@ -1,3 +1,28 @@
1
+ # Copyright (c) 2010 XAOP bvba
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ #
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ #
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
1
26
  module ActiveSP
2
27
 
3
28
  class Item < Base
@@ -6,56 +31,151 @@ module ActiveSP
6
31
  extend Caching
7
32
  include Util
8
33
 
34
+ # Returns the list in which the item is located
35
+ # @return [List]
9
36
  attr_reader :list
10
37
 
11
- def initialize(list, id, folder, uid = nil, url = nil, attributes_before_type_cast = nil)
12
- @list, @id, @folder = list, id, folder
38
+ # @private
39
+ def initialize(list, id, folder = :unset, uid = nil, url = nil, attributes_before_type_cast = nil)
40
+ @list, @id = list, id
41
+ @folder = folder if folder != :unset # We have to allow for nil
13
42
  @uid = uid if uid
14
43
  @site = list.site
15
44
  @url = url if url
16
45
  @attributes_before_type_cast = attributes_before_type_cast if attributes_before_type_cast
17
46
  end
18
47
 
48
+ def ID
49
+ @id
50
+ end
51
+
52
+ def is_folder?
53
+ false
54
+ end
55
+
56
+ # Returns the folder, if any, that this item is located in.
57
+ # @return [Folder, nil]
58
+ def folder
59
+ query = Builder::XmlMarkup.new.Query do |xml|
60
+ xml.Where do |xml|
61
+ xml.Eq do |xml|
62
+ xml.FieldRef(:Name => "FileRef")
63
+ xml.Value(::File.dirname(url), :Type => "Text")
64
+ end
65
+ xml.Eq do |xml|
66
+ xml.FieldRef(:Name => "FSObjType")
67
+ xml.Value(1, :Type => "Text")
68
+ end
69
+ end
70
+ end
71
+ @list.items(:folder => :all, :query => query).first
72
+ end
73
+ cache :folder
74
+
75
+ # Returns the parent of this item.
76
+ # @return [Folder, List]
19
77
  def parent
20
- @folder || @list
78
+ folder || @list
21
79
  end
22
80
 
81
+ # @private
23
82
  def id
24
83
  uid
25
84
  end
26
85
 
86
+ # @private
27
87
  def uid
28
88
  attributes["UniqueID"]
29
89
  end
30
90
  cache :uid
31
91
 
92
+ # The URL of this item
93
+ # @return [String]
32
94
  def url
33
- URL(@list.url).join(attributes["ServerUrl"]).to_s
95
+ # URL(@list.url).join(attributes["ServerUrl"]).to_s
96
+ attributes["ServerUrl"]
34
97
  end
35
98
  cache :url
36
99
 
100
+ def absolute_url
101
+ URL(@list.url).join(attributes["ServerUrl"]).to_s
102
+ end
103
+ cache :absolute_url
104
+
105
+ # See {Base#key}
106
+ # @return [String]
37
107
  def key
38
- encode_key("I", [parent.key, @id])
108
+ encode_key("I", [@list.key, @id])
39
109
  end
40
110
 
41
- def attachments
42
- result = call("Lists", "get_attachment_collection", "listName" => @list.id, "listItemID" => @id)
43
- result.xpath("//sp:Attachment", NS).map { |att| att.text }
111
+ # Returns a list of the URLs of the attachments of this item. Note that for items in a document
112
+ # library, this returns an empty list
113
+ # @return [Array<String>]
114
+ def attachment_urls
115
+ @list.when_list do
116
+ result = call("Lists", "get_attachment_collection", "listName" => @list.id, "listItemID" => @id)
117
+ return result.xpath("//sp:Attachment", NS).map { |att| att.text }
118
+ end
119
+ @list.when_document_library { raise TypeError, "a document library does not support attachments" }
120
+ @list.raise_on_unknown_type
44
121
  end
45
- cache :attachments, :dup => true
122
+ cache :attachment_urls, :dup => :always
46
123
 
47
- def content_urls
48
- case @list.attributes["BaseType"]
49
- when "0", "5"
50
- attachments
51
- when "1"
52
- [url]
53
- else
54
- raise "not yet BaseType = #{@list.attributes["BaseType"].inspect}"
124
+ # Yields each attachment as a ActiveSP::File object.
125
+ #
126
+ def each_attachment
127
+ attachment_urls.each { |url| yield ActiveSP::File.new(self, url, true) }
128
+ end
129
+
130
+ def add_attachment(parameters = {})
131
+ @list.when_list do
132
+ parameters = parameters.dup
133
+ content = parameters.delete(:content) or raise ArgumentError, "Specify the content in the :content parameter"
134
+ file_name = parameters.delete(:file_name) or raise ArgumentError, "Specify the file name in the :file_name parameter"
135
+ result = call("Lists", "add_attachment", "listName" => @list.ID, "listItemID" => self.ID, "fileName" => file_name, "attachment" => Base64.encode64(content.to_s))
136
+ add_result = result.xpath("//sp:AddAttachmentResult", NS).first
137
+ if add_result
138
+ clear_cache_for(:attachment_urls)
139
+ return ActiveSP::File.new(self, add_result.text, true)
140
+ else
141
+ raise "cannot add attachment"
142
+ end
143
+ end
144
+ @list.when_document_library { raise TypeError, "a document library does not support attachments" }
145
+ @list.raise_on_unknown_type
146
+ end
147
+
148
+ association :attachments do
149
+ def create(parameters = {})
150
+ @object.add_attachment(parameters)
55
151
  end
56
152
  end
57
- cache :content_urls, :dup => true
58
153
 
154
+ def content
155
+ @list.when_list { raise TypeError, "a list has attachments" }
156
+ @list.when_document_library { return ActiveSP::File.new(self, url, false) }
157
+ @list.raise_on_unknown_type
158
+ end
159
+
160
+ def content=(data)
161
+ @list.when_list { raise TypeError, "a list has attachments" }
162
+ @list.when_document_library { @list.create_document(:overwrite => true, :content => data, "FileLeafRef" => original_attributes["FileLeafRef"]) }
163
+ @list.raise_on_unknown_type
164
+ end
165
+
166
+ # Returns a list of the content URLs for this item. For items in document libraries, this
167
+ # returns the url, for other items this returns the attachments. These URLs can be used
168
+ # to download all contents. See {Connection#fetch}
169
+ # @return [Array<String>]
170
+ def content_urls
171
+ @list.when_list { return attachment_urls }
172
+ @list.when_document_library { return is_folder? ? [] : [url] }
173
+ @list.raise_on_unknown_type
174
+ end
175
+ cache :content_urls, :dup => :always
176
+
177
+ # Returns the content type of this item
178
+ # @return [ContentType]
59
179
  def content_type
60
180
  ContentType.new(@site, @list, attributes["ContentTypeId"])
61
181
  end
@@ -65,15 +185,99 @@ module ActiveSP
65
185
  # call("Versions", "get_versions", "fileName" => attributes["ServerUrl"])
66
186
  # end
67
187
 
188
+ # See {Base#save}
189
+ # @return [self]
190
+ def save
191
+ update_attributes_internal(untype_cast_attributes(@site, nil, internal_attribute_types, changed_attributes))
192
+ self
193
+ end
194
+
195
+ def check_out
196
+ @list.when_list { raise TypeError, "cannot check out list items; they would disappear" }
197
+ @list.raise_on_unknown_type
198
+ result = call("Lists", "check_out_file", "pageUrl" => absolute_url, "checkoutToLocal" => false)
199
+ checkout_result = result.xpath("//sp:CheckOutFileResult", NS).first.text
200
+ if checkout_result == "true"
201
+ self
202
+ else
203
+ raise "cannot check out this item"
204
+ end
205
+ end
206
+
207
+ def check_in(options = {})
208
+ options = options.dup
209
+ type = options.delete(:type) or raise ArgumentError, ":type parameter not specified"
210
+ comment = options.delete(:comment)
211
+ options.empty? or raise ArgumentError, "unsupported options #{options.keys.map { |k| k.inspect }.join(", ")}"
212
+ @list.when_list { raise TypeError, "cannot check in list items because you can't check them out" }
213
+ @list.raise_on_unknown_type
214
+ if checkin_type = { :minor => 0, :major => 1, :overwrite => 2 }[type]
215
+ if type == :minor && !@list.attribute("EnableMinorVersion")
216
+ raise TypeError, "this list does not support minor versions"
217
+ end
218
+ result = call("Lists", "check_in_file", "pageUrl" => absolute_url, "comment" => comment, "CheckinType" => checkin_type)
219
+ checkin_result = result.xpath("//sp:CheckInFileResult", NS).first.text
220
+ if checkin_result == "true"
221
+ self
222
+ else
223
+ raise "cannot check in this item"
224
+ end
225
+ else
226
+ raise ArgumentError, "invalid checkin type #{type.inspect}, valid values are :minor, :major and :overwrite"
227
+ end
228
+ end
229
+
230
+ def cancel_checkout
231
+ @list.when_list { raise TypeError, "cannot undo check-out for list items because you can't check them out" }
232
+ @list.raise_on_unknown_type
233
+ result = call("Lists", "undo_check_out", "pageUrl" => absolute_url)
234
+ cancel_result = result.xpath("//sp:UndoCheckOutResult", NS).first.text
235
+ if cancel_result == "true"
236
+ self
237
+ else
238
+ raise "cannot cancel check-out for this item"
239
+ end
240
+ end
241
+
242
+ def update_attributes(attributes)
243
+ attributes.each do |k, v|
244
+ set_attribute(k, v)
245
+ end
246
+ save
247
+ end
248
+
249
+ def destroy
250
+ updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => 1) do |xml|
251
+ xml.Method("ID" => 1, "Cmd" => "Delete") do
252
+ xml.Field(self.ID, "Name" => "ID")
253
+ end
254
+ end
255
+ result = call("Lists", "update_list_items", "listName" => @list.id, "updates" => updates)
256
+ create_result = result.xpath("//sp:Result", NS).first
257
+ error_code = create_result.xpath("./sp:ErrorCode", NS).first.text.to_i(0)
258
+ if error_code == 0
259
+ @ID = nil
260
+ else
261
+ raise "cannot create item, error code = #{error_code}"
262
+ end
263
+ self
264
+ end
265
+
266
+ # @private
68
267
  def to_s
69
268
  "#<ActiveSP::Item url=#{url}>"
70
269
  end
71
270
 
271
+ # @private
72
272
  alias inspect to_s
73
273
 
274
+ def ==(object)
275
+ ::ActiveSP::List === object && self.ID == object.ID
276
+ end
277
+
74
278
  private
75
279
 
76
- def data
280
+ def raw_attributes
77
281
  query_options = Builder::XmlMarkup.new.QueryOptions do |xml|
78
282
  xml.Folder
79
283
  end
@@ -85,13 +289,14 @@ module ActiveSP
85
289
  end
86
290
  end
87
291
  end
88
- result = call("Lists", "get_list_items", "listName" => @list.id, "viewFields" => "<ViewFields></ViewFields>", "queryOptions" => query_options, "query" => query)
89
- result.xpath("//z:row", NS).first
292
+ @list.__each_item(query_options, "query" => query) do |attributes|
293
+ return attributes
294
+ end
90
295
  end
91
- cache :data
296
+ cache :raw_attributes
92
297
 
93
298
  def attributes_before_type_cast
94
- clean_item_attributes(data.attributes)
299
+ clean_item_attributes(raw_attributes)
95
300
  end
96
301
  cache :attributes_before_type_cast
97
302
 
@@ -104,6 +309,30 @@ module ActiveSP
104
309
  list.fields_by_name
105
310
  end
106
311
 
312
+ def update_attributes_internal(attributes)
313
+ attributes = attributes.dup
314
+ if file_leaf_ref = attributes.delete("FileLeafRef")
315
+ base_name = ::File.basename(file_leaf_ref, ".*")
316
+ end
317
+ updates = Builder::XmlMarkup.new.Batch("OnError" => "Continue", "ListVersion" => 1) do |xml|
318
+ xml.Method("ID" => 1, "Cmd" => "Update") do
319
+ xml.Field(self.ID, "Name" => "ID")
320
+ construct_xml_for_update_list_items(xml, @list.fields_by_name, attributes)
321
+ xml.Field(base_name, "Name" => "BaseName") if base_name
322
+ end
323
+ end
324
+ result = call("Lists", "update_list_items", "listName" => @list.id, "updates" => updates)
325
+ create_result = result.xpath("//sp:Result", NS).first
326
+ error_code = create_result.xpath("./sp:ErrorCode", NS).first.text.to_i(0)
327
+ if error_code == 0
328
+ row = result.xpath("//z:row", NS).first
329
+ @attributes_before_type_cast = clean_item_attributes(row.attributes)
330
+ reload
331
+ else
332
+ raise "cannot create item, error code = #{error_code}"
333
+ end
334
+ end
335
+
107
336
  end
108
337
 
109
338
  end