active_model_serializers 0.10.0 → 0.10.13
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +239 -2
- data/README.md +171 -34
- data/lib/action_controller/serialization.rb +23 -3
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +4 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +10 -5
- data/lib/active_model/serializer/association.rb +64 -10
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
- data/lib/active_model/serializer/collection_serializer.rb +48 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +89 -117
- data/lib/active_model/serializer/error_serializer.rb +13 -7
- data/lib/active_model/serializer/errors_serializer.rb +27 -20
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +3 -1
- data/lib/active_model/serializer/has_many_reflection.rb +5 -3
- data/lib/active_model/serializer/has_one_reflection.rb +3 -4
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +136 -130
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +130 -65
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model/serializer.rb +321 -86
- data/lib/active_model_serializers/adapter/attributes.rb +17 -57
- data/lib/active_model_serializers/adapter/base.rb +41 -39
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +52 -20
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
- data/lib/active_model_serializers/adapter/json_api.rb +84 -65
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/adapter.rb +9 -1
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +3 -2
- data/lib/active_model_serializers/deserialization.rb +4 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model/caching.rb +26 -0
- data/lib/active_model_serializers/model.rb +111 -28
- data/lib/active_model_serializers/railtie.rb +7 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
- data/lib/active_model_serializers/serializable_resource.rb +10 -7
- data/lib/active_model_serializers/serialization_context.rb +12 -3
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers.rb +35 -10
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +6 -4
- data/lib/grape/active_model_serializers.rb +9 -5
- data/lib/grape/formatters/active_model_serializers.rb +21 -2
- data/lib/grape/helpers/active_model_serializers.rb +3 -0
- data/lib/tasks/rubocop.rake +55 -0
- metadata +104 -296
- data/.github/ISSUE_TEMPLATE.md +0 -29
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
- data/.gitignore +0 -35
- data/.rubocop.yml +0 -104
- data/.rubocop_todo.yml +0 -167
- data/.simplecov +0 -110
- data/.travis.yml +0 -43
- data/CONTRIBUTING.md +0 -105
- data/Gemfile +0 -53
- data/Rakefile +0 -103
- data/active_model_serializers.gemspec +0 -66
- data/appveyor.yml +0 -24
- data/bin/bench +0 -171
- data/bin/bench_regression +0 -316
- data/bin/serve_benchmark +0 -39
- data/docs/ARCHITECTURE.md +0 -126
- data/docs/README.md +0 -40
- data/docs/STYLE.md +0 -58
- data/docs/general/adapters.md +0 -245
- data/docs/general/caching.md +0 -52
- data/docs/general/configuration_options.md +0 -100
- data/docs/general/deserialization.md +0 -100
- data/docs/general/getting_started.md +0 -133
- data/docs/general/instrumentation.md +0 -40
- data/docs/general/key_transforms.md +0 -40
- data/docs/general/logging.md +0 -14
- data/docs/general/rendering.md +0 -255
- data/docs/general/serializers.md +0 -372
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +0 -139
- data/docs/howto/add_root_key.md +0 -51
- data/docs/howto/outside_controller_use.md +0 -58
- data/docs/howto/passing_arbitrary_options.md +0 -27
- data/docs/howto/serialize_poro.md +0 -32
- data/docs/howto/test.md +0 -152
- data/docs/integrations/ember-and-json-api.md +0 -112
- data/docs/integrations/grape.md +0 -19
- data/docs/jsonapi/errors.md +0 -56
- data/docs/jsonapi/schema/schema.json +0 -366
- data/docs/jsonapi/schema.md +0 -151
- data/docs/rfcs/0000-namespace.md +0 -106
- data/docs/rfcs/template.md +0 -15
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/action_controller/adapter_selector_test.rb +0 -53
- data/test/action_controller/explicit_serializer_test.rb +0 -134
- data/test/action_controller/json/include_test.rb +0 -167
- data/test/action_controller/json_api/deserialization_test.rb +0 -112
- data/test/action_controller/json_api/errors_test.rb +0 -41
- data/test/action_controller/json_api/linked_test.rb +0 -197
- data/test/action_controller/json_api/pagination_test.rb +0 -116
- data/test/action_controller/json_api/transform_test.rb +0 -181
- data/test/action_controller/serialization_scope_name_test.rb +0 -229
- data/test/action_controller/serialization_test.rb +0 -469
- data/test/active_model_serializers/adapter_for_test.rb +0 -208
- data/test/active_model_serializers/json_pointer_test.rb +0 -20
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/active_model_serializers/logging_test.rb +0 -77
- data/test/active_model_serializers/model_test.rb +0 -9
- data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
- data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -58
- data/test/active_model_serializers/test/schema_test.rb +0 -130
- data/test/active_model_serializers/test/serializer_test.rb +0 -62
- data/test/active_record_test.rb +0 -9
- data/test/adapter/deprecation_test.rb +0 -100
- data/test/adapter/json/belongs_to_test.rb +0 -45
- data/test/adapter/json/collection_test.rb +0 -90
- data/test/adapter/json/has_many_test.rb +0 -45
- data/test/adapter/json/transform_test.rb +0 -93
- data/test/adapter/json_api/belongs_to_test.rb +0 -155
- data/test/adapter/json_api/collection_test.rb +0 -95
- data/test/adapter/json_api/errors_test.rb +0 -78
- data/test/adapter/json_api/fields_test.rb +0 -87
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
- data/test/adapter/json_api/has_many_test.rb +0 -144
- data/test/adapter/json_api/has_one_test.rb +0 -80
- data/test/adapter/json_api/json_api_test.rb +0 -35
- data/test/adapter/json_api/linked_test.rb +0 -392
- data/test/adapter/json_api/links_test.rb +0 -93
- data/test/adapter/json_api/pagination_links_test.rb +0 -166
- data/test/adapter/json_api/parse_test.rb +0 -137
- data/test/adapter/json_api/relationship_test.rb +0 -161
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- data/test/adapter/json_api/resource_meta_test.rb +0 -100
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
- data/test/adapter/json_api/transform_test.rb +0 -502
- data/test/adapter/json_api/type_test.rb +0 -61
- data/test/adapter/json_test.rb +0 -45
- data/test/adapter/null_test.rb +0 -23
- data/test/adapter/polymorphic_test.rb +0 -171
- data/test/adapter_test.rb +0 -67
- data/test/array_serializer_test.rb +0 -22
- data/test/benchmark/app.rb +0 -65
- data/test/benchmark/benchmarking_support.rb +0 -67
- data/test/benchmark/bm_caching.rb +0 -119
- data/test/benchmark/bm_transform.rb +0 -34
- data/test/benchmark/config.ru +0 -3
- data/test/benchmark/controllers.rb +0 -84
- data/test/benchmark/fixtures.rb +0 -219
- data/test/cache_test.rb +0 -485
- data/test/collection_serializer_test.rb +0 -110
- data/test/fixtures/active_record.rb +0 -78
- data/test/fixtures/poro.rb +0 -282
- data/test/generators/scaffold_controller_generator_test.rb +0 -24
- data/test/generators/serializer_generator_test.rb +0 -57
- data/test/grape_test.rb +0 -82
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
- data/test/lint_test.rb +0 -49
- data/test/logger_test.rb +0 -18
- data/test/poro_test.rb +0 -9
- data/test/serializable_resource_test.rb +0 -83
- data/test/serializers/association_macros_test.rb +0 -36
- data/test/serializers/associations_test.rb +0 -295
- data/test/serializers/attribute_test.rb +0 -151
- data/test/serializers/attributes_test.rb +0 -52
- data/test/serializers/caching_configuration_test_isolated.rb +0 -170
- data/test/serializers/configuration_test.rb +0 -32
- data/test/serializers/fieldset_test.rb +0 -14
- data/test/serializers/meta_test.rb +0 -196
- data/test/serializers/options_test.rb +0 -21
- data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
- data/test/serializers/root_test.rb +0 -21
- data/test/serializers/serialization_test.rb +0 -55
- data/test/serializers/serializer_for_test.rb +0 -134
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/isolated_unit.rb +0 -79
- data/test/support/rails5_shims.rb +0 -47
- data/test/support/rails_app.rb +0 -45
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
- data/test/support/schemas/custom/show.json +0 -7
- data/test/support/schemas/hyper_schema.json +0 -93
- data/test/support/schemas/render_using_json_api.json +0 -43
- data/test/support/schemas/simple_json_pointers.json +0 -10
- data/test/support/serialization_testing.rb +0 -53
- data/test/test_helper.rb +0 -57
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require 'active_model/serializer/version'
|
|
5
|
-
|
|
6
|
-
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name = 'active_model_serializers'
|
|
8
|
-
spec.version = ActiveModel::Serializer::VERSION
|
|
9
|
-
spec.platform = Gem::Platform::RUBY
|
|
10
|
-
spec.authors = ['Steve Klabnik']
|
|
11
|
-
spec.email = ['steve@steveklabnik.com']
|
|
12
|
-
spec.summary = 'Conventions-based JSON generation for Rails.'
|
|
13
|
-
spec.description = 'ActiveModel::Serializers allows you to generate your JSON in an object-oriented and convention-driven manner.'
|
|
14
|
-
spec.homepage = 'https://github.com/rails-api/active_model_serializers'
|
|
15
|
-
spec.license = 'MIT'
|
|
16
|
-
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0")
|
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
-
spec.require_paths = ['lib']
|
|
20
|
-
spec.executables = []
|
|
21
|
-
|
|
22
|
-
spec.required_ruby_version = '>= 2.0.0'
|
|
23
|
-
|
|
24
|
-
rails_versions = '>= 4.0'
|
|
25
|
-
spec.add_runtime_dependency 'activemodel', rails_versions
|
|
26
|
-
# 'activesupport', rails_versions
|
|
27
|
-
# 'builder'
|
|
28
|
-
|
|
29
|
-
spec.add_runtime_dependency 'actionpack', rails_versions
|
|
30
|
-
# 'activesupport', rails_versions
|
|
31
|
-
# 'rack'
|
|
32
|
-
# 'rack-test', '~> 0.6.2'
|
|
33
|
-
|
|
34
|
-
spec.add_runtime_dependency 'railties', rails_versions
|
|
35
|
-
# 'activesupport', rails_versions
|
|
36
|
-
# 'actionpack', rails_versions
|
|
37
|
-
# 'rake', '>= 0.8.7'
|
|
38
|
-
|
|
39
|
-
# 'activesupport', rails_versions
|
|
40
|
-
# 'i18n,
|
|
41
|
-
# 'tzinfo'
|
|
42
|
-
# 'minitest'
|
|
43
|
-
# 'thread_safe'
|
|
44
|
-
|
|
45
|
-
spec.add_development_dependency 'activerecord', rails_versions
|
|
46
|
-
# arel
|
|
47
|
-
# activesupport
|
|
48
|
-
# activemodel
|
|
49
|
-
|
|
50
|
-
# Soft dependency for pagination
|
|
51
|
-
spec.add_development_dependency 'kaminari', ' ~> 0.16.3'
|
|
52
|
-
spec.add_development_dependency 'will_paginate', '~> 3.0', '>= 3.0.7'
|
|
53
|
-
|
|
54
|
-
spec.add_development_dependency 'bundler', '~> 1.6'
|
|
55
|
-
spec.add_development_dependency 'simplecov', '~> 0.11'
|
|
56
|
-
spec.add_development_dependency 'timecop', '~> 0.7'
|
|
57
|
-
spec.add_development_dependency 'grape', ['>= 0.13', '< 1.0']
|
|
58
|
-
spec.add_development_dependency 'json_schema'
|
|
59
|
-
spec.add_development_dependency 'rake', ['>= 10.0', '< 12.0']
|
|
60
|
-
|
|
61
|
-
spec.post_install_message = <<-EOF
|
|
62
|
-
NOTE: The default key case for the JsonApi adapter has changed to dashed.
|
|
63
|
-
See https://github.com/rails-api/active_model_serializers/blob/master/docs/general/key_transforms.md
|
|
64
|
-
for more information on configuring this behavior.
|
|
65
|
-
EOF
|
|
66
|
-
end
|
data/appveyor.yml
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
version: '{build}'
|
|
2
|
-
|
|
3
|
-
skip_tags: true
|
|
4
|
-
|
|
5
|
-
environment:
|
|
6
|
-
JRUBY_OPTS: "--dev -J-Xmx1024M --debug"
|
|
7
|
-
matrix:
|
|
8
|
-
- ruby_version: "Ruby21"
|
|
9
|
-
- ruby_version: "Ruby21-x64"
|
|
10
|
-
- ruby_version: "jruby-9.0.0.0"
|
|
11
|
-
|
|
12
|
-
cache:
|
|
13
|
-
- vendor/bundle
|
|
14
|
-
|
|
15
|
-
install:
|
|
16
|
-
- SET PATH=C:\%ruby_version%\bin;%PATH%
|
|
17
|
-
- gem install bundler
|
|
18
|
-
- bundle env
|
|
19
|
-
- bundle install --path=vendor/bundle --retry=3 --jobs=3
|
|
20
|
-
|
|
21
|
-
test_script:
|
|
22
|
-
- bundle exec rake ci
|
|
23
|
-
|
|
24
|
-
build: off
|
data/bin/bench
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# ActiveModelSerializers Benchmark driver
|
|
3
|
-
# Adapted from
|
|
4
|
-
# https://github.com/ruby-bench/ruby-bench-suite/blob/8ad567f7e43a044ae48c36833218423bb1e2bd9d/rails/benchmarks/driver.rb
|
|
5
|
-
require 'bundler'
|
|
6
|
-
Bundler.setup
|
|
7
|
-
require 'json'
|
|
8
|
-
require 'pathname'
|
|
9
|
-
require 'optparse'
|
|
10
|
-
require 'digest'
|
|
11
|
-
require 'pathname'
|
|
12
|
-
require 'shellwords'
|
|
13
|
-
require 'logger'
|
|
14
|
-
require 'English'
|
|
15
|
-
|
|
16
|
-
class BenchmarkDriver
|
|
17
|
-
ROOT = Pathname File.expand_path(File.join('..', '..'), __FILE__)
|
|
18
|
-
BASE = ENV.fetch('BASE') { ROOT.join('test', 'benchmark') }
|
|
19
|
-
ESCAPED_BASE = Shellwords.shellescape(BASE)
|
|
20
|
-
|
|
21
|
-
def self.benchmark(options)
|
|
22
|
-
new(options).run
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.parse_argv_and_run(argv = ARGV, options = {})
|
|
26
|
-
options = {
|
|
27
|
-
repeat_count: 1,
|
|
28
|
-
pattern: [],
|
|
29
|
-
env: 'CACHE_ON=on'
|
|
30
|
-
}.merge!(options)
|
|
31
|
-
|
|
32
|
-
OptionParser.new do |opts|
|
|
33
|
-
opts.banner = 'Usage: bin/bench [options]'
|
|
34
|
-
|
|
35
|
-
opts.on('-r', '--repeat-count [NUM]', 'Run benchmarks [NUM] times taking the best result') do |value|
|
|
36
|
-
options[:repeat_count] = value.to_i
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
opts.on('-p', '--pattern <PATTERN1,PATTERN2,PATTERN3>', 'Benchmark name pattern') do |value|
|
|
40
|
-
options[:pattern] = value.split(',')
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
opts.on('-e', '--env <var1=val1,var2=val2,var3=vale>', 'ENV variables to pass in') do |value|
|
|
44
|
-
options[:env] = value.split(',')
|
|
45
|
-
end
|
|
46
|
-
end.parse!(argv)
|
|
47
|
-
|
|
48
|
-
benchmark(options)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
attr_reader :commit_hash, :base
|
|
52
|
-
|
|
53
|
-
# Based on logfmt:
|
|
54
|
-
# https://www.brandur.org/logfmt
|
|
55
|
-
# For more complete implementation see:
|
|
56
|
-
# see https://github.com/arachnid-cb/logfmtr/blob/master/lib/logfmtr/base.rb
|
|
57
|
-
# For usage see:
|
|
58
|
-
# https://blog.codeship.com/logfmt-a-log-format-thats-easy-to-read-and-write/
|
|
59
|
-
# https://engineering.heroku.com/blogs/2014-09-05-hutils-explore-your-structured-data-logs/
|
|
60
|
-
# For Ruby parser see:
|
|
61
|
-
# https://github.com/cyberdelia/logfmt-ruby
|
|
62
|
-
def self.summary_logger(device = 'output.txt')
|
|
63
|
-
require 'time'
|
|
64
|
-
logger = Logger.new(device)
|
|
65
|
-
logger.level = Logger::INFO
|
|
66
|
-
logger.formatter = proc { |severity, datetime, progname, msg|
|
|
67
|
-
msg = "'#{msg}'"
|
|
68
|
-
"level=#{severity} time=#{datetime.utc.iso8601(6)} pid=#{Process.pid} progname=#{progname} msg=#{msg}#{$INPUT_RECORD_SEPARATOR}"
|
|
69
|
-
}
|
|
70
|
-
logger
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def self.stdout_logger
|
|
74
|
-
logger = Logger.new(STDOUT)
|
|
75
|
-
logger.level = Logger::INFO
|
|
76
|
-
logger.formatter = proc { |_, _, _, msg| "#{msg}#{$INPUT_RECORD_SEPARATOR}" }
|
|
77
|
-
logger
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def initialize(options)
|
|
81
|
-
@writer = ENV['SUMMARIZE'] ? self.class.summary_logger : self.class.stdout_logger
|
|
82
|
-
@repeat_count = options[:repeat_count]
|
|
83
|
-
@pattern = options[:pattern]
|
|
84
|
-
@commit_hash = options.fetch(:commit_hash) { `git rev-parse --short HEAD`.chomp }
|
|
85
|
-
@base = options.fetch(:base) { ESCAPED_BASE }
|
|
86
|
-
@env = Array(options[:env]).join(' ')
|
|
87
|
-
@rubyopt = options[:rubyopt] # TODO: rename
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def run
|
|
91
|
-
files.each do |path|
|
|
92
|
-
next if !@pattern.empty? && /#{@pattern.join('|')}/ !~ File.basename(path)
|
|
93
|
-
run_single(Shellwords.shellescape(path))
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
private
|
|
98
|
-
|
|
99
|
-
def files
|
|
100
|
-
Dir[File.join(base, 'bm_*')]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def run_single(path)
|
|
104
|
-
script = "RAILS_ENV=production #{@env} ruby #{@rubyopt} #{path}"
|
|
105
|
-
environment = `ruby -v`.chomp.strip[/\d+\.\d+\.\d+\w+/]
|
|
106
|
-
|
|
107
|
-
runs_output = measure(script)
|
|
108
|
-
if runs_output.empty?
|
|
109
|
-
results = { error: :no_results }
|
|
110
|
-
return
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
results = {}
|
|
114
|
-
results['commit_hash'] = commit_hash
|
|
115
|
-
results['version'] = runs_output.first['version']
|
|
116
|
-
results['rails_version'] = runs_output.first['rails_version']
|
|
117
|
-
results['benchmark_run[environment]'] = environment
|
|
118
|
-
results['runs'] = []
|
|
119
|
-
|
|
120
|
-
runs_output.each do |output|
|
|
121
|
-
results['runs'] << {
|
|
122
|
-
'benchmark_type[category]' => output['label'],
|
|
123
|
-
'benchmark_run[result][iterations_per_second]' => output['iterations_per_second'].round(3),
|
|
124
|
-
'benchmark_run[result][total_allocated_objects_per_iteration]' => output['total_allocated_objects_per_iteration']
|
|
125
|
-
}
|
|
126
|
-
end
|
|
127
|
-
ensure
|
|
128
|
-
results && report(results)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def report(results)
|
|
132
|
-
@writer.info { 'Benchmark results:' }
|
|
133
|
-
@writer.info { JSON.pretty_generate(results) }
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def summarize(result)
|
|
137
|
-
puts "#{result['label']} #{result['iterations_per_second']}/ips; #{result['total_allocated_objects_per_iteration']} objects"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# FIXME: ` provides the full output but it'll return failed output as well.
|
|
141
|
-
def measure(script)
|
|
142
|
-
results = Hash.new { |h, k| h[k] = [] }
|
|
143
|
-
|
|
144
|
-
@repeat_count.times do
|
|
145
|
-
output = sh(script)
|
|
146
|
-
output.each_line do |line|
|
|
147
|
-
next if line.nil?
|
|
148
|
-
begin
|
|
149
|
-
result = JSON.parse(line)
|
|
150
|
-
rescue JSON::ParserError
|
|
151
|
-
result = { error: line } # rubocop:disable Lint/UselessAssignment
|
|
152
|
-
else
|
|
153
|
-
summarize(result)
|
|
154
|
-
results[result['label']] << result
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
results.map do |_, bm_runs|
|
|
160
|
-
bm_runs.sort_by do |run|
|
|
161
|
-
run['iterations_per_second']
|
|
162
|
-
end.last
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def sh(cmd)
|
|
167
|
-
`#{cmd}`
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
BenchmarkDriver.parse_argv_and_run if $PROGRAM_NAME == __FILE__
|
data/bin/bench_regression
DELETED
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
require 'fileutils'
|
|
3
|
-
require 'pathname'
|
|
4
|
-
require 'shellwords'
|
|
5
|
-
require 'English'
|
|
6
|
-
|
|
7
|
-
############################
|
|
8
|
-
# USAGE
|
|
9
|
-
#
|
|
10
|
-
# bundle exec bin/bench_regression <ref1> <ref2>
|
|
11
|
-
# <ref1> defaults to the current branch
|
|
12
|
-
# <ref2> defaults to the master branch
|
|
13
|
-
# bundle exec bin/bench_regression current # will run on the current branch
|
|
14
|
-
# bundle exec bin/bench_regression revisions 792fb8a90 master # every revision inclusive
|
|
15
|
-
# bundle exec bin/bench_regression 792fb8a90 master --repeat-count 2 --env CACHE_ON=off
|
|
16
|
-
# bundle exec bin/bench_regression vendor
|
|
17
|
-
###########################
|
|
18
|
-
|
|
19
|
-
class BenchRegression
|
|
20
|
-
ROOT = Pathname File.expand_path(File.join(*['..', '..']), __FILE__)
|
|
21
|
-
TMP_DIR_NAME = File.join('tmp', 'bench')
|
|
22
|
-
TMP_DIR = File.join(ROOT, TMP_DIR_NAME)
|
|
23
|
-
E_TMP_DIR = Shellwords.shellescape(TMP_DIR)
|
|
24
|
-
load ROOT.join('bin', 'bench')
|
|
25
|
-
|
|
26
|
-
attr_reader :source_stasher
|
|
27
|
-
|
|
28
|
-
def initialize
|
|
29
|
-
@source_stasher = SourceStasher.new
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class SourceStasher
|
|
33
|
-
attr_reader :gem_require_paths, :gem_paths
|
|
34
|
-
attr_writer :vendor
|
|
35
|
-
|
|
36
|
-
def initialize
|
|
37
|
-
@gem_require_paths = []
|
|
38
|
-
@gem_paths = []
|
|
39
|
-
refresh_temp_dir
|
|
40
|
-
@vendor = false
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def temp_dir_empty?
|
|
44
|
-
File.directory?(TMP_DIR) &&
|
|
45
|
-
Dir[File.join(TMP_DIR, '*')].none?
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def empty_temp_dir
|
|
49
|
-
return if @vendor
|
|
50
|
-
return if temp_dir_empty?
|
|
51
|
-
FileUtils.mkdir_p(TMP_DIR)
|
|
52
|
-
Dir[File.join(TMP_DIR, '*')].each do |file|
|
|
53
|
-
if File.directory?(file)
|
|
54
|
-
FileUtils.rm_rf(file)
|
|
55
|
-
else
|
|
56
|
-
FileUtils.rm(file)
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def fill_temp_dir
|
|
62
|
-
vendor_files(Dir[File.join(ROOT, 'test', 'benchmark', '*.{rb,ru}')])
|
|
63
|
-
# vendor_file(File.join('bin', 'bench'))
|
|
64
|
-
housekeeping { empty_temp_dir }
|
|
65
|
-
vendor_gem('benchmark-ips')
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def vendor_files(files)
|
|
69
|
-
files.each do |file|
|
|
70
|
-
vendor_file(file)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def vendor_file(file)
|
|
75
|
-
FileUtils.cp(file, File.join(TMP_DIR, File.basename(file)))
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def vendor_gem(gem_name)
|
|
79
|
-
directory_name = `bundle exec gem unpack benchmark-ips --target=#{E_TMP_DIR}`[/benchmark-ips.+\d/]
|
|
80
|
-
gem_paths << File.join(TMP_DIR, directory_name)
|
|
81
|
-
gem_require_paths << File.join(TMP_DIR_NAME, directory_name, 'lib')
|
|
82
|
-
housekeeping { remove_vendored_gems }
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def remove_vendored_gems
|
|
86
|
-
return if @vendor
|
|
87
|
-
FileUtils.rm_rf(*gem_paths)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def refresh_temp_dir
|
|
91
|
-
empty_temp_dir
|
|
92
|
-
fill_temp_dir
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def housekeeping
|
|
96
|
-
at_exit { yield }
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
module RevisionMethods
|
|
101
|
-
module_function
|
|
102
|
-
def current_branch
|
|
103
|
-
@current_branch ||= `cat .git/HEAD | cut -d/ -f3,4,5`.chomp
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def current_revision
|
|
107
|
-
`git rev-parse --short HEAD`.chomp
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def revision_description(rev)
|
|
111
|
-
`git log --oneline -1 #{rev}`.chomp
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def revisions(start_ref, end_ref)
|
|
115
|
-
cmd = "git rev-list --reverse #{start_ref}..#{end_ref}"
|
|
116
|
-
`#{cmd}`.chomp.split("\n")
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def checkout_ref(ref)
|
|
120
|
-
`git checkout #{ref}`.chomp
|
|
121
|
-
if $CHILD_STATUS
|
|
122
|
-
STDERR.puts "Checkout failed: #{ref}, #{$CHILD_STATUS.exitstatus}" unless $CHILD_STATUS.success?
|
|
123
|
-
$CHILD_STATUS.success?
|
|
124
|
-
else
|
|
125
|
-
true
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def clean_head
|
|
130
|
-
system('git reset --hard --quiet')
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
module ShellMethods
|
|
134
|
-
|
|
135
|
-
def sh(cmd)
|
|
136
|
-
puts cmd
|
|
137
|
-
# system(cmd)
|
|
138
|
-
run(cmd)
|
|
139
|
-
# env = {}
|
|
140
|
-
# # out = STDOUT
|
|
141
|
-
# pid = spawn(env, cmd)
|
|
142
|
-
# Process.wait(pid)
|
|
143
|
-
# pid = fork do
|
|
144
|
-
# exec cmd
|
|
145
|
-
# end
|
|
146
|
-
# Process.waitpid2(pid)
|
|
147
|
-
# puts $CHILD_STATUS.exitstatus
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
require 'pty'
|
|
151
|
-
# should consider trapping SIGINT in here
|
|
152
|
-
def run(cmd)
|
|
153
|
-
puts cmd
|
|
154
|
-
child_process = ''
|
|
155
|
-
result = ''
|
|
156
|
-
# http://stackoverflow.com/a/1162850
|
|
157
|
-
# stream output of subprocess
|
|
158
|
-
begin
|
|
159
|
-
PTY.spawn(cmd) do |stdin, _stdout, pid|
|
|
160
|
-
begin
|
|
161
|
-
# Do stuff with the output here. Just printing to show it works
|
|
162
|
-
stdin.each do |line|
|
|
163
|
-
print line
|
|
164
|
-
result << line
|
|
165
|
-
end
|
|
166
|
-
child_process = PTY.check(pid)
|
|
167
|
-
rescue Errno::EIO
|
|
168
|
-
puts 'Errno:EIO error, but this probably just means ' \
|
|
169
|
-
'that the process has finished giving output'
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
rescue PTY::ChildExited
|
|
173
|
-
puts 'The child process exited!'
|
|
174
|
-
end
|
|
175
|
-
unless (child_process && child_process.success?)
|
|
176
|
-
exitstatus = child_process.exitstatus
|
|
177
|
-
puts "FAILED: #{child_process.pid} exited with status #{exitstatus.inspect} due to failed command #{cmd}"
|
|
178
|
-
exit exitstatus || 1
|
|
179
|
-
end
|
|
180
|
-
result
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def bundle(ref)
|
|
184
|
-
system("rm -f Gemfile.lock")
|
|
185
|
-
# This is absolutely critical for bundling to work
|
|
186
|
-
Bundler.with_clean_env do
|
|
187
|
-
system("bundle check ||
|
|
188
|
-
bundle install --local ||
|
|
189
|
-
bundle install ||
|
|
190
|
-
bundle update")
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
# if $CHILD_STATUS
|
|
194
|
-
# STDERR.puts "Bundle failed at: #{ref}, #{$CHILD_STATUS.exitstatus}" unless $CHILD_STATUS.success?
|
|
195
|
-
# $CHILD_STATUS.success?
|
|
196
|
-
# else
|
|
197
|
-
# false
|
|
198
|
-
# end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
include ShellMethods
|
|
202
|
-
include RevisionMethods
|
|
203
|
-
|
|
204
|
-
def benchmark_refs(ref1: nil, ref2: nil, cmd:)
|
|
205
|
-
checking_out = false
|
|
206
|
-
ref0 = current_branch
|
|
207
|
-
ref1 ||= current_branch
|
|
208
|
-
ref2 ||= 'master'
|
|
209
|
-
p [ref0, ref1, ref2, current_revision]
|
|
210
|
-
|
|
211
|
-
run_benchmark_at_ref(cmd, ref1)
|
|
212
|
-
p [ref0, ref1, ref2, current_revision]
|
|
213
|
-
run_benchmark_at_ref(cmd, ref2)
|
|
214
|
-
p [ref0, ref1, ref2, current_revision]
|
|
215
|
-
|
|
216
|
-
checking_out = true
|
|
217
|
-
checkout_ref(ref0)
|
|
218
|
-
rescue Exception # rubocop:disable Lint/RescueException
|
|
219
|
-
STDERR.puts "[ERROR] #{$!.message}"
|
|
220
|
-
checkout_ref(ref0) unless checking_out
|
|
221
|
-
raise
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def benchmark_revisions(ref1: nil, ref2: nil, cmd:)
|
|
225
|
-
checking_out = false
|
|
226
|
-
ref0 = current_branch
|
|
227
|
-
ref1 ||= current_branch
|
|
228
|
-
ref2 ||= 'master'
|
|
229
|
-
|
|
230
|
-
revisions(ref1, ref2).each do |rev|
|
|
231
|
-
STDERR.puts "Checking out: #{revision_description(rev)}"
|
|
232
|
-
|
|
233
|
-
run_benchmark_at_ref(cmd, rev)
|
|
234
|
-
clean_head
|
|
235
|
-
end
|
|
236
|
-
checking_out = true
|
|
237
|
-
checkout_ref(ref0)
|
|
238
|
-
rescue Exception # rubocop:disable Lint/RescueException
|
|
239
|
-
STDERR.puts "[ERROR]: #{$!.message}"
|
|
240
|
-
checkout_ref(ref0) unless checking_out
|
|
241
|
-
raise
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
def run_benchmark_at_ref(cmd, ref)
|
|
245
|
-
checkout_ref(ref)
|
|
246
|
-
run_benchmark(cmd, ref)
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def run_benchmark(cmd, ref = nil)
|
|
250
|
-
ref ||= current_revision
|
|
251
|
-
bundle(ref) &&
|
|
252
|
-
benchmark_tests(cmd, ref)
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
def benchmark_tests(cmd, ref)
|
|
256
|
-
base = E_TMP_DIR
|
|
257
|
-
# cmd.sub('bin/bench', 'tmp/revision_runner/bench')
|
|
258
|
-
# bundle = Gem.bin('bunle'
|
|
259
|
-
# Bundler.with_clean_env(&block)
|
|
260
|
-
|
|
261
|
-
# cmd = Shellwords.shelljoin(cmd)
|
|
262
|
-
# cmd = "COMMIT_HASH=#{ref} BASE=#{base} bundle exec ruby -rbenchmark/ips #{cmd}"
|
|
263
|
-
# Add vendoring benchmark/ips to load path
|
|
264
|
-
|
|
265
|
-
# CURRENT THINKING: IMPORTANT
|
|
266
|
-
# Pass into require statement as RUBYOPTS i.e. via env rather than command line argument
|
|
267
|
-
# otherwise, have a 'fast ams benchmarking' module that extends benchmarkings to add the 'ams'
|
|
268
|
-
# method but doesn't depend on benchmark-ips
|
|
269
|
-
options = {
|
|
270
|
-
commit_hash: ref,
|
|
271
|
-
base: base,
|
|
272
|
-
rubyopt: Shellwords.shellescape("-Ilib:#{source_stasher.gem_require_paths.join(':')}")
|
|
273
|
-
}
|
|
274
|
-
BenchmarkDriver.parse_argv_and_run(ARGV.dup, options)
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
if $PROGRAM_NAME == __FILE__
|
|
279
|
-
benchmarking = BenchRegression.new
|
|
280
|
-
|
|
281
|
-
case ARGV[0]
|
|
282
|
-
when 'current'
|
|
283
|
-
# Run current branch only
|
|
284
|
-
|
|
285
|
-
# super simple command line parsing
|
|
286
|
-
args = ARGV.dup
|
|
287
|
-
_ = args.shift # remove 'current' from args
|
|
288
|
-
cmd = args
|
|
289
|
-
benchmarking.run_benchmark(cmd)
|
|
290
|
-
when 'revisions'
|
|
291
|
-
# Runs on every revision
|
|
292
|
-
|
|
293
|
-
# super simple command line parsing
|
|
294
|
-
args = ARGV.dup
|
|
295
|
-
_ = args.shift
|
|
296
|
-
ref1 = args.shift # remove 'revisions' from args
|
|
297
|
-
ref2 = args.shift
|
|
298
|
-
cmd = args
|
|
299
|
-
benchmarking.benchmark_revisions(ref1: ref1, ref2: ref2, cmd: cmd)
|
|
300
|
-
when 'vendor'
|
|
301
|
-
# Just prevents vendored files from being cleaned up
|
|
302
|
-
# at exit. (They are vendored at initialize.)
|
|
303
|
-
benchmarking.source_stasher.vendor = true
|
|
304
|
-
else
|
|
305
|
-
# Default: Compare current_branch to master
|
|
306
|
-
# Optionally: pass in two refs as args to `bin/bench_regression`
|
|
307
|
-
# TODO: Consider checking across more revisions, to automatically find problems.
|
|
308
|
-
|
|
309
|
-
# super simple command line parsing
|
|
310
|
-
args = ARGV.dup
|
|
311
|
-
ref1 = args.shift
|
|
312
|
-
ref2 = args.shift
|
|
313
|
-
cmd = args
|
|
314
|
-
benchmarking.benchmark_refs(ref1: ref1, ref2: ref2, cmd: cmd)
|
|
315
|
-
end
|
|
316
|
-
end
|
data/bin/serve_benchmark
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -e
|
|
3
|
-
|
|
4
|
-
case "$1" in
|
|
5
|
-
|
|
6
|
-
start)
|
|
7
|
-
config="${CONFIG_RU:-test/benchmark/config.ru}"
|
|
8
|
-
bundle exec ruby -Ilib -S rackup "$config" --daemonize --pid tmp/benchmark_app.pid --warn --server webrick
|
|
9
|
-
until [ -f 'tmp/benchmark_app.pid' ]; do
|
|
10
|
-
sleep 0.1 # give it time to start.. I don't know a better way
|
|
11
|
-
done
|
|
12
|
-
cat tmp/benchmark_app.pid
|
|
13
|
-
true
|
|
14
|
-
;;
|
|
15
|
-
|
|
16
|
-
stop)
|
|
17
|
-
if [ -f 'tmp/benchmark_app.pid' ]; then
|
|
18
|
-
kill -TERM $(cat tmp/benchmark_app.pid)
|
|
19
|
-
else
|
|
20
|
-
echo 'No pidfile'
|
|
21
|
-
false
|
|
22
|
-
fi
|
|
23
|
-
;;
|
|
24
|
-
|
|
25
|
-
status)
|
|
26
|
-
if [ -f 'tmp/benchmark_app.pid' ]; then
|
|
27
|
-
kill -0 $(cat tmp/benchmark_app.pid)
|
|
28
|
-
[ "$?" -eq 0 ]
|
|
29
|
-
else
|
|
30
|
-
echo 'No pidfile'
|
|
31
|
-
false
|
|
32
|
-
fi
|
|
33
|
-
;;
|
|
34
|
-
|
|
35
|
-
*)
|
|
36
|
-
echo "Usage: $0 [start|stop|status]"
|
|
37
|
-
;;
|
|
38
|
-
|
|
39
|
-
esac
|