api_view 0.5.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 474ae37f4261ac132bcca7331d12e3eac1c56a62
4
+ data.tar.gz: a794b2806e37db11ae671fd870e88f905f61025d
5
+ SHA512:
6
+ metadata.gz: 9461e48f8d5e2cfd3f4a71217d9143cbae4577f67693167e52939eda282fbf8acdb3afe2e26ca70575102d26211bf27430e03e52d092bb936fbe2b51bfa6f0ed
7
+ data.tar.gz: f8b2ec2d180baa84d3933d8e603cd08e3e3717e0688cbed49730078da2576879e1ca8f3eca7d20b311b0e0a3f0d69886aba907c35a8ef065d64c89fbab0565a4
@@ -0,0 +1,7 @@
1
+ :directories:
2
+ - lib
3
+ :excludes:
4
+ - test
5
+ - .direnv
6
+ :single_line_report: true
7
+ :show_link_in_terminal: true
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+
5
+ before_install:
6
+ - gem update --system
7
+ - gem --version
8
+ - gem install bundler
9
+
10
+ script: sh/test
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in api_view.gemspec
4
+ gemspec
5
+
6
+ gem 'codecov', :require => false, :group => :test
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Roman Heinrich
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,119 @@
1
+ # ApiView
2
+
3
+ [![Build Status](https://travis-ci.org/mindreframer/api_view.svg?branch=master)](http://travis-ci.org/mindreframer/api_view)
4
+ [![codecov.io](https://codecov.io/github/mindreframer/api_view/coverage.svg?branch=master)](https://codecov.io/github/mindreframer/api_view?branch=master)
5
+
6
+ a small and very performance focused serializer for complex nested objects. The initial code was taken from `chetan` and was wrapped into a gem with unit-tests and a bit more convenient API. The original links are below:
7
+ - http://techblog.thescore.com/benchmarking-json-generation-in-ruby/#comment-1678429451
8
+ - https://github.com/chetan/json_serialization_benchmark/tree/api_view
9
+ - https://gist.github.com/chetan/d613e8f7d45600e1ca34
10
+
11
+
12
+
13
+ ### Why should you even care? Is (... insert your favourite ruby serializer ... ) not good enough?
14
+
15
+ - you want great performance
16
+ - you care about object allocations (less garbage to collect for the Ruby VM)
17
+ - you want **blazing** fast test suite, so that you can switch globally the serialization off and test just the shape of the resulting Hash object
18
+ -> no converting to JSON, then parsing JSON back and checking values on it, that sux!
19
+ - really small and clean codebase
20
+ - unit-tested and with test 100% coverage
21
+
22
+ ApiView gives you all that and stays very small doing that.
23
+
24
+ ## Installation
25
+
26
+ ## Add this line to your application's Gemfile:
27
+ gem 'api_view'
28
+
29
+
30
+ ## And then execute:
31
+ $ bundle
32
+
33
+
34
+ ## Usage
35
+
36
+ - you inherit from ApiView::Base
37
+ - you say, what model should be serialized by default with this serializer (optional)
38
+ - you specify an array of attributes, that will be copied from the object in serializer
39
+ - you tell how you main object is called (defaults to `object` / `obj`)
40
+ - you implement `instance_convert`-method for further customization of the serialization
41
+ -> `field` - a setter method, that also accepts `via: SomeSerializerApiView`
42
+
43
+
44
+ class EventApiView < EventSummaryApiView
45
+ # default serializer for BoxScore, will be picked, if none other was given
46
+ for_model ::Event
47
+
48
+ # the attributes to copy from the object
49
+ attributes :share_url, :sport_name
50
+
51
+ # the name of your main object, optional
52
+ main_object :event
53
+
54
+ # the method to add additional logic + fields
55
+ def instance_convert
56
+ # just a setter method with optional serializer for that sub-object
57
+ field :box_score, event.box_score, via: BasketballBoxScoreApiView
58
+ end
59
+ end
60
+
61
+
62
+ For more examples take a look into the `example/`-folder and run the benchmark script via `ruby example/benchmark.rb`.
63
+
64
+
65
+
66
+ ## Developement
67
+
68
+ # run tests
69
+ $ sh/test
70
+
71
+
72
+
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it ( https://github.com/[my-github-username]/api_view/fork )
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create a new Pull Request
81
+
82
+
83
+
84
+ ## Benchmark numbers (ApiView vs the rest of the pack)
85
+
86
+ user system total real allocations memsize
87
+ RABL Ultra Simple 4.860000 0.620000 5.480000 ( 5.493406) 664 25787
88
+ AMS Ultra Simple 0.220000 0.000000 0.220000 ( 0.220079) 26 650
89
+ Presenters Ultra Simple 0.140000 0.000000 0.140000 ( 0.152729) 24 650
90
+ ApiView Ultra Simple 0.190000 0.000000 0.190000 ( 0.193124) 12 842
91
+ -------------------------------------------------------------------------------------------------------------------
92
+ RABL Simple 21.470000 3.330000 24.800000 ( 25.147988) 2265 114051
93
+ AMS Simple 1.060000 0.000000 1.060000 ( 1.066668) 105 2726
94
+ Presenters Simple 0.610000 0.000000 0.610000 ( 0.611980) 98 2918
95
+ ApiView Simple 0.280000 0.010000 0.290000 ( 0.292290) 17 2246
96
+ -------------------------------------------------------------------------------------------------------------------
97
+ RABL Complex 43.930000 6.850000 50.780000 ( 51.574975) 4325 248000
98
+ AMS Complex 2.150000 0.000000 2.150000 ( 2.160445) 209 5851
99
+ Presenters Complex 1.210000 0.010000 1.220000 ( 1.220806) 201 7395
100
+ ApiView Complex 0.270000 0.000000 0.270000 ( 0.270517) 21 1504
101
+
102
+
103
+ Collection tests:
104
+
105
+ user system total real allocations memsize
106
+ RABL Ultra Simple: Collection 3.560000 0.600000 4.160000 ( 4.182852) 43102 1977224
107
+ AMS Ultra Simple: Collection 0.120000 0.000000 0.120000 ( 0.124631) 1914 47786
108
+ Presenters Ultra Simple: Collection 0.100000 0.010000 0.110000 ( 0.109781) 3508 67594
109
+ ApiView Ultra Simple: Collection 0.050000 0.000000 0.050000 ( 0.050875) 311 46986
110
+ -------------------------------------------------------------------------------------------------------------------
111
+ RABL Simple: Collection 18.720000 3.150000 21.870000 ( 21.924020) 202905 11255130
112
+ AMS Simple: Collection 0.870000 0.010000 0.880000 ( 0.890479) 9714 236186
113
+ Presenters Simple: Collection 0.540000 0.000000 0.540000 ( 0.542100) 16108 380794
114
+ ApiView Simple: Collection 0.160000 0.000000 0.160000 ( 0.166484) 812 187386
115
+ -------------------------------------------------------------------------------------------------------------------
116
+ RABL Complex: Collection 41.190000 6.680000 47.870000 ( 48.438854) 408015 25251570
117
+ AMS Complex: Collection 2.170000 0.030000 2.200000 ( 2.211721) 20114 548686
118
+ Presenters Complex: Collection 1.380000 0.010000 1.390000 ( 1.389608) 34408 960494
119
+ ApiView Complex: Collection 0.150000 0.000000 0.150000 ( 0.145595) 1212 113186
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'api_view/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "api_view"
8
+ spec.version = ApiView::VERSION
9
+ spec.authors = ["Roman Heinrich"]
10
+ spec.email = ["roman.heinrich@gmail.com"]
11
+ spec.summary = %q{A fast and nimble object serializer}
12
+ spec.description = %q{A fast and nimble object serializer}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "require_pattern"
24
+ spec.add_development_dependency "minitest", '~> 5.4.3'
25
+ spec.add_development_dependency "mocha"
26
+ spec.add_development_dependency "minitest-reporters"
27
+ spec.add_development_dependency "oj"
28
+ spec.add_development_dependency "multi_json"
29
+ spec.add_development_dependency "ffaker"
30
+ spec.add_development_dependency "pry"
31
+ spec.add_development_dependency "ruby-prof"
32
+ spec.add_development_dependency "allocation_stats"
33
+ spec.add_development_dependency "bixby-bench"
34
+ spec.add_development_dependency "coco"
35
+
36
+ end
@@ -0,0 +1,13 @@
1
+
2
+ Object tests:
3
+ user system total real allocations memsize
4
+ ApiView Ultra Simple 0.180000 0.000000 0.180000 ( 0.184020) 13 648
5
+ ApiView Simple 0.310000 0.010000 0.320000 ( 0.318673) 17 2251
6
+ ApiView Complex 0.350000 0.000000 0.350000 ( 0.352970) 17 1501
7
+
8
+
9
+ Collection tests:
10
+ user system total real allocations memsize
11
+ ApiView Ultra Simple: Collection 0.030000 0.000000 0.030000 ( 0.028780) 113 46882
12
+ ApiView Simple: Collection 0.140000 0.010000 0.150000 ( 0.144577) 712 187886
13
+ ApiView Complex: Collection 0.140000 0.000000 0.140000 ( 0.140050) 712 112886
@@ -0,0 +1,43 @@
1
+ require './example/require_models'
2
+ # require 'ruby-prof'
3
+ # require 'allocation_stats'
4
+ require 'bixby/bench'
5
+
6
+ module SerializationBenchmark
7
+ collection_size = 100
8
+ event = EventFactory.build_event
9
+ team = event.home_team
10
+
11
+ event_collection = collection_size.times.map { event }
12
+ team_collection = collection_size.times.map { EventFactory.home_team }
13
+
14
+ puts "\nObject tests:\n"
15
+ Bixby::Bench.run(10_000) do |b|
16
+ b.sample('ApiView Ultra Simple') do
17
+ ApiView::Engine.render(team)
18
+ end
19
+
20
+ b.sample('ApiView Simple') do
21
+ EventSummaryApiView.render(event)
22
+ end
23
+
24
+ b.sample('ApiView Complex') do
25
+ BasketballEventApiView.render(event)
26
+ end
27
+ end
28
+
29
+ puts "\n\nCollection tests:\n"
30
+ Bixby::Bench.run(100) do |b|
31
+ b.sample('ApiView Ultra Simple: Collection') do
32
+ ApiView::Engine.render(team_collection)
33
+ end
34
+
35
+ b.sample('ApiView Simple: Collection') do
36
+ EventSummaryApiView.render(event_collection)
37
+ end
38
+
39
+ b.sample('ApiView Complex: Collection') do
40
+ BasketballEventApiView.render(event_collection)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ class BoxScore < Model
2
+ attr_reader :attendance,
3
+ :has_statistics,
4
+ :last_play,
5
+ :progress,
6
+ :referees
7
+ end
@@ -0,0 +1,20 @@
1
+ class Event < Model
2
+ attr_reader :away_ranking,
3
+ :away_region,
4
+ :away_team,
5
+ :box_score,
6
+ :game_date,
7
+ :game_type,
8
+ :home_ranking,
9
+ :home_region,
10
+ :home_team,
11
+ :important,
12
+ :location,
13
+ :share_url,
14
+ :sport_name,
15
+ :status
16
+
17
+ def ncaa?
18
+ true
19
+ end
20
+ end
@@ -0,0 +1,61 @@
1
+ require 'ffaker'
2
+ class EventFactory
3
+ def self.build_event
4
+ Event.new(
5
+ away_team: away_team,
6
+ box_score: box_score,
7
+ home_team: home_team,
8
+ away_ranking: 10,
9
+ away_region: 'Pac-12',
10
+ game_date: Date.today,
11
+ game_type: 'Regular Season',
12
+ home_ranking: 15,
13
+ home_region: 'Top 25',
14
+ important: true,
15
+ location: 'Washington, DC',
16
+ share_url: 'http://thesco.re/123',
17
+ sport_name: 'basketball',
18
+ status: 'Final'
19
+ )
20
+ end
21
+
22
+ def self.last_play
23
+ PlayByPlayRecord.new(
24
+ points_type: 'Field Goal',
25
+ player_fouls: 10,
26
+ player_score: 15,
27
+ record_type: 'Postseason',
28
+ seconds: 100
29
+ )
30
+ end
31
+
32
+ def self.box_score
33
+ BoxScore.new(
34
+ last_play: last_play,
35
+ attendance: '21,307',
36
+ has_statistics: true,
37
+ progress: '11:23 2nd',
38
+ referees: 'Thuva, Nate, Roel'
39
+ )
40
+ end
41
+
42
+ def self.away_team
43
+ Team.new(
44
+ abbreviation: 'MIA',
45
+ full_name: Faker::Name.name,
46
+ location: Faker::AddressUS.state,
47
+ meidum_name: 'Miami',
48
+ short_name: 'Heats'
49
+ )
50
+ end
51
+
52
+ def self.home_team
53
+ Team.new(
54
+ abbreviation: 'TOR',
55
+ full_name: Faker::Name.name,
56
+ location: Faker::AddressUS.state,
57
+ medium_name: Faker::AddressUS.state,
58
+ short_name: 'Raptors'
59
+ )
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ class Model
2
+ def initialize(attributes={})
3
+ attributes.each do |attribute, value|
4
+ instance_variable_set("@#{attribute}", value)
5
+ end
6
+ end
7
+
8
+ def read_attribute_for_serialization(attribute)
9
+ send(attribute)
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ class PlayByPlayRecord < Model
2
+ attr_reader :points_type,
3
+ :player_fouls,
4
+ :player_score,
5
+ :record_type,
6
+ :seconds
7
+ end
@@ -0,0 +1,7 @@
1
+ class Team < Model
2
+ attr_reader :abbreviation,
3
+ :full_name,
4
+ :location,
5
+ :medium_name,
6
+ :short_name
7
+ end
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler.setup
3
+ require 'benchmark'
4
+ require 'api_view'
5
+
6
+ require 'multi_json'
7
+ require 'oj'
8
+ require 'pry'
9
+ Oj.mimic_JSON() # this will speedup benchmarks using #to_json
10
+
11
+
12
+ require 'require_pattern'
13
+ require_relative_pattern 'models/**/**.rb'
14
+ require_relative_pattern 'views/**/**.rb'
15
+
@@ -0,0 +1,11 @@
1
+ class BasketballBoxScoreApiView < BoxScoreApiView
2
+
3
+ attributes :attendance, :referees
4
+ main_object :box_score
5
+
6
+
7
+ def instance_convert
8
+ field :last_play, box_score.last_play, via: BasketballPlayByPlayRecordApiView
9
+ end
10
+
11
+ end