to_api 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+ gem "rake"
3
+ gem "activerecord", "2.3.5"
4
+ group :test do
5
+ gem 'rspec', '1.3.0', :require => false
6
+ end
7
+ gem "jeweler"
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activerecord (2.3.5)
5
+ activesupport (= 2.3.5)
6
+ activesupport (2.3.5)
7
+ git (1.2.5)
8
+ jeweler (1.5.1)
9
+ bundler (~> 1.0.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ rake (0.8.7)
13
+ rspec (1.3.0)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ activerecord (= 2.3.5)
20
+ jeweler
21
+ rake
22
+ rspec (= 1.3.0)
data/README ADDED
@@ -0,0 +1 @@
1
+ TODO
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "to_api"
9
+ gem.rubyforge_project = "to_api"
10
+ gem.summary = %Q{Helper for simplifying JSON api creation}
11
+ gem.description = %Q{Helper for simplifying JSON api creation.}
12
+ gem.email = "shawn42@gmail.com"
13
+ gem.homepage = "http://github.com/atomicobject/to_api"
14
+ gem.authors = ["Shawn Anderson","Ryan Fogle"]
15
+ gem.add_development_dependency "rspec"
16
+ gem.add_development_dependency "jeweler"
17
+ gem.add_dependency 'activerecord'
18
+ gem.test_files = FileList['{spec,test}/**/*.rb']
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+
27
+ begin
28
+ require 'spec/rake/spectask'
29
+ desc "Run the code examples in spec/"
30
+ Spec::Rake::SpecTask.new(:spec) do |t|
31
+ t.spec_files = FileList["spec/**/*_spec.rb"]
32
+ end
33
+ task :default => :spec
34
+
35
+ rescue LoadError
36
+ puts "RSpec (or a dependency) not available. Install it with: gem install rspec"
37
+ end
38
+
39
+ # vim: syntax=Ruby
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/lib/to_api.rb ADDED
@@ -0,0 +1,84 @@
1
+ class ActiveRecord::Base
2
+ def to_api(*includes) #assumes all attribute types are fine
3
+ hash = {}
4
+ valid_includes = (self.class.reflect_on_all_associations.map(&:name).map(&:to_s) | self.valid_api_includes)
5
+
6
+ include_hash = {}
7
+ includes.each do |i|
8
+ if i.kind_of?(Hash)
9
+ i.each do |k,v|
10
+ include_hash[k] = v
11
+ end
12
+ else
13
+ include_hash[i] = []
14
+ end
15
+ end
16
+
17
+ include_hash.delete_if{|k,v| !valid_includes.include?(k)}
18
+
19
+ attributes.each do |k, v|
20
+ attribute_includes = include_hash[k] || []
21
+ v = v.to_api(*attribute_includes) if v.respond_to?(:to_api)
22
+ hash[k] = v
23
+ end
24
+
25
+ (include_hash.keys-attributes.keys).each do |relation|
26
+ relation_includes = include_hash[relation] || []
27
+ api_obj = self.send(relation)
28
+ hash[relation.to_s] = api_obj.respond_to?(:to_api) ? api_obj.to_api(*relation_includes) : api_obj
29
+ end
30
+
31
+ hash
32
+ end
33
+
34
+ # override in models
35
+ def valid_api_includes
36
+ []
37
+ end
38
+ end
39
+
40
+ module Enumerable
41
+ def to_api(*includes)
42
+ map{|e|e.to_api(*includes)}
43
+ end
44
+ end
45
+
46
+ #Sadly, Scope isn't enumerable
47
+ class ActiveRecord::NamedScope::Scope
48
+ def to_api(*includes)
49
+ map{|e|e.to_api(*includes)}
50
+ end
51
+ end
52
+
53
+ class Fixnum
54
+ def to_api(*includes)
55
+ self
56
+ end
57
+ end
58
+
59
+ class String
60
+ def to_api(*includes)
61
+ self
62
+ end
63
+ end
64
+
65
+ class DateTime
66
+ def to_api(*includes)
67
+ to_s(:db)
68
+ end
69
+ end
70
+
71
+ class Hash
72
+ def to_api(*includes)
73
+ inject({}) do |memo, (k, v)|
74
+ memo[k]=v.to_api(*includes)
75
+ memo
76
+ end
77
+ end
78
+ end
79
+
80
+ class Symbol
81
+ def to_api(*includes)
82
+ to_s
83
+ end
84
+ end
@@ -0,0 +1,2 @@
1
+ require 'active_record'
2
+ require File.join(File.dirname(__FILE__), "..", "lib", 'to_api')
@@ -0,0 +1,212 @@
1
+ require 'spec_helper'
2
+
3
+ class FakeRecord < ActiveRecord::Base
4
+ def attributes;{};end
5
+ def attributes_from_column_definition;[];end
6
+ def self.columns_hash;{};end
7
+ named_scope :scopez, :conditions => '1=1'
8
+ end
9
+
10
+ class FakeChildRecord < FakeRecord
11
+ end
12
+
13
+ describe '#to_api' do
14
+ shared_examples_for "ignoring includes" do
15
+ it "ignores includes" do
16
+ lambda {instance.to_api(['bar']) }.should_not raise_exception
17
+ end
18
+ end
19
+
20
+ describe Hash do
21
+
22
+ it "returns a new hash with all values to_api'ed" do
23
+ obj1 = stub('1', :to_api => "1 to api")
24
+ obj2 = mock('2', :to_api => "2 to the api")
25
+
26
+ hash = {:one => obj1, :two => obj2}
27
+ hash.to_api.should == {
28
+ :one => "1 to api",
29
+ :two => "2 to the api",
30
+ }
31
+ end
32
+
33
+ it "passes on includes" do
34
+ a = "a"
35
+ a.should_receive(:to_api).with(['bar']).and_return(:apiz)
36
+ {:one => a}.to_api(['bar']).should == {:one => :apiz}
37
+ end
38
+ end
39
+
40
+ describe String do
41
+ it "returns self" do
42
+ foo = "thequickbrownfoxjumpsoverthelazydog"
43
+ foo.to_api.should == foo
44
+ end
45
+ describe "ingoring includes" do
46
+ let(:instance) { "foo" }
47
+ it_should_behave_like "ignoring includes"
48
+ end
49
+
50
+ end
51
+
52
+ describe Integer do
53
+ it "returns self" do
54
+ foo = 8
55
+ foo.to_api.should == foo
56
+ end
57
+ describe "ingoring includes" do
58
+ let(:instance) { 8 }
59
+ it_should_behave_like "ignoring includes"
60
+ end
61
+
62
+ end
63
+
64
+ describe Symbol do
65
+ it "returns string of sym" do
66
+ :foo.to_api.should == "foo"
67
+ end
68
+ describe "ingoring includes" do
69
+ let(:instance) { :foo }
70
+ it_should_behave_like "ignoring includes"
71
+ end
72
+
73
+ end
74
+
75
+ describe DateTime do
76
+ it "returns db string for date time" do
77
+ now = DateTime.parse("2001-11-28 04:01:59")
78
+ now.to_api.should == "2001-11-28 04:01:59"
79
+ end
80
+ describe "ingoring includes" do
81
+ let(:instance) { DateTime.now }
82
+ it_should_behave_like "ignoring includes"
83
+ end
84
+ end
85
+
86
+ describe Enumerable do
87
+ class Enumz
88
+ attr_accessor :kid
89
+ include Enumerable
90
+ def each
91
+ yield @kid
92
+ end
93
+ end
94
+ it "returns to_api of its kids" do
95
+ e = Enumz.new
96
+ e.kid = "a"
97
+ e.kid.should_receive(:to_api).and_return(:apiz)
98
+ [e.kid].to_api.should == [:apiz]
99
+ end
100
+ end
101
+
102
+ describe ActiveRecord::NamedScope::Scope do
103
+ it "returns to_api of its kids" do
104
+ FakeRecord.should_receive(:reflect_on_all_associations).and_return([mock(:name => "fake_child_records")])
105
+ @base = FakeRecord.new
106
+ @base.should_receive(:fake_child_records).and_return([{"foo" => "bar"}])
107
+
108
+ FakeRecord.stub!(:find_every => [@base])
109
+ FakeRecord.scopez.to_api("fake_child_records").should == [{"fake_child_records" => [{"foo" => "bar"}]}]
110
+ end
111
+ end
112
+
113
+ describe Array do
114
+ it "returns to_api of its kids" do
115
+ a = "a"
116
+ a.should_receive(:to_api).and_return(:apiz)
117
+ [a].to_api.should == [:apiz]
118
+ end
119
+
120
+ it "explodes on non-to_api-able kids" do
121
+ lambda { [/boom/].to_api }.should raise_exception
122
+ end
123
+
124
+ it "passes on includes" do
125
+ a = "a"
126
+ a.should_receive(:to_api).with(['bar']).and_return(:apiz)
127
+ [a].to_api(['bar']).should == [:apiz]
128
+ end
129
+ end
130
+
131
+ describe ActiveRecord::Base do
132
+
133
+ describe "with attributes" do
134
+ before do
135
+ @base = FakeRecord.new
136
+ @base.stub!(:attributes => {"age" => mock(:to_api => :apid_age)})
137
+ end
138
+
139
+ it "includes the to_api'd attributes" do
140
+ @base.to_api["age"].should == :apid_age
141
+ end
142
+ end
143
+
144
+ describe "with includes" do
145
+ before do
146
+ @base = FakeRecord.new
147
+ @base.stub!(:attributes => {})
148
+ FakeRecord.stub!(:reflect_on_all_associations => [mock(:name => "foopy_pantz")])
149
+ @base.stub!(:foopy_pantz => "pantz of foop")
150
+ end
151
+
152
+ it "includes the to_api'd attributes" do
153
+ @base.to_api("foopy_pantz")["foopy_pantz"].should == "pantz of foop"
154
+ end
155
+
156
+ it "ignores non association includes" do
157
+ @base.stub!(:yarg => "YYYYARRGG")
158
+ @base.to_api("yarg")["yarg"].should be_nil
159
+ end
160
+
161
+ it "allows for explicitly declaring allowable includes" do
162
+ @base.stub!(:foo => "FOO")
163
+ @base.stub!(:valid_api_includes => ["foo"])
164
+ @base.to_api("foo")["foo"].should == "FOO"
165
+ end
166
+
167
+ describe "versions of params" do
168
+
169
+ before do
170
+ FakeChildRecord.stub!(:reflect_on_all_associations => [mock(:name => "foopy_pantz")])
171
+ @child = FakeChildRecord.new
172
+ @child.stub!(:foopy_pantz => "pantz of foop")
173
+
174
+ FakeRecord.should_receive(:reflect_on_all_associations).and_return([mock(:name => "fake_child_records"), mock(:name => "other_relation")])
175
+ @base = FakeRecord.new
176
+
177
+ @base.should_receive(:fake_child_records).and_return([@child])
178
+ @other_child = mock(:to_api => {"foo"=>"bar"})
179
+ end
180
+
181
+ it "only passes includes to the correct objects" do
182
+ @child.should_receive(:to_api).with().and_return({})
183
+ @base.to_api("fake_child_records","foopy_pantz").should == {"fake_child_records" => [{}]}
184
+ end
185
+
186
+
187
+ it "takes a single arg" do
188
+ @child.should_receive(:to_api).with().and_return({})
189
+ @base.to_api("fake_child_records").should == {"fake_child_records" => [{}]}
190
+ end
191
+
192
+ it "takes array with singles" do
193
+ @child.should_receive(:to_api).with().and_return({})
194
+ @base.to_api("fake_child_records","foopy_pantz").should == {"fake_child_records" => [{}]}
195
+ end
196
+
197
+ it "takes array with subhash" do
198
+ @child.should_receive(:to_api).with("foopy_pantz").and_return({})
199
+ @base.should_receive(:other_relation).and_return(@other_child)
200
+ @base.to_api({"fake_child_records" => "foopy_pantz"}, "other_relation").should == {"fake_child_records" => [{}], "other_relation" => {"foo"=>"bar"}}
201
+ end
202
+
203
+ it "takes array with singles and subhashes" do
204
+ @child.should_receive(:to_api).with("foopy_pantz").and_return({})
205
+ @base.to_api("fake_child_records" => "foopy_pantz").should == {"fake_child_records" => [{}]}
206
+ end
207
+ end
208
+ end
209
+
210
+ end
211
+ end
212
+
data/to_api.gemspec ADDED
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{to_api}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Shawn Anderson", "Ryan Fogle"]
12
+ s.date = %q{2010-12-10}
13
+ s.description = %q{Helper for simplifying JSON api creation.}
14
+ s.email = %q{shawn42@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ "Gemfile",
20
+ "Gemfile.lock",
21
+ "README",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/to_api.rb",
25
+ "spec/spec_helper.rb",
26
+ "spec/to_api_spec.rb",
27
+ "to_api.gemspec"
28
+ ]
29
+ s.homepage = %q{http://github.com/atomicobject/to_api}
30
+ s.require_paths = ["lib"]
31
+ s.rubyforge_project = %q{to_api}
32
+ s.rubygems_version = %q{1.3.7}
33
+ s.summary = %q{Helper for simplifying JSON api creation}
34
+ s.test_files = [
35
+ "spec/spec_helper.rb",
36
+ "spec/to_api_spec.rb"
37
+ ]
38
+
39
+ if s.respond_to? :specification_version then
40
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
41
+ s.specification_version = 3
42
+
43
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
45
+ s.add_runtime_dependency(%q<activerecord>, ["= 2.3.5"])
46
+ s.add_runtime_dependency(%q<jeweler>, [">= 0"])
47
+ s.add_development_dependency(%q<rspec>, [">= 0"])
48
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
49
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
50
+ else
51
+ s.add_dependency(%q<rake>, [">= 0"])
52
+ s.add_dependency(%q<activerecord>, ["= 2.3.5"])
53
+ s.add_dependency(%q<jeweler>, [">= 0"])
54
+ s.add_dependency(%q<rspec>, [">= 0"])
55
+ s.add_dependency(%q<jeweler>, [">= 0"])
56
+ s.add_dependency(%q<activerecord>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<rake>, [">= 0"])
60
+ s.add_dependency(%q<activerecord>, ["= 2.3.5"])
61
+ s.add_dependency(%q<jeweler>, [">= 0"])
62
+ s.add_dependency(%q<rspec>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ s.add_dependency(%q<activerecord>, [">= 0"])
65
+ end
66
+ end
67
+
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: to_api
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Shawn Anderson
14
+ - Ryan Fogle
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-12-10 00:00:00 -05:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ name: rake
35
+ requirement: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - "="
43
+ - !ruby/object:Gem::Version
44
+ hash: 9
45
+ segments:
46
+ - 2
47
+ - 3
48
+ - 5
49
+ version: 2.3.5
50
+ name: activerecord
51
+ requirement: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ name: jeweler
65
+ requirement: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ name: rspec
79
+ requirement: *id004
80
+ - !ruby/object:Gem::Dependency
81
+ type: :development
82
+ prerelease: false
83
+ version_requirements: &id005 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ name: jeweler
93
+ requirement: *id005
94
+ - !ruby/object:Gem::Dependency
95
+ type: :runtime
96
+ prerelease: false
97
+ version_requirements: &id006 !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ name: activerecord
107
+ requirement: *id006
108
+ description: Helper for simplifying JSON api creation.
109
+ email: shawn42@gmail.com
110
+ executables: []
111
+
112
+ extensions: []
113
+
114
+ extra_rdoc_files:
115
+ - README
116
+ files:
117
+ - Gemfile
118
+ - Gemfile.lock
119
+ - README
120
+ - Rakefile
121
+ - VERSION
122
+ - lib/to_api.rb
123
+ - spec/spec_helper.rb
124
+ - spec/to_api_spec.rb
125
+ - to_api.gemspec
126
+ has_rdoc: true
127
+ homepage: http://github.com/atomicobject/to_api
128
+ licenses: []
129
+
130
+ post_install_message:
131
+ rdoc_options: []
132
+
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ hash: 3
150
+ segments:
151
+ - 0
152
+ version: "0"
153
+ requirements: []
154
+
155
+ rubyforge_project: to_api
156
+ rubygems_version: 1.3.7
157
+ signing_key:
158
+ specification_version: 3
159
+ summary: Helper for simplifying JSON api creation
160
+ test_files:
161
+ - spec/spec_helper.rb
162
+ - spec/to_api_spec.rb