to_api 1.1.1 → 1.1.2
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/lib/to_api/version.rb +1 -1
- data/lib/to_api.rb +111 -57
- data/spec/to_api_spec.rb +84 -18
- metadata +4 -4
data/lib/to_api/version.rb
CHANGED
data/lib/to_api.rb
CHANGED
@@ -1,32 +1,80 @@
|
|
1
|
+
module ToApiSelf
|
2
|
+
def to_api(*includes)
|
3
|
+
self
|
4
|
+
end
|
5
|
+
end
|
6
|
+
[ Fixnum, String, DateTime, Date, Time, NilClass ].each do |klass|
|
7
|
+
klass.send(:include, ToApiSelf)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ToApiInstanceMethods
|
11
|
+
def build_to_api_include_hash(*includes)
|
12
|
+
include_hash = {}
|
13
|
+
includes.each do |i|
|
14
|
+
if i.kind_of?(Hash)
|
15
|
+
i.each do |k,v|
|
16
|
+
include_hash[k] = v
|
17
|
+
end
|
18
|
+
else
|
19
|
+
include_hash[i] = []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
include_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ToApiFilter
|
27
|
+
def add_to_api_filter(include_name, &block)
|
28
|
+
@_to_api_filters ||= {}
|
29
|
+
@_to_api_filters[include_name] = block
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_api_filters=(filters)
|
33
|
+
@_to_api_filters = filters
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_api_filters
|
37
|
+
@_to_api_filters ||={}
|
38
|
+
@_to_api_filters
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
1
42
|
if Object.const_defined? :ActiveRecord
|
43
|
+
|
2
44
|
class ActiveRecord::Base
|
45
|
+
include ToApiFilter
|
46
|
+
|
3
47
|
def to_api(*includes) #assumes all attribute types are fine
|
4
48
|
hash = {}
|
5
|
-
valid_includes = (self.class.reflect_on_all_associations.map(&:name).map(&:to_s) | self.valid_api_includes)
|
49
|
+
valid_includes = (self.class.reflect_on_all_associations.map(&:name).map(&:to_s) | self.valid_api_includes | self.attributes.keys)
|
6
50
|
|
7
|
-
include_hash =
|
8
|
-
|
9
|
-
if
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
else
|
14
|
-
include_hash[i.to_s] = []
|
51
|
+
include_hash = build_to_api_ar_include_hash(*includes)
|
52
|
+
include_hash.keys.each do |inc|
|
53
|
+
if to_api_filters.has_key?(inc)
|
54
|
+
child_includes = include_hash.delete(inc) || []
|
55
|
+
hash[inc] = to_api_filters[inc].call self, child_includes
|
15
56
|
end
|
16
57
|
end
|
17
|
-
|
58
|
+
|
18
59
|
include_hash.delete_if{|k,v| !valid_includes.include?(k.to_s)}
|
19
|
-
|
20
60
|
to_api_attributes.each do |k, v|
|
21
|
-
|
22
|
-
|
23
|
-
|
61
|
+
unless hash[k]
|
62
|
+
v.to_api_filters = to_api_filters if v.respond_to? :to_api_filters
|
63
|
+
|
64
|
+
attribute_includes = include_hash[k] || []
|
65
|
+
to_api_v = v.to_api(*[attribute_includes].flatten.compact)
|
66
|
+
hash[k] = to_api_v
|
67
|
+
end
|
24
68
|
end
|
25
69
|
|
26
|
-
(include_hash.keys-
|
27
|
-
|
28
|
-
|
29
|
-
|
70
|
+
(include_hash.keys-to_api_attributes.keys).each do |relation|
|
71
|
+
unless hash[relation]
|
72
|
+
relation_includes = include_hash[relation] || []
|
73
|
+
api_obj = self.send(relation)
|
74
|
+
api_obj.to_api_filters = to_api_filters if api_obj.respond_to? :to_api_filters
|
75
|
+
|
76
|
+
hash[relation.to_s] = api_obj.respond_to?(:to_api) ? api_obj.to_api(*[relation_includes].flatten.compact) : api_obj
|
77
|
+
end
|
30
78
|
end
|
31
79
|
|
32
80
|
hash
|
@@ -40,58 +88,69 @@ if Object.const_defined? :ActiveRecord
|
|
40
88
|
def to_api_attributes
|
41
89
|
attributes
|
42
90
|
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def build_to_api_ar_include_hash(*includes)
|
94
|
+
include_hash = {}
|
95
|
+
includes.each do |i|
|
96
|
+
if i.kind_of?(Hash)
|
97
|
+
i.each do |k,v|
|
98
|
+
include_hash[k.to_s] = v
|
99
|
+
end
|
100
|
+
else
|
101
|
+
include_hash[i.to_s] = []
|
102
|
+
end
|
103
|
+
end
|
104
|
+
include_hash
|
105
|
+
end
|
106
|
+
|
43
107
|
end
|
44
108
|
|
45
109
|
#Sadly, Scope isn't enumerable
|
46
110
|
class ActiveRecord::NamedScope::Scope
|
111
|
+
include ToApiFilter
|
47
112
|
def to_api(*includes)
|
48
|
-
map{|e|
|
113
|
+
map{|e|
|
114
|
+
e.to_api_filters = to_api_filters if e.respond_to? :to_api_filters
|
115
|
+
e.to_api(*includes)
|
116
|
+
}
|
49
117
|
end
|
50
118
|
end
|
51
119
|
end
|
52
120
|
|
53
|
-
|
54
|
-
|
55
|
-
map{|e|e.to_api(*includes)}
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class Fixnum
|
121
|
+
class Array
|
122
|
+
include ToApiFilter
|
60
123
|
def to_api(*includes)
|
61
|
-
|
62
|
-
|
63
|
-
end
|
124
|
+
map{|e|
|
125
|
+
e.to_api_filters = to_api_filters if e.respond_to? :to_api_filters
|
64
126
|
|
65
|
-
|
66
|
-
|
67
|
-
self
|
127
|
+
e.to_api(*includes)
|
128
|
+
}
|
68
129
|
end
|
69
130
|
end
|
70
131
|
|
71
|
-
class
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class Date
|
132
|
+
class Hash
|
133
|
+
include ToApiFilter
|
134
|
+
include ToApiInstanceMethods
|
78
135
|
def to_api(*includes)
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
136
|
+
values = {}
|
82
137
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
138
|
+
include_hash = build_to_api_include_hash(*includes)
|
139
|
+
|
140
|
+
include_hash.keys.each do |inc|
|
141
|
+
if to_api_filters.has_key?(inc)
|
142
|
+
child_includes = include_hash[inc]
|
143
|
+
values[inc] = to_api_filters[inc].call self, child_includes
|
144
|
+
end
|
145
|
+
end
|
88
146
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
147
|
+
(keys-values.keys).each do |k|
|
148
|
+
val = self[k]
|
149
|
+
val.to_api_filters = to_api_filters if val.respond_to? :to_api_filters
|
150
|
+
child_includes = include_hash[k] || []
|
151
|
+
values[k] = val.to_api(*[child_includes].flatten.compact)
|
94
152
|
end
|
153
|
+
values
|
95
154
|
end
|
96
155
|
end
|
97
156
|
|
@@ -101,8 +160,3 @@ class Symbol
|
|
101
160
|
end
|
102
161
|
end
|
103
162
|
|
104
|
-
class NilClass
|
105
|
-
def to_api(*includes)
|
106
|
-
self
|
107
|
-
end
|
108
|
-
end
|
data/spec/to_api_spec.rb
CHANGED
@@ -8,6 +8,8 @@ class FakeRecord < ActiveRecord::Base
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class OtherFakeRecord < FakeRecord
|
11
|
+
def attributes;{"my_field"=>''};end
|
12
|
+
def my_field;'yar';end
|
11
13
|
end
|
12
14
|
|
13
15
|
class FakeChildRecord < FakeRecord
|
@@ -35,8 +37,8 @@ describe '#to_api' do
|
|
35
37
|
|
36
38
|
it "passes on includes" do
|
37
39
|
a = "a"
|
38
|
-
a.should_receive(:to_api).with(
|
39
|
-
{:one => a}.to_api(['bar']).should == {:one => :apiz}
|
40
|
+
a.should_receive(:to_api).with('bar').and_return(:apiz)
|
41
|
+
{:one => a}.to_api(:one => ['bar']).should == {:one => :apiz}
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
@@ -108,22 +110,6 @@ describe '#to_api' do
|
|
108
110
|
end
|
109
111
|
end
|
110
112
|
|
111
|
-
describe Enumerable do
|
112
|
-
class Enumz
|
113
|
-
attr_accessor :kid
|
114
|
-
include Enumerable
|
115
|
-
def each
|
116
|
-
yield @kid
|
117
|
-
end
|
118
|
-
end
|
119
|
-
it "returns to_api of its kids" do
|
120
|
-
e = Enumz.new
|
121
|
-
e.kid = "a"
|
122
|
-
e.kid.should_receive(:to_api).and_return(:apiz)
|
123
|
-
[e.kid].to_api.should == [:apiz]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
113
|
describe ActiveRecord::NamedScope::Scope do
|
128
114
|
it "returns to_api of its kids" do
|
129
115
|
FakeRecord.should_receive(:reflect_on_all_associations).and_return([mock(:name => "fake_child_records")])
|
@@ -182,6 +168,10 @@ describe '#to_api' do
|
|
182
168
|
it "includes the to_api'd attributes" do
|
183
169
|
@base.to_api["age"].should == :apid_age
|
184
170
|
end
|
171
|
+
|
172
|
+
it "allows the inclusion of attributes" do
|
173
|
+
@base.to_api("my_field")["my_field"].should == 'yar'
|
174
|
+
end
|
185
175
|
end
|
186
176
|
|
187
177
|
describe "with includes" do
|
@@ -258,8 +248,84 @@ describe '#to_api' do
|
|
258
248
|
@base.to_api("fake_child_records" => "foopy_pantz").should == {"fake_child_records" => [{}]}
|
259
249
|
end
|
260
250
|
end
|
251
|
+
|
252
|
+
describe "#add_to_api_filter" do
|
253
|
+
it "adds a filter" do
|
254
|
+
@base = OtherFakeRecord.new
|
255
|
+
@base.should_not_receive(:my_field)
|
256
|
+
@base.add_to_api_filter("my_field") do |parent, child_includes|
|
257
|
+
"YO-HO-HO"
|
258
|
+
end
|
259
|
+
|
260
|
+
@base.to_api("my_field")["my_field"].should == "YO-HO-HO"
|
261
|
+
end
|
262
|
+
|
263
|
+
it "sends filter to child" do
|
264
|
+
FakeRecord.stub!(:reflect_on_all_associations => [mock(:name => "kids")])
|
265
|
+
FakeChildRecord.stub!(:reflect_on_all_associations => [mock(:name => "foopy_pantz")])
|
266
|
+
|
267
|
+
@base = FakeRecord.new
|
268
|
+
@base.stub!(:attributes => {})
|
269
|
+
|
270
|
+
@child = FakeChildRecord.new
|
271
|
+
|
272
|
+
@child.stub!(:foopy_pantz => "pantz of foop")
|
273
|
+
|
274
|
+
@base.should_receive(:kids).and_return([@child])
|
275
|
+
|
276
|
+
@base.add_to_api_filter("foopy_pantz") do |parent, child_includes|
|
277
|
+
"kachaa"
|
278
|
+
end
|
279
|
+
|
280
|
+
@base.to_api("kids" => "foopy_pantz").should == {"kids" => [{"foopy_pantz" => "kachaa"}]}
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe "#add_to_api_filter" do
|
287
|
+
before do
|
288
|
+
@subhash = {:b => :c, :d => :e}
|
289
|
+
@hash = {:a => @subhash}
|
261
290
|
end
|
262
291
|
|
292
|
+
it "puts blocks return value in for filtered key" do
|
293
|
+
@hash.add_to_api_filter("count") do |parent, child_includes|
|
294
|
+
@hash.count
|
295
|
+
end
|
296
|
+
|
297
|
+
@hash.to_api("count")["count"].should == 1
|
298
|
+
end
|
299
|
+
|
300
|
+
it "nests hashes with filters" do
|
301
|
+
@hash.add_to_api_filter("id") do |parent, child_includes|
|
302
|
+
parent.object_id
|
303
|
+
end
|
304
|
+
|
305
|
+
api_object = @hash.to_api({"id" => "", :a => "id"})
|
306
|
+
api_object["id"].should == @hash.object_id
|
307
|
+
api_object[:a]["id"].should == @subhash.object_id
|
308
|
+
end
|
309
|
+
|
310
|
+
it "nests hashes of hashes with filters" do
|
311
|
+
@hash.add_to_api_filter("id") do |parent, child_includes|
|
312
|
+
parent.object_id
|
313
|
+
end
|
314
|
+
|
315
|
+
api_object = @hash.to_api({"id" => "", :a => {"id" => ""}})
|
316
|
+
api_object["id"].should == @hash.object_id
|
317
|
+
api_object[:a]["id"].should == @subhash.object_id
|
318
|
+
end
|
319
|
+
|
320
|
+
it "nests hashes with filters with hash params" do
|
321
|
+
@hash.add_to_api_filter("id") do |parent, child_includes|
|
322
|
+
parent.object_id
|
323
|
+
end
|
324
|
+
|
325
|
+
api_object = @hash.to_api(:a => "id")
|
326
|
+
api_object["id"].should be_nil
|
327
|
+
api_object[:a]["id"].should == @subhash.object_id
|
328
|
+
end
|
263
329
|
end
|
264
330
|
end
|
265
331
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: to_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
9
|
+
- 2
|
10
|
+
version: 1.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Shawn Anderson
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-01-
|
19
|
+
date: 2011-01-18 00:00:00 -05:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|