activesp 0.0.1 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +25 -0
- data/README.rdoc +105 -0
- data/Rakefile +35 -6
- data/VERSION +1 -1
- data/lib/activesp.rb +27 -0
- data/lib/activesp/associations.rb +76 -0
- data/lib/activesp/base.rb +93 -7
- data/lib/activesp/caching.rb +32 -3
- data/lib/activesp/connection.rb +53 -16
- data/lib/activesp/content_type.rb +50 -1
- data/lib/activesp/field.rb +48 -2
- data/lib/activesp/file.rb +71 -0
- data/lib/activesp/folder.rb +72 -9
- data/lib/activesp/ghost_field.rb +70 -1
- data/lib/activesp/group.rb +46 -7
- data/lib/activesp/item.rb +252 -23
- data/lib/activesp/list.rb +284 -81
- data/lib/activesp/permission_set.rb +39 -4
- data/lib/activesp/persistent_caching.rb +61 -1
- data/lib/activesp/role.rb +49 -8
- data/lib/activesp/root.rb +67 -3
- data/lib/activesp/site.rb +110 -20
- data/lib/activesp/url.rb +27 -0
- data/lib/activesp/user.rb +39 -1
- data/lib/activesp/util.rb +198 -40
- metadata +42 -16
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
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
|
+
|
10
|
+
Software is furnished to do so, subject to the following
|
11
|
+
conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
19
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
21
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
22
|
+
|
23
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
24
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
25
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
= ActiveSP Release 0.0.3 "Under Pressure" (Aug 27th 2010)
|
2
|
+
|
3
|
+
== What?
|
4
|
+
|
5
|
+
ActiveSP is a library for talking to SharePoint through its web services in an
|
6
|
+
object-oriented way.
|
7
|
+
|
8
|
+
At the moment it only provides read-only access and write access to list items.
|
9
|
+
Full write access is on the way!
|
10
|
+
|
11
|
+
== Why?
|
12
|
+
|
13
|
+
Because Ruby is great and SharePoint's popularity is a fact of life.
|
14
|
+
|
15
|
+
== When?
|
16
|
+
|
17
|
+
This library is pure Ruby and does not need a Ruby VM running on .NET (such as IronRuby).
|
18
|
+
Use this library when using IronRuby is not an option, or when it needs to run on more
|
19
|
+
than IronRuby.
|
20
|
+
|
21
|
+
The web services are not fully functional and somewhat slow, so if you can use
|
22
|
+
the .NET platform then consider talking to the .NET API's directly instead.
|
23
|
+
|
24
|
+
== How?
|
25
|
+
|
26
|
+
Install the gem and its dependencies:
|
27
|
+
|
28
|
+
gem install activesp
|
29
|
+
|
30
|
+
Create a file <tt>test.rb</tt> like this:
|
31
|
+
|
32
|
+
require 'rubygems'
|
33
|
+
require 'activesp'
|
34
|
+
|
35
|
+
def browse(item, indentation = 0)
|
36
|
+
puts " " * indentation + "- " + item.class.to_s + " : " + item.url
|
37
|
+
case item
|
38
|
+
when ActiveSP::Site
|
39
|
+
puts " " * indentation + " Title = #{item.Title}, Description = #{item.Description}"
|
40
|
+
item.sites.each { |site| browse(site, indentation + 1) }
|
41
|
+
item.lists.each { |list| browse(list, indentation + 1) }
|
42
|
+
when ActiveSP::List
|
43
|
+
puts " " * indentation + " Description = #{item.Description}, Hidden = #{item.Hidden}"
|
44
|
+
item.items.each { |item| browse(item, indentation + 1) }
|
45
|
+
when ActiveSP::Folder
|
46
|
+
item.items.each { |item| browse(item, indentation + 1) }
|
47
|
+
when ActiveSP::Item
|
48
|
+
item.content_urls.each do |url|
|
49
|
+
puts " " * indentation + " Content URL = #{url}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
c = ActiveSP::Connection.new(:login => "your login", :password => "your password", :root => "URL of root site")
|
55
|
+
|
56
|
+
browse(c.root)
|
57
|
+
|
58
|
+
Run <tt>ruby test.rb</tt> and it will print the structure of your SharePoint site.
|
59
|
+
|
60
|
+
The examples directory contains this example plus a few others. We will add more along the way.
|
61
|
+
|
62
|
+
== Support
|
63
|
+
|
64
|
+
We support read access to sites (webs), lists, items, documents, folders, content type,
|
65
|
+
columns (fields), content, users, groups, roles.
|
66
|
+
|
67
|
+
We support write access to list items (including documents): create, update and delete list items.
|
68
|
+
|
69
|
+
We do not yet support life cycles, versions, full write support.
|
70
|
+
|
71
|
+
== Compatibility
|
72
|
+
|
73
|
+
We have tested ActiveSP with SharePoint 2007 and SharePoint 2010. ActiveSP has been tested
|
74
|
+
on Mac OS X with Ruby 1.8.6, but we do not see any reason why it would not work on Linux
|
75
|
+
or Windows, or with other Ruby implementations.
|
76
|
+
|
77
|
+
For release 0.0.3, we have not tested extensively on SharePoint 2007 so we can't guarantee
|
78
|
+
compatibility.
|
79
|
+
|
80
|
+
== Changelog
|
81
|
+
|
82
|
+
=== ActiveSP Release 0.0.3 "Under Pressure" (Aug 27th 2010)
|
83
|
+
|
84
|
+
* Added write support for list items (including documents): create, update, delete
|
85
|
+
* Use association proxies for list items and item attachments
|
86
|
+
* Decode field names (e.g., File_x0020_Type becomes File Type)
|
87
|
+
* A few bug fixes
|
88
|
+
* Added method to ask for list changes since token
|
89
|
+
|
90
|
+
=== ActiveSP Release 0.0.1 "Space Oddity" (Apr 9th 2010)
|
91
|
+
|
92
|
+
* Initial release
|
93
|
+
|
94
|
+
== License
|
95
|
+
|
96
|
+
ActiveSP is released under the MIT license. The usual disclaimers apply, including that we are
|
97
|
+
not responsible for inevitable Ruby addiction.
|
98
|
+
|
99
|
+
See the LICENSE file included in the distribution for further details.
|
100
|
+
|
101
|
+
== Who?
|
102
|
+
|
103
|
+
ActiveSP is copyright (c) 2010 XAOP bvba
|
104
|
+
|
105
|
+
Visit us at http://www.xaop.com.
|
data/Rakefile
CHANGED
@@ -1,5 +1,31 @@
|
|
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
|
require 'rubygems'
|
2
27
|
require 'rake/gempackagetask'
|
28
|
+
require 'yard'
|
3
29
|
|
4
30
|
ACTIVESP_VERSION = File.readlines("VERSION")[0][/[\d.]*/]
|
5
31
|
|
@@ -9,18 +35,17 @@ spec = Gem::Specification.new do |s|
|
|
9
35
|
s.version = ACTIVESP_VERSION
|
10
36
|
s.author = "Peter Vanbroekhoven"
|
11
37
|
s.email = "peter@xaop.com"
|
12
|
-
|
38
|
+
s.homepage = "http://www.xaop.com/labs/activesp"
|
13
39
|
s.summary = "Interface to SharePoint"
|
14
|
-
s.description =
|
15
|
-
|
16
|
-
s.files += %w(VERSION Rakefile)
|
40
|
+
s.description = "An object-oriented interface to SharePoint that uses the web services provided by SharePoint to connect to it. Supports SharePoint 2007 and 2010."
|
41
|
+
s.files += %w(VERSION LICENSE README.rdoc Rakefile)
|
17
42
|
s.files += Dir['lib/**/*.rb']
|
18
43
|
# s.bindir = "bin"
|
19
|
-
# s.executables.push(*(Dir['bin/*.rb']
|
44
|
+
# s.executables.push(*(Dir['bin/*.rb']))
|
20
45
|
s.add_dependency('savon-xaop')
|
21
46
|
s.add_dependency('nokogiri')
|
22
47
|
# s.rdoc_options << '--exclude' << 'ext' << '--main' << 'README'
|
23
|
-
# s.extra_rdoc_files = ["README"
|
48
|
+
# s.extra_rdoc_files = ["README"]
|
24
49
|
s.has_rdoc = false
|
25
50
|
s.require_paths << 'lib'
|
26
51
|
# s.autorequire = 'mysql'
|
@@ -32,3 +57,7 @@ Rake::GemPackageTask.new(spec) do |pkg|
|
|
32
57
|
pkg.need_zip = true
|
33
58
|
pkg.need_tar = true
|
34
59
|
end
|
60
|
+
|
61
|
+
YARD::Rake::YardocTask.new do |t|
|
62
|
+
t.options = ['--no-private', '--readme', 'README.rdoc']
|
63
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/lib/activesp.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
|
require 'nokogiri'
|
2
27
|
require 'time'
|
3
28
|
|
@@ -6,6 +31,7 @@ end
|
|
6
31
|
|
7
32
|
require 'activesp/util'
|
8
33
|
require 'activesp/caching'
|
34
|
+
require 'activesp/associations'
|
9
35
|
require 'activesp/persistent_caching'
|
10
36
|
|
11
37
|
require 'activesp/base'
|
@@ -24,3 +50,4 @@ require 'activesp/user'
|
|
24
50
|
require 'activesp/group'
|
25
51
|
require 'activesp/role'
|
26
52
|
require 'activesp/permission_set'
|
53
|
+
require 'activesp/file'
|
@@ -0,0 +1,76 @@
|
|
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
|
+
|
26
|
+
module ActiveSP
|
27
|
+
|
28
|
+
# @private
|
29
|
+
module Associations
|
30
|
+
|
31
|
+
class AssociationProxy
|
32
|
+
|
33
|
+
include Enumerable
|
34
|
+
|
35
|
+
def initialize(object, &element_getter)
|
36
|
+
@object = object
|
37
|
+
@element_getter = element_getter
|
38
|
+
end
|
39
|
+
|
40
|
+
def each(&blk)
|
41
|
+
@element_getter.call(blk)
|
42
|
+
end
|
43
|
+
|
44
|
+
def first
|
45
|
+
each { |element| return element }
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def last
|
50
|
+
inject { |_, element| element }
|
51
|
+
end
|
52
|
+
|
53
|
+
def count
|
54
|
+
inject(0) { |cnt, _| cnt + 1 }
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def association(name, each_method = ("each_" + name.to_s.sub(/s\z/, "")).to_sym, &blk)
|
62
|
+
proxy = Class.new(AssociationProxy) do
|
63
|
+
class_eval(&blk) if blk
|
64
|
+
define_method(:to_s) { "#{@object.to_s}.#{name}" }
|
65
|
+
define_method(:inspect) { "#{@object.inspect}.#{name}" }
|
66
|
+
end
|
67
|
+
define_method(name) do |*a|
|
68
|
+
proxy.new(self) do |blk|
|
69
|
+
send(each_method, *a, &blk)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
data/lib/activesp/base.rb
CHANGED
@@ -1,35 +1,99 @@
|
|
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
|
+
# The base class for all objects stored in SharePoint
|
3
29
|
class Base
|
4
30
|
|
5
31
|
extend Caching
|
32
|
+
extend Associations
|
6
33
|
|
34
|
+
# Returns a key that can be used to retrieve this object later on using {Connection#find_by_key}
|
35
|
+
# @return [String]
|
36
|
+
def key
|
37
|
+
raise "This is here for documentation purposes only"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the attributes of this object as a Hash
|
41
|
+
# @return [Hash{String => Integer, Float, String, Time, Boolean, Base}]
|
7
42
|
def attributes
|
8
43
|
current_attributes
|
9
44
|
end
|
10
|
-
cache :attributes, :dup =>
|
45
|
+
cache :attributes, :dup => :always
|
11
46
|
|
47
|
+
# Returns the types of the attributes of this object as a Hash
|
48
|
+
# @return [Hash{String => Field}]
|
12
49
|
def attribute_types
|
13
50
|
internal_attribute_types
|
14
51
|
end
|
15
|
-
cache :attribute_types, :dup =>
|
52
|
+
cache :attribute_types, :dup => :always
|
16
53
|
|
54
|
+
# Returns whether or not this object has an attribute with the given name
|
55
|
+
# @param [String] name The name of the attribute
|
56
|
+
# @return [Boolean]
|
17
57
|
def has_attribute?(name)
|
18
|
-
|
58
|
+
current_attributes.has_key?(name)
|
19
59
|
end
|
20
60
|
|
61
|
+
# Returns whether or not this object has an attribute with the given name that can be assigned to
|
62
|
+
# @param [String] name The name of the attribute
|
63
|
+
# @return [Boolean]
|
21
64
|
def has_writable_attribute?(name)
|
22
|
-
has_attribute?(name)
|
65
|
+
has_attribute?(name) and attr = internal_attribute_types[name] and !attr.ReadOnly
|
23
66
|
end
|
24
67
|
|
68
|
+
# Returns the value of the attribute of the given name, or nil if this object does not have an attribute by the given name
|
69
|
+
# @param [String] name The name of the attribute
|
70
|
+
# @return [Integer, Float, String, Time, Boolean, Base]
|
25
71
|
def attribute(name)
|
26
|
-
|
72
|
+
current_attributes[name]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the type of the attribute by the given name, or nil if this object does not have an attribute by the given name
|
76
|
+
# @param [String] name The name of the attribute
|
77
|
+
# @return [Field]
|
78
|
+
def attribute_type(name)
|
79
|
+
internal_attribute_types[name]
|
27
80
|
end
|
28
81
|
|
82
|
+
# Sets the attribute with the given name to the given value
|
83
|
+
# @param [String] name The name of the attribute
|
84
|
+
# @param [Integer, Float, String, Time, Boolean, Base] value The value to assign
|
85
|
+
# @return [Integer, Float, String, Time, Boolean, Base] The assigned value
|
86
|
+
# @raise [ArgumentError] Raised when this object does not have an attribute by the given name or if the attribute by the given name is read-only
|
29
87
|
def set_attribute(name, value)
|
30
|
-
|
88
|
+
has_attribute?(name) and field = attribute_type(name) and internal_attribute_types[name] or raise ArgumentError, "#{self} has no field by the name #{name}"
|
89
|
+
!field.ReadOnly or raise ArgumentError, "field #{name} of #{self} is read-only"
|
90
|
+
current_attributes[name] = type_check_attribute(field, value)
|
31
91
|
end
|
32
92
|
|
93
|
+
# Provides convenient getters and setters for attributes. Note that no name mangling
|
94
|
+
# is done, so an attribute such as Title is accessed as obj.Title. The main rationale
|
95
|
+
# behind this is that name mangling is usually not lossless (e.g., both <tt>Title</tt>
|
96
|
+
# and <tt>title</tt> could map to the more Rubyish <tt>title</tt>) and imperfect.
|
33
97
|
def method_missing(m, *a, &b)
|
34
98
|
ms = m.to_s
|
35
99
|
if a.length == 0 && has_attribute?(ms)
|
@@ -41,13 +105,35 @@ module ActiveSP
|
|
41
105
|
end
|
42
106
|
end
|
43
107
|
|
108
|
+
# Reloads the object from the server
|
109
|
+
# @return [void]
|
110
|
+
def reload
|
111
|
+
end
|
112
|
+
|
113
|
+
# Saves the object to the server. Raises an exception when the save fails
|
114
|
+
# @return [void]
|
115
|
+
def save
|
116
|
+
end
|
117
|
+
|
44
118
|
private
|
45
119
|
|
46
120
|
def current_attributes
|
47
|
-
original_attributes
|
121
|
+
original_attributes.inject({}) { |h, (k, v)| h[k] = ::Array === v ? v.dup.freeze : v ; h }
|
48
122
|
end
|
49
123
|
cache :current_attributes
|
50
124
|
|
125
|
+
def changed_attributes
|
126
|
+
before = original_attributes
|
127
|
+
after = current_attributes
|
128
|
+
changes = {}
|
129
|
+
after.each do |name, value|
|
130
|
+
if before[name] != value
|
131
|
+
changes[name] = value
|
132
|
+
end
|
133
|
+
end
|
134
|
+
changes
|
135
|
+
end
|
136
|
+
|
51
137
|
end
|
52
138
|
|
53
139
|
end
|