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.
@@ -1,3 +1,3 @@
1
1
  module ToApi
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
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
- includes.each do |i|
9
- if i.kind_of?(Hash)
10
- i.each do |k,v|
11
- include_hash[k.to_s] = v
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
- attribute_includes = include_hash[k] || []
22
- v = v.to_api(*attribute_includes)
23
- hash[k] = v
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-attributes.keys).each do |relation|
27
- relation_includes = include_hash[relation] || []
28
- api_obj = self.send(relation)
29
- hash[relation.to_s] = api_obj.respond_to?(:to_api) ? api_obj.to_api(*relation_includes) : api_obj
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|e.to_api(*includes)}
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
- module Enumerable
54
- def to_api(*includes)
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
- self
62
- end
63
- end
124
+ map{|e|
125
+ e.to_api_filters = to_api_filters if e.respond_to? :to_api_filters
64
126
 
65
- class String
66
- def to_api(*includes)
67
- self
127
+ e.to_api(*includes)
128
+ }
68
129
  end
69
130
  end
70
131
 
71
- class DateTime
72
- def to_api(*includes)
73
- self
74
- end
75
- end
76
-
77
- class Date
132
+ class Hash
133
+ include ToApiFilter
134
+ include ToApiInstanceMethods
78
135
  def to_api(*includes)
79
- self
80
- end
81
- end
136
+ values = {}
82
137
 
83
- class Time
84
- def to_api(*includes)
85
- self
86
- end
87
- end
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
- class Hash
90
- def to_api(*includes)
91
- inject({}) do |memo, (k, v)|
92
- memo[k]=v.to_api(*includes)
93
- memo
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(['bar']).and_return(:apiz)
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: 17
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 1
10
- version: 1.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-12 00:00:00 -05:00
19
+ date: 2011-01-18 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency