active_model_serializers 0.9.12 → 0.10.15

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.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +638 -82
  3. data/MIT-LICENSE +3 -2
  4. data/README.md +194 -846
  5. data/lib/action_controller/serialization.rb +34 -74
  6. data/lib/active_model/serializable_resource.rb +13 -0
  7. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  8. data/lib/active_model/serializer/adapter/base.rb +20 -0
  9. data/lib/active_model/serializer/adapter/json.rb +17 -0
  10. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  11. data/lib/active_model/serializer/adapter/null.rb +17 -0
  12. data/lib/active_model/serializer/adapter.rb +26 -0
  13. data/lib/active_model/serializer/array_serializer.rb +14 -0
  14. data/lib/active_model/serializer/association.rb +53 -38
  15. data/lib/active_model/serializer/attribute.rb +27 -0
  16. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  17. data/lib/active_model/serializer/collection_serializer.rb +99 -0
  18. data/lib/active_model/serializer/concerns/caching.rb +305 -0
  19. data/lib/active_model/serializer/error_serializer.rb +16 -0
  20. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  21. data/lib/active_model/serializer/field.rb +92 -0
  22. data/lib/active_model/serializer/fieldset.rb +33 -0
  23. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  24. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  25. data/lib/active_model/serializer/lazy_association.rb +99 -0
  26. data/lib/active_model/serializer/link.rb +23 -0
  27. data/lib/active_model/serializer/lint.rb +152 -0
  28. data/lib/active_model/serializer/null.rb +19 -0
  29. data/lib/active_model/serializer/reflection.rb +212 -0
  30. data/lib/active_model/serializer/version.rb +1 -1
  31. data/lib/active_model/serializer.rb +361 -263
  32. data/lib/active_model_serializers/adapter/attributes.rb +36 -0
  33. data/lib/active_model_serializers/adapter/base.rb +85 -0
  34. data/lib/active_model_serializers/adapter/json.rb +23 -0
  35. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  36. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  37. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  38. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  39. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  40. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +94 -0
  41. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  42. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  43. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  44. data/lib/active_model_serializers/adapter/null.rb +11 -0
  45. data/lib/active_model_serializers/adapter.rb +100 -0
  46. data/lib/active_model_serializers/callbacks.rb +57 -0
  47. data/lib/active_model_serializers/deprecate.rb +56 -0
  48. data/lib/active_model_serializers/deserialization.rb +17 -0
  49. data/lib/active_model_serializers/json_pointer.rb +16 -0
  50. data/lib/active_model_serializers/logging.rb +124 -0
  51. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  52. data/lib/active_model_serializers/model.rb +132 -0
  53. data/lib/active_model_serializers/railtie.rb +62 -0
  54. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  55. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  56. data/lib/active_model_serializers/serialization_context.rb +41 -0
  57. data/lib/active_model_serializers/test/schema.rb +140 -0
  58. data/lib/active_model_serializers/test/serializer.rb +127 -0
  59. data/lib/active_model_serializers/test.rb +9 -0
  60. data/lib/active_model_serializers.rb +58 -27
  61. data/lib/generators/rails/USAGE +6 -0
  62. data/lib/{active_model/serializer/generators → generators/rails}/resource_override.rb +1 -4
  63. data/lib/{active_model/serializer/generators/serializer → generators/rails}/serializer_generator.rb +4 -5
  64. data/lib/grape/active_model_serializers.rb +18 -0
  65. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  66. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  67. data/lib/tasks/rubocop.rake +60 -0
  68. metadata +248 -155
  69. data/CONTRIBUTING.md +0 -20
  70. data/DESIGN.textile +0 -586
  71. data/lib/action_controller/serialization_test_case.rb +0 -82
  72. data/lib/active_model/array_serializer.rb +0 -70
  73. data/lib/active_model/default_serializer.rb +0 -30
  74. data/lib/active_model/serializable/utils.rb +0 -18
  75. data/lib/active_model/serializable.rb +0 -61
  76. data/lib/active_model/serializer/association/has_many.rb +0 -41
  77. data/lib/active_model/serializer/association/has_one.rb +0 -27
  78. data/lib/active_model/serializer/config.rb +0 -33
  79. data/lib/active_model/serializer/generators/serializer/USAGE +0 -9
  80. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +0 -16
  81. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +0 -93
  82. data/lib/active_model/serializer/railtie.rb +0 -24
  83. data/lib/active_model/serializer_support.rb +0 -7
  84. data/test/benchmark/app.rb +0 -60
  85. data/test/benchmark/benchmarking_support.rb +0 -67
  86. data/test/benchmark/bm_active_record.rb +0 -41
  87. data/test/benchmark/setup.rb +0 -75
  88. data/test/benchmark/tmp/miniprofiler/mp_timers_6eqewtfgrhitvq5gqm25 +0 -0
  89. data/test/benchmark/tmp/miniprofiler/mp_timers_8083sx03hu72pxz1a4d0 +0 -0
  90. data/test/benchmark/tmp/miniprofiler/mp_timers_fyz2gsml4z0ph9kpoy1c +0 -0
  91. data/test/benchmark/tmp/miniprofiler/mp_timers_hjry5rc32imd42oxoi48 +0 -0
  92. data/test/benchmark/tmp/miniprofiler/mp_timers_m8fpoz2cvt3g9agz0bs3 +0 -0
  93. data/test/benchmark/tmp/miniprofiler/mp_timers_p92m2drnj1i568u3sta0 +0 -0
  94. data/test/benchmark/tmp/miniprofiler/mp_timers_qg52tpca3uesdfguee9i +0 -0
  95. data/test/benchmark/tmp/miniprofiler/mp_timers_s15t1a6mvxe0z7vjv790 +0 -0
  96. data/test/benchmark/tmp/miniprofiler/mp_timers_x8kal3d17nfds6vp4kcj +0 -0
  97. data/test/benchmark/tmp/miniprofiler/mp_views_127.0.0.1 +0 -0
  98. data/test/fixtures/active_record.rb +0 -96
  99. data/test/fixtures/poro.rb +0 -255
  100. data/test/fixtures/template.html.erb +0 -1
  101. data/test/integration/action_controller/namespaced_serialization_test.rb +0 -105
  102. data/test/integration/action_controller/serialization_test.rb +0 -287
  103. data/test/integration/action_controller/serialization_test_case_test.rb +0 -71
  104. data/test/integration/active_record/active_record_test.rb +0 -94
  105. data/test/integration/generators/resource_generator_test.rb +0 -26
  106. data/test/integration/generators/scaffold_controller_generator_test.rb +0 -64
  107. data/test/integration/generators/serializer_generator_test.rb +0 -41
  108. data/test/test_app.rb +0 -18
  109. data/test/test_helper.rb +0 -31
  110. data/test/tmp/app/assets/javascripts/accounts.js +0 -2
  111. data/test/tmp/app/assets/stylesheets/accounts.css +0 -4
  112. data/test/tmp/app/controllers/accounts_controller.rb +0 -3
  113. data/test/tmp/app/helpers/accounts_helper.rb +0 -3
  114. data/test/tmp/app/serializers/account_serializer.rb +0 -4
  115. data/test/tmp/config/routes.rb +0 -2
  116. data/test/unit/active_model/array_serializer/except_test.rb +0 -18
  117. data/test/unit/active_model/array_serializer/key_format_test.rb +0 -18
  118. data/test/unit/active_model/array_serializer/meta_test.rb +0 -53
  119. data/test/unit/active_model/array_serializer/only_test.rb +0 -18
  120. data/test/unit/active_model/array_serializer/options_test.rb +0 -16
  121. data/test/unit/active_model/array_serializer/root_test.rb +0 -102
  122. data/test/unit/active_model/array_serializer/scope_test.rb +0 -24
  123. data/test/unit/active_model/array_serializer/serialization_test.rb +0 -239
  124. data/test/unit/active_model/default_serializer_test.rb +0 -13
  125. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +0 -36
  126. data/test/unit/active_model/serializer/associations_test.rb +0 -49
  127. data/test/unit/active_model/serializer/attributes_test.rb +0 -57
  128. data/test/unit/active_model/serializer/config_test.rb +0 -91
  129. data/test/unit/active_model/serializer/filter_test.rb +0 -69
  130. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +0 -189
  131. data/test/unit/active_model/serializer/has_many_test.rb +0 -265
  132. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +0 -27
  133. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +0 -196
  134. data/test/unit/active_model/serializer/has_one_test.rb +0 -253
  135. data/test/unit/active_model/serializer/key_format_test.rb +0 -25
  136. data/test/unit/active_model/serializer/meta_test.rb +0 -39
  137. data/test/unit/active_model/serializer/options_test.rb +0 -42
  138. data/test/unit/active_model/serializer/root_test.rb +0 -117
  139. data/test/unit/active_model/serializer/scope_test.rb +0 -49
  140. data/test/unit/active_model/serializer/url_helpers_test.rb +0 -36
  141. data/test/unit/active_model/serilizable_test.rb +0 -50
  142. /data/lib/{active_model/serializer/generators/serializer/templates/serializer.rb → generators/rails/templates/serializer.rb.erb} +0 -0
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_model/default_serializer'
4
- require 'active_model/serializable'
5
-
6
- module ActiveModel
7
- class ArraySerializer
8
- include Serializable
9
-
10
- class << self
11
- attr_accessor :_root
12
- alias root _root=
13
- alias root= _root=
14
- end
15
-
16
- def initialize(object, options={})
17
- @object = object
18
- @scope = options[:scope]
19
- @root = options.fetch(:root, self.class._root)
20
- @polymorphic = options.fetch(:polymorphic, false)
21
- @meta_key = options[:meta_key] || :meta
22
- @meta = options[@meta_key]
23
- @each_serializer = options[:each_serializer]
24
- @resource_name = options[:resource_name]
25
- @only = options[:only] ? Array(options[:only]) : nil
26
- @except = options[:except] ? Array(options[:except]) : nil
27
- @context = options[:context]
28
- @namespace = options[:namespace]
29
- @key_format = options[:key_format] || options[:each_serializer].try(:key_format)
30
- end
31
- attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context
32
-
33
- def json_key
34
- key = root.nil? ? @resource_name : root
35
-
36
- key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
37
- end
38
-
39
- def serializer_for(item)
40
- serializer_class = @each_serializer || Serializer.serializer_for(item, namespace: @namespace) || DefaultSerializer
41
- serializer_class.new(item, scope: scope, key_format: key_format, context: @context, only: @only, except: @except, polymorphic: @polymorphic, namespace: @namespace)
42
- end
43
-
44
- def serializable_object(options={})
45
- @object.map do |item|
46
- serializer_for(item).serializable_object_with_notification(options)
47
- end
48
- end
49
- alias_method :serializable_array, :serializable_object
50
-
51
- def embedded_in_root_associations
52
- @object.each_with_object({}) do |item, hash|
53
- serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
54
- next if !objects || objects.flatten.empty?
55
-
56
- if hash.has_key?(type)
57
- case hash[type] when Hash
58
- hash[type].deep_merge!(objects){ |key, old, new| (Array(old) + Array(new)).uniq }
59
- else
60
- hash[type].concat(objects).uniq!
61
- end
62
- else
63
- hash[type] = objects
64
- end
65
- end
66
- end
67
- end
68
-
69
- end
70
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_model/serializable'
4
-
5
- module ActiveModel
6
- # DefaultSerializer
7
- #
8
- # Provides a constant interface for all items
9
- class DefaultSerializer
10
- include ActiveModel::Serializable
11
-
12
- attr_reader :object
13
-
14
- def initialize(object, options={})
15
- @object = object
16
- @wrap_in_array = options[:_wrap_in_array]
17
- end
18
-
19
- def as_json(options={})
20
- instrument do
21
- return [] if @object.nil? && @wrap_in_array
22
- hash = @object.as_json
23
- @wrap_in_array ? [hash] : hash
24
- end
25
- end
26
-
27
- alias serializable_hash as_json
28
- alias serializable_object as_json
29
- end
30
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- module Serializable
5
- module Utils
6
- extend self
7
-
8
- def _const_get(const)
9
- begin
10
- method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get
11
- Object.send method, const
12
- rescue NameError
13
- const.safe_constantize
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_model/serializable/utils'
4
-
5
- module ActiveModel
6
- module Serializable
7
- INSTRUMENTATION_KEY = '!serialize.active_model_serializers'
8
-
9
- def self.included(base)
10
- base.extend Utils
11
- end
12
-
13
- def as_json(options={})
14
- instrument do
15
- if root = options.fetch(:root, json_key)
16
- hash = { root => serializable_object(options) }
17
- hash.merge!(serializable_data)
18
- hash
19
- else
20
- serializable_object(options)
21
- end
22
- end
23
- end
24
-
25
- def serializable_object_with_notification(options={})
26
- instrument { serializable_object(options) }
27
- end
28
-
29
- def serializable_data
30
- embedded_in_root_associations.tap do |hash|
31
- if respond_to?(:meta) && meta
32
- hash[meta_key] = meta
33
- end
34
- end
35
- end
36
-
37
- def namespace
38
- if module_name = get_namespace
39
- Serializer.serializers_cache.fetch_or_store(module_name) do
40
- Utils._const_get(module_name)
41
- end
42
- end
43
- end
44
-
45
- def embedded_in_root_associations
46
- {}
47
- end
48
-
49
- private
50
-
51
- def get_namespace
52
- modules = self.class.name.split('::')
53
- modules[0..-2].join('::') if modules.size > 1
54
- end
55
-
56
- def instrument(&block)
57
- payload = { serializer: self.class.name }
58
- ActiveSupport::Notifications.instrument(INSTRUMENTATION_KEY, payload, &block)
59
- end
60
- end
61
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- class Serializer
5
- class Association
6
- class HasMany < Association
7
- def initialize(name, *args)
8
- super
9
- @root_key = @embedded_key.to_s
10
- @key ||= case CONFIG.default_key_type
11
- when :name then name.to_s.pluralize
12
- else "#{name.to_s.singularize}_ids"
13
- end
14
- end
15
-
16
- def serializer_class(object, _)
17
- if use_array_serializer?
18
- ArraySerializer
19
- else
20
- serializer_from_options
21
- end
22
- end
23
-
24
- def options
25
- if use_array_serializer?
26
- { each_serializer: serializer_from_options }.merge! super
27
- else
28
- super
29
- end
30
- end
31
-
32
- private
33
-
34
- def use_array_serializer?
35
- !serializer_from_options ||
36
- serializer_from_options && !(serializer_from_options <= ArraySerializer)
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- class Serializer
5
- class Association
6
- class HasOne < Association
7
- def initialize(name, *args)
8
- super
9
- @root_key = @embedded_key.to_s.pluralize
10
- @key ||= case CONFIG.default_key_type
11
- when :name then name.to_s.singularize
12
- else "#{name}_id"
13
- end
14
- end
15
-
16
- def serializer_class(object, options = {})
17
- (serializer_from_options unless object.nil?) || serializer_from_object(object, options) || default_serializer
18
- end
19
-
20
- def build_serializer(object, options = {})
21
- options[:_wrap_in_array] = embed_in_root?
22
- super
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- class Serializer
5
- class Config
6
- def initialize(data = {})
7
- @data = data
8
- end
9
-
10
- def each(&block)
11
- @data.each(&block)
12
- end
13
-
14
- def clear
15
- @data.clear
16
- end
17
-
18
- def method_missing(name, *args)
19
- name = name.to_s
20
- return @data[name] if @data.include?(name)
21
- match = name.match(/\A(.*?)([?=]?)\Z/)
22
- case match[2]
23
- when "="
24
- @data[match[1]] = args.first
25
- when "?"
26
- !!@data[match[1]]
27
- end
28
- end
29
- end
30
-
31
- CONFIG = Config.new('embed' => :objects) # :nodoc:
32
- end
33
- end
@@ -1,9 +0,0 @@
1
- Description:
2
- Generates a serializer for the given resource with tests.
3
-
4
- Example:
5
- `rails generate serializer Account name created_at`
6
-
7
- For TestUnit it creates:
8
- Serializer: app/serializers/account_serializer.rb
9
- TestUnit: test/unit/account_serializer_test.rb
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails/generators'
4
- require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
5
-
6
- module Rails
7
- module Generators
8
- class ScaffoldControllerGenerator
9
- if Rails::VERSION::MAJOR >= 4
10
- source_root File.expand_path('../templates', __FILE__)
11
-
12
- hook_for :serializer, default: true, type: :boolean
13
- end
14
- end
15
- end
16
- end
@@ -1,93 +0,0 @@
1
- <% if namespaced? -%>
2
- require_dependency "<%= namespaced_file_path %>/application_controller"
3
-
4
- <% end -%>
5
- <% module_namespacing do -%>
6
- class <%= controller_class_name %>Controller < ApplicationController
7
- before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
8
-
9
- # GET <%= route_url %>
10
- # GET <%= route_url %>.json
11
- def index
12
- @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
13
-
14
- respond_to do |format|
15
- format.html # index.html.erb
16
- format.json { render json: <%= "@#{plural_table_name}" %> }
17
- end
18
- end
19
-
20
- # GET <%= route_url %>/1
21
- # GET <%= route_url %>/1.json
22
- def show
23
- respond_to do |format|
24
- format.html # show.html.erb
25
- format.json { render json: <%= "@#{singular_table_name}" %> }
26
- end
27
- end
28
-
29
- # GET <%= route_url %>/new
30
- def new
31
- @<%= singular_table_name %> = <%= orm_class.build(class_name) %>
32
- end
33
-
34
- # GET <%= route_url %>/1/edit
35
- def edit
36
- end
37
-
38
- # POST <%= route_url %>
39
- # POST <%= route_url %>.json
40
- def create
41
- @<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
42
-
43
- respond_to do |format|
44
- if @<%= orm_instance.save %>
45
- format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %> }
46
- format.json { render json: <%= "@#{singular_table_name}" %>, status: :created }
47
- else
48
- format.html { render action: 'new' }
49
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
50
- end
51
- end
52
- end
53
-
54
- # PATCH/PUT <%= route_url %>/1
55
- # PATCH/PUT <%= route_url %>/1.json
56
- def update
57
- respond_to do |format|
58
- if @<%= orm_instance.update("#{singular_table_name}_params") %>
59
- format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %> }
60
- format.json { head :no_content }
61
- else
62
- format.html { render action: 'edit' }
63
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
64
- end
65
- end
66
- end
67
-
68
- # DELETE <%= route_url %>/1
69
- # DELETE <%= route_url %>/1.json
70
- def destroy
71
- @<%= orm_instance.destroy %>
72
- respond_to do |format|
73
- format.html { redirect_to <%= index_helper %>_url }
74
- format.json { head :no_content }
75
- end
76
- end
77
-
78
- private
79
- # Use callbacks to share common setup or constraints between actions.
80
- def set_<%= singular_table_name %>
81
- @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
82
- end
83
-
84
- # Never trust parameters from the scary internet, only allow the white list through.
85
- def <%= "#{singular_table_name}_params" %>
86
- <%- if attributes_names.empty? -%>
87
- params[<%= ":#{singular_table_name}" %>]
88
- <%- else -%>
89
- params.require(<%= ":#{singular_table_name}" %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
90
- <%- end -%>
91
- end
92
- end
93
- <% end -%>
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- class Railtie < Rails::Railtie
5
- initializer 'generators' do |app|
6
- app.load_generators
7
- require 'active_model/serializer/generators/serializer/serializer_generator'
8
- require 'active_model/serializer/generators/serializer/scaffold_controller_generator'
9
- require 'active_model/serializer/generators/resource_override'
10
- end
11
-
12
- initializer 'include_routes.active_model_serializer' do |app|
13
- ActiveSupport.on_load(:active_model_serializers) do
14
- include app.routes.url_helpers
15
- end
16
- end
17
-
18
- config.to_prepare do
19
- ActiveModel::Serializer.serializers_cache.clear
20
- end
21
- end
22
- end
23
-
24
- ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveModel
4
- module SerializerSupport
5
- alias read_attribute_for_serialization send
6
- end
7
- end
@@ -1,60 +0,0 @@
1
- # https://github.com/rails-api/active_model_serializers/pull/872
2
- # approx ref 792fb8a9053f8db3c562dae4f40907a582dd1720 to test against
3
- require 'bundler/setup'
4
-
5
- require 'rails'
6
- require 'active_model'
7
- require 'active_support'
8
- require 'active_support/json'
9
- require 'action_controller'
10
- require 'action_controller/test_case'
11
- require 'action_controller/railtie'
12
- abort "Rails application already defined: #{Rails.application.class}" if Rails.application
13
-
14
- class NullLogger < Logger
15
- def initialize(*_args)
16
- end
17
-
18
- def add(*_args, &_block)
19
- end
20
- end
21
- class BenchmarkLogger < ActiveSupport::Logger
22
- def initialize
23
- @file = StringIO.new
24
- super(@file)
25
- end
26
-
27
- def messages
28
- @file.rewind
29
- @file.read
30
- end
31
- end
32
- # ref: https://gist.github.com/bf4/8744473
33
- class BenchmarkApp < Rails::Application
34
- # Set up production configuration
35
- config.eager_load = true
36
- config.cache_classes = true
37
- # CONFIG: CACHE_ON={on,off}
38
- config.action_controller.perform_caching = ENV['CACHE_ON'] != 'off'
39
- config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
40
-
41
- config.active_support.test_order = :random
42
- config.secret_token = 'S' * 30
43
- config.secret_key_base = 'abc123'
44
- config.consider_all_requests_local = false
45
-
46
- # otherwise deadlock occurred
47
- config.middleware.delete 'Rack::Lock'
48
-
49
- # to disable log files
50
- config.logger = NullLogger.new
51
- config.active_support.deprecation = :log
52
- config.log_level = :info
53
- end
54
-
55
- require 'active_model_serializers'
56
-
57
- # Initialize app before any serializers are defined, for running across revisions.
58
- # ref: https://github.com/rails-api/active_model_serializers/pull/1478
59
- Rails.application.initialize!
60
-
@@ -1,67 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'json'
3
-
4
- # Add benchmarking runner from ruby-bench-suite
5
- # https://github.com/ruby-bench/ruby-bench-suite/blob/master/rails/benchmarks/support/benchmark_rails.rb
6
- module Benchmark
7
- module ActiveModelSerializers
8
- module TestMethods
9
- def request(method, path)
10
- response = Rack::MockRequest.new(BenchmarkApp).send(method, path)
11
- if response.status.in?([404, 500])
12
- fail "omg, #{method}, #{path}, '#{response.status}', '#{response.body}'"
13
- end
14
- response
15
- end
16
- end
17
-
18
- # extend Benchmark with an `ams` method
19
- def ams(label = nil, time:, disable_gc: true, warmup: 3, &block)
20
- fail ArgumentError.new, 'block should be passed' unless block_given?
21
-
22
- if disable_gc
23
- GC.disable
24
- else
25
- GC.enable
26
- end
27
-
28
- report = Benchmark.ips(time, warmup, true) do |x|
29
- x.report(label) { yield }
30
- end
31
-
32
- entry = report.entries.first
33
-
34
- output = {
35
- label: label,
36
- version: ::ActiveModel::Serializer::VERSION.to_s,
37
- rails_version: ::Rails.version.to_s,
38
- iterations_per_second: entry.ips,
39
- iterations_per_second_standard_deviation: entry.error_percentage,
40
- total_allocated_objects_per_iteration: count_total_allocated_objects(&block)
41
- }.to_json
42
-
43
- puts output
44
- output
45
- end
46
-
47
- def count_total_allocated_objects
48
- if block_given?
49
- key =
50
- if RUBY_VERSION < '2.2'
51
- :total_allocated_object
52
- else
53
- :total_allocated_objects
54
- end
55
-
56
- before = GC.stat[key]
57
- yield
58
- after = GC.stat[key]
59
- after - before
60
- else
61
- -1
62
- end
63
- end
64
- end
65
-
66
- extend Benchmark::ActiveModelSerializers
67
- end
@@ -1,41 +0,0 @@
1
- require_relative './benchmarking_support'
2
- require_relative './app'
3
- require_relative './setup'
4
-
5
- time = 10
6
- disable_gc = true
7
-
8
-
9
-
10
- authors_query = Author.preload(:posts).preload(:profile)
11
- author = authors_query.first
12
- authors = authors_query.to_a
13
-
14
-
15
- Benchmark.ams('Single: DefaultSerializer', time: time, disable_gc: disable_gc) do
16
- ActiveModel::DefaultSerializer.new(author).to_json
17
- end
18
-
19
- Benchmark.ams('ArraySerializer', time: time, disable_gc: disable_gc) do
20
- ActiveModel::ArraySerializer.new(authors).to_json
21
- end
22
-
23
- Benchmark.ams('ArraySerializer: each_serializer: DefaultSerializer', time: time, disable_gc: disable_gc) do
24
- ActiveModel::ArraySerializer.new(authors, each_serializer:ActiveModel::DefaultSerializer).to_json
25
- end
26
-
27
- Benchmark.ams('FlatAuthorSerializer', time: time, disable_gc: disable_gc) do
28
- FlatAuthorSerializer.new(author).to_json
29
- end
30
-
31
- Benchmark.ams('ArraySerializer: each_serializer: FlatAuthorSerializer', time: time, disable_gc: disable_gc) do
32
- ActiveModel::ArraySerializer.new(authors, each_serializer: FlatAuthorSerializer).to_json
33
- end
34
-
35
- Benchmark.ams('AuthorWithDefaultRelationshipsSerializer', time: time, disable_gc: disable_gc) do
36
- AuthorWithDefaultRelationshipsSerializer.new(author).to_json
37
- end
38
-
39
- Benchmark.ams('ArraySerializer: each_serializer: AuthorWithDefaultRelationshipsSerializer', time: time, disable_gc: disable_gc) do
40
- ActiveModel::ArraySerializer.new(authors, each_serializer: AuthorWithDefaultRelationshipsSerializer).to_json
41
- end
@@ -1,75 +0,0 @@
1
- ###########################################
2
- # Setup active record models
3
- ##########################################
4
- require 'active_record'
5
- require 'sqlite3'
6
-
7
-
8
- # Change the following to reflect your database settings
9
- ActiveRecord::Base.establish_connection(
10
- adapter: 'sqlite3',
11
- database: ':memory:'
12
- )
13
-
14
- # Don't show migration output when constructing fake db
15
- ActiveRecord::Migration.verbose = false
16
-
17
- ActiveRecord::Schema.define do
18
- create_table :authors, force: true do |t|
19
- t.string :name
20
- end
21
-
22
- create_table :posts, force: true do |t|
23
- t.text :body
24
- t.string :title
25
- t.references :author
26
- end
27
-
28
- create_table :profiles, force: true do |t|
29
- t.text :project_url
30
- t.text :bio
31
- t.date :birthday
32
- t.references :author
33
- end
34
- end
35
-
36
- class Author < ActiveRecord::Base
37
- has_one :profile
38
- has_many :posts
39
- end
40
-
41
- class Post < ActiveRecord::Base
42
- belongs_to :author
43
- end
44
-
45
- class Profile < ActiveRecord::Base
46
- belongs_to :author
47
- end
48
-
49
- # Build out the data to serialize
50
- author = Author.create(name: 'Preston Sego')
51
- Profile.create(project_url: 'https://github.com/NullVoxPopuli', author: author)
52
- 50.times do
53
- Post.create(
54
- body: 'something about how password restrictions are evil, and less secure, and with the math to prove it.',
55
- title: 'Your bank is does not know how to do security',
56
- author: author
57
- )
58
- end
59
-
60
- ActiveModel::Serializer.root = false
61
- ActiveModel::ArraySerializer.root = false
62
-
63
- class FlatAuthorSerializer < ActiveModel::Serializer
64
- attributes :id, :name
65
- end
66
-
67
- class AuthorWithDefaultRelationshipsSerializer < ActiveModel::Serializer
68
- attributes :id, :name
69
-
70
- has_one :profile
71
- has_many :posts
72
- end
73
-
74
- # For debugging SQL output
75
- #ActiveRecord::Base.logger = Logger.new(STDERR)