versions 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/History.txt +6 -1
- data/README.rdoc +41 -7
- data/Rakefile +1 -0
- data/lib/versions.rb +3 -2
- data/lib/versions/after_commit.rb +69 -0
- data/lib/versions/attachment.rb +104 -0
- data/lib/versions/auto.rb +3 -2
- data/lib/versions/multi.rb +44 -16
- data/lib/versions/shared_attachment.rb +62 -2
- data/lib/versions/version.rb +1 -1
- data/test/fixtures.rb +8 -4
- data/test/fixtures/files/bird.jpg +0 -0
- data/test/fixtures/files/lake.jpg +0 -0
- data/test/helper.rb +35 -3
- data/test/unit/after_commit_test.rb +107 -0
- data/test/unit/attachment_test.rb +258 -220
- data/test/unit/auto_test.rb +20 -3
- data/test/unit/multi_test.rb +58 -14
- data/versions.gemspec +11 -5
- metadata +18 -5
- data/lib/versions/shared_attachment/attachment.rb +0 -66
- data/lib/versions/shared_attachment/owner.rb +0 -77
- data/lib/versions/transparent.rb +0 -98
data/test/unit/auto_test.rb
CHANGED
@@ -29,8 +29,25 @@ class AutoTest < Test::Unit::TestCase
|
|
29
29
|
@version = BadVersion.create('title' => 'Socrate')
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
context 'if changed' do
|
33
|
+
should 'clone on update' do
|
34
|
+
assert_difference('Version.count', 1) do
|
35
|
+
subject.update_attributes('title' => 'Aristotle')
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
assert_difference('Version.count', 1) do
|
40
|
+
subject.update_attributes('title' => 'Augustin')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'if not changed' do
|
46
|
+
should 'not clone on update' do
|
47
|
+
assert_difference('Version.count', 0) do
|
48
|
+
subject.update_attributes('title' => 'Socrate')
|
49
|
+
end
|
50
|
+
end
|
34
51
|
end
|
35
52
|
end
|
36
53
|
|
@@ -92,7 +109,7 @@ class AutoTest < Test::Unit::TestCase
|
|
92
109
|
subject.update_attributes('title' => 'Aristotle')
|
93
110
|
assert_equal 2, subject.number
|
94
111
|
|
95
|
-
subject.update_attributes('title' => '
|
112
|
+
subject.update_attributes('title' => 'Kierkegaard')
|
96
113
|
assert_equal 3, subject.number
|
97
114
|
end
|
98
115
|
end
|
data/test/unit/multi_test.rb
CHANGED
@@ -23,15 +23,12 @@ class MultiTest < Test::Unit::TestCase
|
|
23
23
|
include Versions::Multi
|
24
24
|
|
25
25
|
set_table_name :pages
|
26
|
-
has_multiple :foos, :class_name => 'MultiTest::SimpleVersion'
|
26
|
+
has_multiple :foos, :class_name => 'MultiTest::SimpleVersion', :inverse => 'node'
|
27
27
|
end
|
28
28
|
|
29
29
|
class Version < ActiveRecord::Base
|
30
30
|
set_table_name :versions
|
31
31
|
include Versions::Auto
|
32
|
-
def should_clone?
|
33
|
-
changed?
|
34
|
-
end
|
35
32
|
end
|
36
33
|
class Page < ActiveRecord::Base
|
37
34
|
set_table_name :pages
|
@@ -82,16 +79,12 @@ class MultiTest < Test::Unit::TestCase
|
|
82
79
|
end
|
83
80
|
|
84
81
|
should 'rollback if foo save fails on create' do
|
82
|
+
page = nil
|
85
83
|
assert_difference('MultiTest::SimpleVersion.count', 0) do
|
86
84
|
assert_difference('MultiTest::SimplePage.count', 0) do
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
rescue ActiveRecord::RecordInvalid => err
|
91
|
-
assert_equal 'Validation failed: Foo title should not contain letter y', err.message
|
92
|
-
raise
|
93
|
-
end
|
94
|
-
end
|
85
|
+
page = SimplePage.new('foo_attributes' => {'title' => 'Fly'})
|
86
|
+
assert !page.save
|
87
|
+
assert_contains page.errors.full_messages, 'Foo title should not contain letter y'
|
95
88
|
end
|
96
89
|
end
|
97
90
|
end
|
@@ -102,6 +95,18 @@ class MultiTest < Test::Unit::TestCase
|
|
102
95
|
assert !page.update_attributes('foo_attributes' => {'title' => 'fly'})
|
103
96
|
assert_equal 'should not contain letter y', page.errors['foo_title']
|
104
97
|
end
|
98
|
+
|
99
|
+
should 'find owner back using inverse' do
|
100
|
+
page = SimplePage.create
|
101
|
+
assert_equal page, page.foo.node
|
102
|
+
end
|
103
|
+
|
104
|
+
should 'list foos' do
|
105
|
+
page = SimplePage.create('foo_attributes' => {'title' => 'One'})
|
106
|
+
page.foo = SimpleVersion.new('title' => 'Two')
|
107
|
+
page.save
|
108
|
+
assert_equal 2, page.foos.size
|
109
|
+
end
|
105
110
|
end
|
106
111
|
|
107
112
|
context 'A class with multiple auto versions' do
|
@@ -111,12 +116,12 @@ class MultiTest < Test::Unit::TestCase
|
|
111
116
|
assert page.update_attributes('version_attributes' => {'title' => 'newTitle'})
|
112
117
|
end
|
113
118
|
end
|
114
|
-
|
119
|
+
|
115
120
|
should 'mark new version as not dirty after create' do
|
116
121
|
page = Page.create
|
117
122
|
assert !page.version.changed?
|
118
123
|
end
|
119
|
-
|
124
|
+
|
120
125
|
should 'mark new version as not dirty after update' do
|
121
126
|
page = Page.create
|
122
127
|
assert page.update_attributes('version_attributes' => {'title' => 'Yodle'})
|
@@ -136,5 +141,44 @@ class MultiTest < Test::Unit::TestCase
|
|
136
141
|
assert page.update_attributes('version_attributes' => {'title' => 'One'})
|
137
142
|
end
|
138
143
|
end
|
144
|
+
|
145
|
+
|
146
|
+
should 'list versions' do
|
147
|
+
page = Page.create('version_attributes' => {'title' => 'One'})
|
148
|
+
assert page.update_attributes('version_attributes' => {'title' => 'Two'})
|
149
|
+
assert page.update_attributes('version_attributes' => {'title' => 'Three'})
|
150
|
+
assert_equal 3, page.versions.size
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'Defining association with custom foreign_key' do
|
155
|
+
should 'not raise an exception if the key exists' do
|
156
|
+
assert_nothing_raised do
|
157
|
+
class Book < ActiveRecord::Base
|
158
|
+
set_table_name :pages
|
159
|
+
include Versions::Multi
|
160
|
+
has_multiple :versions, :class_name => 'MultiTest::SimpleVersion', :inverse => 'big_book', :foreign_key => 'node_id'
|
161
|
+
has_multiple :versions, :class_name => 'MultiTest::SimpleVersion', :inverse => :big_book, :foreign_key => :node_id
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
should 'raise an exception if the key does not exist' do
|
167
|
+
assert_raise(TypeError) do
|
168
|
+
class Book < ActiveRecord::Base
|
169
|
+
set_table_name :pages
|
170
|
+
include Versions::Multi
|
171
|
+
has_multiple :versions, :class_name => 'MultiTest::SimpleVersion', :inverse => 'big_book', :foreign_key => 'bug_id'
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
assert_raise(TypeError) do
|
176
|
+
class Book < ActiveRecord::Base
|
177
|
+
set_table_name :pages
|
178
|
+
include Versions::Multi
|
179
|
+
has_multiple :versions, :class_name => 'MultiTest::SimpleVersion', :inverse => :big_book, :foreign_key => :bug_id
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
139
183
|
end
|
140
184
|
end
|
data/versions.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{versions}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Gaspard Bucher"]
|
12
|
-
s.date = %q{2010-02-
|
12
|
+
s.date = %q{2010-02-15}
|
13
13
|
s.description = %q{A list of libraries to work with ActiveRecord model versioning: Auto (duplicate on save), Multi (hide many versions behind a single one), Transparent (hide versions from outside world), Property (define properties on model, store them in versions)}
|
14
14
|
s.email = %q{gaspard@teti.ch}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,16 +24,18 @@ Gem::Specification.new do |s|
|
|
24
24
|
"README.rdoc",
|
25
25
|
"Rakefile",
|
26
26
|
"lib/versions.rb",
|
27
|
+
"lib/versions/after_commit.rb",
|
28
|
+
"lib/versions/attachment.rb",
|
27
29
|
"lib/versions/auto.rb",
|
28
30
|
"lib/versions/destroy.rb",
|
29
31
|
"lib/versions/multi.rb",
|
30
32
|
"lib/versions/shared_attachment.rb",
|
31
|
-
"lib/versions/shared_attachment/attachment.rb",
|
32
|
-
"lib/versions/shared_attachment/owner.rb",
|
33
|
-
"lib/versions/transparent.rb",
|
34
33
|
"lib/versions/version.rb",
|
35
34
|
"test/fixtures.rb",
|
35
|
+
"test/fixtures/files/bird.jpg",
|
36
|
+
"test/fixtures/files/lake.jpg",
|
36
37
|
"test/helper.rb",
|
38
|
+
"test/unit/after_commit_test.rb",
|
37
39
|
"test/unit/attachment_test.rb",
|
38
40
|
"test/unit/auto_test.rb",
|
39
41
|
"test/unit/multi_test.rb",
|
@@ -49,6 +51,7 @@ Gem::Specification.new do |s|
|
|
49
51
|
s.test_files = [
|
50
52
|
"test/fixtures.rb",
|
51
53
|
"test/helper.rb",
|
54
|
+
"test/unit/after_commit_test.rb",
|
52
55
|
"test/unit/attachment_test.rb",
|
53
56
|
"test/unit/auto_test.rb",
|
54
57
|
"test/unit/multi_test.rb",
|
@@ -63,15 +66,18 @@ Gem::Specification.new do |s|
|
|
63
66
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
64
67
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
65
68
|
s.add_development_dependency(%q<property>, [">= 0.8.1"])
|
69
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
66
70
|
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
67
71
|
else
|
68
72
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
69
73
|
s.add_dependency(%q<property>, [">= 0.8.1"])
|
74
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
70
75
|
s.add_dependency(%q<activerecord>, [">= 0"])
|
71
76
|
end
|
72
77
|
else
|
73
78
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
74
79
|
s.add_dependency(%q<property>, [">= 0.8.1"])
|
80
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
75
81
|
s.add_dependency(%q<activerecord>, [">= 0"])
|
76
82
|
end
|
77
83
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: versions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gaspard Bucher
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-15 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -32,6 +32,16 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.8.1
|
34
34
|
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activesupport
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
35
45
|
- !ruby/object:Gem::Dependency
|
36
46
|
name: activerecord
|
37
47
|
type: :runtime
|
@@ -59,16 +69,18 @@ files:
|
|
59
69
|
- README.rdoc
|
60
70
|
- Rakefile
|
61
71
|
- lib/versions.rb
|
72
|
+
- lib/versions/after_commit.rb
|
73
|
+
- lib/versions/attachment.rb
|
62
74
|
- lib/versions/auto.rb
|
63
75
|
- lib/versions/destroy.rb
|
64
76
|
- lib/versions/multi.rb
|
65
77
|
- lib/versions/shared_attachment.rb
|
66
|
-
- lib/versions/shared_attachment/attachment.rb
|
67
|
-
- lib/versions/shared_attachment/owner.rb
|
68
|
-
- lib/versions/transparent.rb
|
69
78
|
- lib/versions/version.rb
|
70
79
|
- test/fixtures.rb
|
80
|
+
- test/fixtures/files/bird.jpg
|
81
|
+
- test/fixtures/files/lake.jpg
|
71
82
|
- test/helper.rb
|
83
|
+
- test/unit/after_commit_test.rb
|
72
84
|
- test/unit/attachment_test.rb
|
73
85
|
- test/unit/auto_test.rb
|
74
86
|
- test/unit/multi_test.rb
|
@@ -106,6 +118,7 @@ summary: A list of libraries to work with ActiveRecord model versioning
|
|
106
118
|
test_files:
|
107
119
|
- test/fixtures.rb
|
108
120
|
- test/helper.rb
|
121
|
+
- test/unit/after_commit_test.rb
|
109
122
|
- test/unit/attachment_test.rb
|
110
123
|
- test/unit/auto_test.rb
|
111
124
|
- test/unit/multi_test.rb
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module Versions
|
2
|
-
# This module enables file attachments to versions. The file is shared between versions if
|
3
|
-
# it is not changed. The Attachment only stores a reference to the file which is saved in the
|
4
|
-
# filesystem.
|
5
|
-
module SharedAttachment
|
6
|
-
class Attachment < ::ActiveRecord::Base
|
7
|
-
set_table_name 'attachments'
|
8
|
-
after_destroy :destroy_file
|
9
|
-
after_save :write_file
|
10
|
-
|
11
|
-
def unlink(model)
|
12
|
-
link_count = model.class.count(:conditions => ["attachment_id = ? AND id != ?", self.id, model.id])
|
13
|
-
if link_count == 0
|
14
|
-
destroy
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def file=(file)
|
19
|
-
@file = file
|
20
|
-
self[:filename] = get_filename(file)
|
21
|
-
end
|
22
|
-
|
23
|
-
def filepath
|
24
|
-
@filepath ||= begin
|
25
|
-
digest = Digest::SHA1.hexdigest(self[:id].to_s)
|
26
|
-
"#{digest[0..0]}/#{digest[1..1]}/#{filename}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def write_file
|
32
|
-
after_commit do
|
33
|
-
make_file(filepath, @file)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def destroy_file
|
38
|
-
after_commit do
|
39
|
-
remove_file
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def make_file(path, data)
|
44
|
-
FileUtils::mkpath(File.dirname(path)) unless File.exist?(File.dirname(path))
|
45
|
-
if data.respond_to?(:rewind)
|
46
|
-
data.rewind
|
47
|
-
end
|
48
|
-
File.open(path, "wb") { |f| f.syswrite(data.read) }
|
49
|
-
end
|
50
|
-
|
51
|
-
def remove_file
|
52
|
-
FileUtils.rm(filepath)
|
53
|
-
end
|
54
|
-
|
55
|
-
def get_filename(file)
|
56
|
-
# make sure name is not corrupted
|
57
|
-
fname = file.original_filename.gsub(/[^a-zA-Z\-_0-9\.]/,'')
|
58
|
-
if fname[0..0] == '.'
|
59
|
-
# Forbid names starting with a dot
|
60
|
-
fname = Digest::SHA1.hexdigest(Time.now.to_i.to_s)[0..6]
|
61
|
-
end
|
62
|
-
fname
|
63
|
-
end
|
64
|
-
end # Attachment
|
65
|
-
end # SharedAttachment
|
66
|
-
end # Versions
|
@@ -1,77 +0,0 @@
|
|
1
|
-
|
2
|
-
module Zena
|
3
|
-
module Use
|
4
|
-
|
5
|
-
# The attachement module provides shared file attachments to a class with a copy-on-write
|
6
|
-
# pattern.
|
7
|
-
# Basically the module provides 'file=' and 'file' methods.
|
8
|
-
module SharedAttachment
|
9
|
-
module ClassMethods
|
10
|
-
def set_attachment_class(class_name)
|
11
|
-
belongs_to :attachment,
|
12
|
-
:class_name => class_name,
|
13
|
-
:foreign_key => 'attachment_id'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.included(base)
|
18
|
-
base.class_eval do
|
19
|
-
before_create :save_attachment
|
20
|
-
before_update :attachment_before_update
|
21
|
-
before_destroy :attachment_before_destroy
|
22
|
-
|
23
|
-
extend Zena::Use::SharedAttachment::ClassMethods
|
24
|
-
set_attachment_class 'Zena::Use::SharedAttachment::Attachment'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def file=(file)
|
29
|
-
if attachment
|
30
|
-
@attachment_to_unlink = self.attachment
|
31
|
-
self.attachment = nil
|
32
|
-
end
|
33
|
-
@attachment_need_save = true
|
34
|
-
self.build_attachment(:file => file)
|
35
|
-
end
|
36
|
-
|
37
|
-
def filepath
|
38
|
-
attachment ? attachment.filepath : nil
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
def save_attachment
|
43
|
-
if @attachment_need_save
|
44
|
-
@attachment_need_save = nil
|
45
|
-
attachment.save
|
46
|
-
else
|
47
|
-
true
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def attachment_before_update
|
52
|
-
if @attachment_to_unlink
|
53
|
-
@attachment_to_unlink.unlink(self)
|
54
|
-
@attachment_to_unlink = nil
|
55
|
-
end
|
56
|
-
save_attachment
|
57
|
-
end
|
58
|
-
|
59
|
-
def attachment_before_destroy
|
60
|
-
if attachment = self.attachment
|
61
|
-
attachment.unlink(self)
|
62
|
-
else
|
63
|
-
true
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def unlink_attachment_mark
|
68
|
-
@attachment_to_unlink = self.attachment
|
69
|
-
end
|
70
|
-
|
71
|
-
def unlink_attachment
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
end # SharedAttachment
|
76
|
-
end # Use
|
77
|
-
end # Zena
|
data/lib/versions/transparent.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
module Zena
|
2
|
-
module Use
|
3
|
-
# This module lets the user use a node as if it was not versioned and will
|
4
|
-
# take care of routing the attributes between the node and the version.
|
5
|
-
module TransparentVersion
|
6
|
-
|
7
|
-
def self.included(base)
|
8
|
-
base.class_eval do
|
9
|
-
# When writing attributes, we send everything that we do not know of
|
10
|
-
# to the version.
|
11
|
-
def attributes_with_multi_version=(attributes)
|
12
|
-
columns = self.class.column_names
|
13
|
-
version_attributes = {}
|
14
|
-
attributes.keys.each do |k|
|
15
|
-
if !respond_to?("#{k}=") && !columns.include?(k)
|
16
|
-
version_attributes[k] = attributes.delete(k)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
version.attributes = version_attributes
|
20
|
-
self.attributes_without_multi_version = attributes
|
21
|
-
end
|
22
|
-
|
23
|
-
alias_method_chain :attributes=, :multi_version
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
# We need method_missing in forms, normal access in templates should be made
|
29
|
-
# through 'node.version.xxxx', not 'node.xxxx'.
|
30
|
-
def method_missing(meth, *args)
|
31
|
-
method = meth.to_s
|
32
|
-
if !args.empty? || method[-1..-1] == '?' || self.class.column_names.include?(method)
|
33
|
-
super
|
34
|
-
elsif version.respond_to?(meth)
|
35
|
-
version.send(meth)
|
36
|
-
else
|
37
|
-
#version.prop[meth.to_s]
|
38
|
-
super
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Any attribute starting with 'v_' belongs to the 'version' or 'redaction'
|
43
|
-
# Any attribute starting with 'c_' belongs to the 'version' or 'redaction' content
|
44
|
-
# FIXME: performance: create methods on the fly so that next calls will not pass through 'method_missing'. #189.
|
45
|
-
# FIXME: this should not be used anymore. Remove.
|
46
|
-
# def method_missing(meth, *args)
|
47
|
-
# if meth.to_s =~ /^(v_|c_|d_)(([\w_\?]+)(=?))$/
|
48
|
-
# target = $1
|
49
|
-
# method = $2
|
50
|
-
# value = $3
|
51
|
-
# mode = $4
|
52
|
-
# if mode == '='
|
53
|
-
# begin
|
54
|
-
# # set
|
55
|
-
# unless recipient = redaction
|
56
|
-
# # remove trailing '='
|
57
|
-
# redaction_error(meth.to_s[0..-2], "could not be set (no redaction)")
|
58
|
-
# return
|
59
|
-
# end
|
60
|
-
#
|
61
|
-
# case target
|
62
|
-
# when 'c_'
|
63
|
-
# if recipient.content_class && recipient = recipient.redaction_content
|
64
|
-
# recipient.send(method,*args)
|
65
|
-
# else
|
66
|
-
# redaction_error(meth.to_s[0..-2], "cannot be set") # remove trailing '='
|
67
|
-
# end
|
68
|
-
# when 'd_'
|
69
|
-
# recipient.prop[method[0..-2]] = args[0]
|
70
|
-
# else
|
71
|
-
# recipient.send(method,*args)
|
72
|
-
# end
|
73
|
-
# rescue NoMethodError
|
74
|
-
# # bad attribute, just ignore
|
75
|
-
# end
|
76
|
-
# else
|
77
|
-
# # read
|
78
|
-
# recipient = version
|
79
|
-
# if target == 'd_'
|
80
|
-
# version.prop[method]
|
81
|
-
# else
|
82
|
-
# recipient = recipient.content if target == 'c_'
|
83
|
-
# return nil unless recipient
|
84
|
-
# begin
|
85
|
-
# recipient.send(method,*args)
|
86
|
-
# rescue NoMethodError
|
87
|
-
# # bad attribute
|
88
|
-
# return nil
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
# else
|
93
|
-
# super
|
94
|
-
# end
|
95
|
-
# end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|