active_remote 1.3.3 → 1.4.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.
@@ -38,10 +38,10 @@ module ActiveRemote
|
|
38
38
|
# end
|
39
39
|
#
|
40
40
|
def belongs_to(belongs_to_klass, options={})
|
41
|
-
perform_association(
|
41
|
+
perform_association(belongs_to_klass, options) do |klass, object|
|
42
42
|
foreign_key = options.fetch(:foreign_key) { :"#{belongs_to_klass}_guid" }
|
43
|
-
association_guid =
|
44
|
-
klass.search(:guid => association_guid).first
|
43
|
+
association_guid = object.read_attribute(foreign_key)
|
44
|
+
klass.search(:guid => association_guid).first if association_guid
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -76,9 +76,9 @@ module ActiveRemote
|
|
76
76
|
# end
|
77
77
|
#
|
78
78
|
def has_many(has_many_class, options={})
|
79
|
-
perform_association( has_many_class, options ) do |klass,
|
80
|
-
foreign_key = options.fetch(:foreign_key) { :"#{
|
81
|
-
klass.search(foreign_key =>
|
79
|
+
perform_association( has_many_class, options ) do |klass, object|
|
80
|
+
foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
|
81
|
+
object.guid ? klass.search(foreign_key => object.guid) : []
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -112,9 +112,9 @@ module ActiveRemote
|
|
112
112
|
# end
|
113
113
|
#
|
114
114
|
def has_one(has_one_klass, options={})
|
115
|
-
perform_association(
|
116
|
-
foreign_key = options.fetch(:foreign_key) { :"#{
|
117
|
-
klass.search(foreign_key =>
|
115
|
+
perform_association(has_one_klass, options) do |klass, object|
|
116
|
+
foreign_key = options.fetch(:foreign_key) { :"#{object.class.name.demodulize.underscore}_guid" }
|
117
|
+
klass.search(foreign_key => object.guid).first if object.guid
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
data/lib/active_remote/dirty.rb
CHANGED
@@ -51,6 +51,15 @@ module ActiveRemote
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
# Override #write_attribute (along with #[]=) so we can provide support for
|
55
|
+
# ActiveModel::Dirty.
|
56
|
+
#
|
57
|
+
def write_attribute(name, value)
|
58
|
+
__send__("#{name}_will_change!") unless value == self[name]
|
59
|
+
super
|
60
|
+
end
|
61
|
+
alias_method :[]=, :write_attribute
|
62
|
+
|
54
63
|
private
|
55
64
|
|
56
65
|
# Override ActiveAttr's attribute= method so we can provide support for
|
@@ -1,144 +1,168 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe ActiveRemote::Association do
|
4
4
|
let(:record) { double(:record) }
|
5
5
|
let(:records) { [ record ] }
|
6
6
|
|
7
|
-
describe
|
8
|
-
|
9
|
-
|
10
|
-
let(:author_guid) { 'AUT-123' }
|
7
|
+
describe ".belongs_to" do
|
8
|
+
context "simple association" do
|
9
|
+
let(:author_guid) { "AUT-123" }
|
11
10
|
|
12
11
|
subject { Post.new(:author_guid => author_guid) }
|
12
|
+
|
13
13
|
it { should respond_to(:author) }
|
14
14
|
|
15
|
-
it
|
15
|
+
it "searches the associated model for a single record" do
|
16
16
|
Author.should_receive(:search).with(:guid => subject.author_guid).and_return(records)
|
17
17
|
subject.author.should eq record
|
18
18
|
end
|
19
19
|
|
20
|
-
it
|
20
|
+
it "memoizes the result record" do
|
21
21
|
Author.should_receive(:search).once.with(:guid => subject.author_guid).and_return(records)
|
22
22
|
3.times { subject.author.should eq record }
|
23
23
|
end
|
24
24
|
|
25
|
-
context
|
26
|
-
|
25
|
+
context "when guid is nil" do
|
26
|
+
subject { Post.new }
|
27
|
+
|
28
|
+
it "returns nil" do
|
29
|
+
subject.author.should be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when the search is empty" do
|
34
|
+
it "returns a nil" do
|
27
35
|
Author.should_receive(:search).with(:guid => subject.author_guid).and_return([])
|
28
36
|
subject.author.should be_nil
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
|
-
context
|
34
|
-
let(:author_guid) {
|
41
|
+
context "specific association with class name" do
|
42
|
+
let(:author_guid) { "AUT-456" }
|
35
43
|
|
36
44
|
subject { Post.new(:author_guid => author_guid) }
|
37
45
|
it { should respond_to(:coauthor) }
|
38
46
|
|
39
|
-
it
|
47
|
+
it "searches the associated model for a single record" do
|
40
48
|
Author.should_receive(:search).with(:guid => subject.author_guid).and_return(records)
|
41
49
|
subject.author.should eq record
|
42
50
|
end
|
43
51
|
end
|
44
52
|
|
45
|
-
context
|
46
|
-
let(:author_guid) {
|
53
|
+
context "specific association with class name and foreign_key" do
|
54
|
+
let(:author_guid) { "AUT-456" }
|
47
55
|
|
48
56
|
subject { Post.new(:author_guid => author_guid) }
|
49
57
|
it { should respond_to(:bestseller) }
|
50
58
|
|
51
|
-
it
|
59
|
+
it "searches the associated model for a single record" do
|
52
60
|
Author.should_receive(:search).with(:guid => subject.bestseller_guid).and_return(records)
|
53
61
|
subject.author.should eq record
|
54
62
|
end
|
55
63
|
end
|
56
|
-
|
57
64
|
end
|
58
65
|
|
59
|
-
describe
|
66
|
+
describe ".has_many" do
|
60
67
|
let(:records) { [ record, record, record ] }
|
61
|
-
let(:guid) {
|
68
|
+
let(:guid) { "AUT-123" }
|
62
69
|
|
63
70
|
subject { Author.new(:guid => guid) }
|
71
|
+
|
64
72
|
it { should respond_to(:posts) }
|
65
73
|
|
66
|
-
it
|
74
|
+
it "searches the associated model for all associated records" do
|
67
75
|
Post.should_receive(:search).with(:author_guid => subject.guid).and_return(records)
|
68
76
|
subject.posts.should eq records
|
69
77
|
end
|
70
78
|
|
71
|
-
it
|
79
|
+
it "memoizes the result record" do
|
72
80
|
Post.should_receive(:search).once.with(:author_guid => subject.guid).and_return(records)
|
73
81
|
3.times { subject.posts.should eq records }
|
74
82
|
end
|
75
83
|
|
76
|
-
context
|
77
|
-
|
84
|
+
context "when guid is nil" do
|
85
|
+
subject { Author.new }
|
86
|
+
|
87
|
+
it "returns []" do
|
88
|
+
subject.posts.should eq []
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when the search is empty" do
|
93
|
+
it "returns the empty set" do
|
78
94
|
Post.should_receive(:search).with(:author_guid => subject.guid).and_return([])
|
79
95
|
subject.posts.should be_empty
|
80
96
|
end
|
81
97
|
end
|
82
98
|
|
83
|
-
context
|
99
|
+
context "specific association with class name" do
|
84
100
|
it { should respond_to(:flagged_posts) }
|
85
101
|
|
86
|
-
it
|
102
|
+
it "searches the associated model for a single record" do
|
87
103
|
Post.should_receive(:search).with(:author_guid => subject.guid).and_return([])
|
88
104
|
subject.flagged_posts.should be_empty
|
89
105
|
end
|
90
106
|
end
|
91
107
|
|
92
|
-
context
|
108
|
+
context "specific association with class name and foreign_key" do
|
93
109
|
it { should respond_to(:bestseller_posts) }
|
94
110
|
|
95
|
-
it
|
111
|
+
it "searches the associated model for multiple record" do
|
96
112
|
Post.should_receive(:search).with(:bestseller_guid => subject.guid).and_return(records)
|
97
113
|
subject.bestseller_posts.should eq(records)
|
98
114
|
end
|
99
115
|
end
|
100
116
|
end
|
101
117
|
|
102
|
-
describe
|
103
|
-
let(:guid) {
|
118
|
+
describe ".has_one" do
|
119
|
+
let(:guid) { "PST-123" }
|
104
120
|
|
105
121
|
subject { Post.new(:guid => guid) }
|
122
|
+
|
106
123
|
it { should respond_to(:category) }
|
107
124
|
|
108
|
-
it
|
125
|
+
it "searches the associated model for all associated records" do
|
109
126
|
Category.should_receive(:search).with(:post_guid => subject.guid).and_return(records)
|
110
127
|
subject.category.should eq record
|
111
128
|
end
|
112
129
|
|
113
|
-
it
|
130
|
+
it "memoizes the result record" do
|
114
131
|
Category.should_receive(:search).once.with(:post_guid => subject.guid).and_return(records)
|
115
132
|
3.times { subject.category.should eq record }
|
116
133
|
end
|
117
134
|
|
118
|
-
context
|
119
|
-
|
135
|
+
context "when guid is nil" do
|
136
|
+
subject { Post.new }
|
137
|
+
|
138
|
+
it "returns nil" do
|
139
|
+
subject.category.should be_nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when the search is empty" do
|
144
|
+
it "returns a nil value" do
|
120
145
|
Category.should_receive(:search).with(:post_guid => subject.guid).and_return([])
|
121
146
|
subject.category.should be_nil
|
122
147
|
end
|
123
148
|
end
|
124
149
|
|
125
|
-
context
|
150
|
+
context "specific association with class name" do
|
126
151
|
it { should respond_to(:main_category) }
|
127
152
|
|
128
|
-
it
|
153
|
+
it "searches the associated model for a single record" do
|
129
154
|
Category.should_receive(:search).with(:post_guid => subject.guid).and_return(records)
|
130
155
|
subject.main_category.should eq record
|
131
156
|
end
|
132
157
|
end
|
133
158
|
|
134
|
-
context
|
159
|
+
context "specific association with class name and foreign_key" do
|
135
160
|
it { should respond_to(:default_category) }
|
136
161
|
|
137
|
-
it
|
162
|
+
it "searches the associated model for a single record" do
|
138
163
|
Category.should_receive(:search).with(:template_post_guid => subject.guid).and_return(records)
|
139
164
|
subject.default_category.should eq record
|
140
165
|
end
|
141
166
|
end
|
142
167
|
end
|
143
|
-
|
144
168
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRemote::Dirty do
|
4
|
+
context "when writing attributes through the setter" do
|
5
|
+
subject { Post.new(:name => 'foo') }
|
6
|
+
|
7
|
+
before {
|
8
|
+
subject.previous_changes.try(:clear)
|
9
|
+
subject.changed_attributes.try(:clear)
|
10
|
+
}
|
11
|
+
|
12
|
+
context "when the value changes" do
|
13
|
+
before { subject.name = 'bar' }
|
14
|
+
|
15
|
+
its(:name_changed?) { should be_true }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when the value doesn't change" do
|
19
|
+
before { subject.name = 'foo' }
|
20
|
+
|
21
|
+
its(:name_changed?) { should be_false }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when writing attributes directly" do
|
26
|
+
subject { Post.new(:name => 'foo') }
|
27
|
+
|
28
|
+
before {
|
29
|
+
subject.previous_changes.try(:clear)
|
30
|
+
subject.changed_attributes.try(:clear)
|
31
|
+
}
|
32
|
+
|
33
|
+
context "when the value changes" do
|
34
|
+
before { subject[:name] = 'bar' }
|
35
|
+
|
36
|
+
its(:name_changed?) { should be_true }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when the value doesn't change" do
|
40
|
+
before { subject[:name] = 'foo' }
|
41
|
+
|
42
|
+
its(:name_changed?) { should be_false }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#reload" do
|
47
|
+
subject { Post.new(:name => 'foo') }
|
48
|
+
|
49
|
+
before {
|
50
|
+
subject.stub(:last_response).and_return({})
|
51
|
+
subject.stub(:execute)
|
52
|
+
subject.reload
|
53
|
+
}
|
54
|
+
|
55
|
+
its(:changes) { should be_empty }
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#save" do
|
59
|
+
let!(:changes) { subject.changes }
|
60
|
+
|
61
|
+
subject { Post.new(:name => 'foo') }
|
62
|
+
|
63
|
+
before {
|
64
|
+
subject.stub(:create_or_update).and_return(true)
|
65
|
+
subject.save
|
66
|
+
}
|
67
|
+
|
68
|
+
its(:previous_changes) { should eq changes }
|
69
|
+
its(:changes) { should be_empty }
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#save!" do
|
73
|
+
let!(:changes) { subject.changes }
|
74
|
+
|
75
|
+
subject { Post.new(:name => 'foo') }
|
76
|
+
|
77
|
+
before {
|
78
|
+
subject.stub(:save).and_return(true)
|
79
|
+
subject.save!
|
80
|
+
}
|
81
|
+
|
82
|
+
its(:previous_changes) { should eq changes }
|
83
|
+
its(:changes) { should be_empty }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#serialize_records" do
|
87
|
+
let(:post) { Post.new }
|
88
|
+
let(:record) { ::Generic::Remote::Post.new(:name => 'foo') }
|
89
|
+
let(:response) { double(:response, :records => [ record ]) }
|
90
|
+
|
91
|
+
before {
|
92
|
+
post.stub(:last_response).and_return(response)
|
93
|
+
}
|
94
|
+
|
95
|
+
it "clears previous changes" do
|
96
|
+
records = post.serialize_records
|
97
|
+
records.first.previous_changes.should be_nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it "clears changes" do
|
101
|
+
records = post.serialize_records
|
102
|
+
records.first.changes.should be_empty
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_remote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_attr
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- spec/lib/active_remote/association_spec.rb
|
179
179
|
- spec/lib/active_remote/base_spec.rb
|
180
180
|
- spec/lib/active_remote/bulk_spec.rb
|
181
|
+
- spec/lib/active_remote/dirty_spec.rb
|
181
182
|
- spec/lib/active_remote/dsl_spec.rb
|
182
183
|
- spec/lib/active_remote/persistence_spec.rb
|
183
184
|
- spec/lib/active_remote/rpc_spec.rb
|
@@ -218,7 +219,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
218
219
|
version: '0'
|
219
220
|
segments:
|
220
221
|
- 0
|
221
|
-
hash:
|
222
|
+
hash: -2137387569376097013
|
222
223
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
223
224
|
none: false
|
224
225
|
requirements:
|
@@ -227,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
228
|
version: '0'
|
228
229
|
segments:
|
229
230
|
- 0
|
230
|
-
hash:
|
231
|
+
hash: -2137387569376097013
|
231
232
|
requirements: []
|
232
233
|
rubyforge_project:
|
233
234
|
rubygems_version: 1.8.24
|
@@ -239,6 +240,7 @@ test_files:
|
|
239
240
|
- spec/lib/active_remote/association_spec.rb
|
240
241
|
- spec/lib/active_remote/base_spec.rb
|
241
242
|
- spec/lib/active_remote/bulk_spec.rb
|
243
|
+
- spec/lib/active_remote/dirty_spec.rb
|
242
244
|
- spec/lib/active_remote/dsl_spec.rb
|
243
245
|
- spec/lib/active_remote/persistence_spec.rb
|
244
246
|
- spec/lib/active_remote/rpc_spec.rb
|