active_model_serializers 0.9.0 → 0.10.12

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 (113) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +679 -9
  3. data/MIT-LICENSE +3 -2
  4. data/README.md +195 -753
  5. data/lib/action_controller/serialization.rb +45 -49
  6. data/lib/active_model/serializable_resource.rb +13 -0
  7. data/lib/active_model/serializer.rb +369 -212
  8. data/lib/active_model/serializer/adapter.rb +26 -0
  9. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  10. data/lib/active_model/serializer/adapter/base.rb +20 -0
  11. data/lib/active_model/serializer/adapter/json.rb +17 -0
  12. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  13. data/lib/active_model/serializer/adapter/null.rb +17 -0
  14. data/lib/active_model/serializer/array_serializer.rb +14 -0
  15. data/lib/active_model/serializer/association.rb +73 -0
  16. data/lib/active_model/serializer/attribute.rb +27 -0
  17. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  18. data/lib/active_model/serializer/collection_serializer.rb +90 -0
  19. data/lib/active_model/serializer/concerns/caching.rb +305 -0
  20. data/lib/active_model/serializer/error_serializer.rb +16 -0
  21. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  22. data/lib/active_model/serializer/field.rb +92 -0
  23. data/lib/active_model/serializer/fieldset.rb +33 -0
  24. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  25. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  26. data/lib/active_model/serializer/lazy_association.rb +99 -0
  27. data/lib/active_model/serializer/link.rb +23 -0
  28. data/lib/active_model/serializer/lint.rb +152 -0
  29. data/lib/active_model/serializer/null.rb +19 -0
  30. data/lib/active_model/serializer/reflection.rb +212 -0
  31. data/lib/active_model/serializer/version.rb +3 -1
  32. data/lib/active_model_serializers.rb +60 -17
  33. data/lib/active_model_serializers/adapter.rb +100 -0
  34. data/lib/active_model_serializers/adapter/attributes.rb +36 -0
  35. data/lib/active_model_serializers/adapter/base.rb +85 -0
  36. data/lib/active_model_serializers/adapter/json.rb +23 -0
  37. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  38. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  39. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  40. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  41. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  42. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  43. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
  44. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  45. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  46. data/lib/active_model_serializers/adapter/null.rb +11 -0
  47. data/lib/active_model_serializers/callbacks.rb +57 -0
  48. data/lib/active_model_serializers/deprecate.rb +56 -0
  49. data/lib/active_model_serializers/deserialization.rb +17 -0
  50. data/lib/active_model_serializers/json_pointer.rb +16 -0
  51. data/lib/active_model_serializers/logging.rb +124 -0
  52. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  53. data/lib/active_model_serializers/model.rb +132 -0
  54. data/lib/active_model_serializers/model/caching.rb +25 -0
  55. data/lib/active_model_serializers/railtie.rb +52 -0
  56. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  57. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  58. data/lib/active_model_serializers/serialization_context.rb +41 -0
  59. data/lib/active_model_serializers/test.rb +9 -0
  60. data/lib/active_model_serializers/test/schema.rb +140 -0
  61. data/lib/active_model_serializers/test/serializer.rb +127 -0
  62. data/lib/generators/rails/USAGE +6 -0
  63. data/lib/{active_model/serializer/generators → generators/rails}/resource_override.rb +3 -4
  64. data/lib/{active_model/serializer/generators/serializer → generators/rails}/serializer_generator.rb +6 -5
  65. data/lib/{active_model/serializer/generators/serializer/templates/serializer.rb → generators/rails/templates/serializer.rb.erb} +0 -0
  66. data/lib/grape/active_model_serializers.rb +18 -0
  67. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  68. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  69. data/lib/tasks/rubocop.rake +55 -0
  70. metadata +315 -99
  71. data/CONTRIBUTING.md +0 -20
  72. data/DESIGN.textile +0 -586
  73. data/lib/action_controller/serialization_test_case.rb +0 -79
  74. data/lib/active_model/array_serializer.rb +0 -65
  75. data/lib/active_model/default_serializer.rb +0 -32
  76. data/lib/active_model/serializable.rb +0 -40
  77. data/lib/active_model/serializer/associations.rb +0 -102
  78. data/lib/active_model/serializer/config.rb +0 -31
  79. data/lib/active_model/serializer/generators/serializer/USAGE +0 -9
  80. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +0 -14
  81. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +0 -93
  82. data/lib/active_model/serializer/railtie.rb +0 -10
  83. data/lib/active_model/serializer_support.rb +0 -5
  84. data/test/fixtures/active_record.rb +0 -92
  85. data/test/fixtures/poro.rb +0 -75
  86. data/test/integration/action_controller/serialization_test.rb +0 -287
  87. data/test/integration/action_controller/serialization_test_case_test.rb +0 -61
  88. data/test/integration/active_record/active_record_test.rb +0 -77
  89. data/test/integration/generators/resource_generator_test.rb +0 -26
  90. data/test/integration/generators/scaffold_controller_generator_test.rb +0 -64
  91. data/test/integration/generators/serializer_generator_test.rb +0 -41
  92. data/test/test_app.rb +0 -11
  93. data/test/test_helper.rb +0 -24
  94. data/test/unit/active_model/array_serializer/except_test.rb +0 -18
  95. data/test/unit/active_model/array_serializer/key_format_test.rb +0 -18
  96. data/test/unit/active_model/array_serializer/meta_test.rb +0 -53
  97. data/test/unit/active_model/array_serializer/only_test.rb +0 -18
  98. data/test/unit/active_model/array_serializer/root_test.rb +0 -102
  99. data/test/unit/active_model/array_serializer/scope_test.rb +0 -24
  100. data/test/unit/active_model/array_serializer/serialization_test.rb +0 -199
  101. data/test/unit/active_model/default_serializer_test.rb +0 -13
  102. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +0 -21
  103. data/test/unit/active_model/serializer/associations_test.rb +0 -19
  104. data/test/unit/active_model/serializer/attributes_test.rb +0 -41
  105. data/test/unit/active_model/serializer/config_test.rb +0 -88
  106. data/test/unit/active_model/serializer/filter_test.rb +0 -69
  107. data/test/unit/active_model/serializer/has_many_test.rb +0 -230
  108. data/test/unit/active_model/serializer/has_one_test.rb +0 -207
  109. data/test/unit/active_model/serializer/key_format_test.rb +0 -25
  110. data/test/unit/active_model/serializer/meta_test.rb +0 -39
  111. data/test/unit/active_model/serializer/options_test.rb +0 -15
  112. data/test/unit/active_model/serializer/root_test.rb +0 -117
  113. data/test/unit/active_model/serializer/scope_test.rb +0 -49
@@ -1,79 +0,0 @@
1
- module ActionController
2
- module SerializationAssertions
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- setup :setup_subscriptions
7
- teardown :teardown_subscriptions
8
- end
9
-
10
- def setup_subscriptions
11
- @serializers = Hash.new(0)
12
-
13
- ActiveSupport::Notifications.subscribe("!serialize.active_model_serializers") do |name, start, finish, id, payload|
14
- serializer = payload[:serializer]
15
- @serializers[serializer] += 1
16
- end
17
- end
18
-
19
- def teardown_subscriptions
20
- ActiveSupport::Notifications.unsubscribe("!serialize.active_model_serializers")
21
- end
22
-
23
- def process(*args)
24
- @serializers = Hash.new(0)
25
- super
26
- end
27
-
28
- # Asserts that the request was rendered with the appropriate serializers.
29
- #
30
- # # assert that the "PostSerializer" serializer was rendered
31
- # assert_serializer "PostSerializer"
32
- #
33
- # # assert that the instance of PostSerializer was rendered
34
- # assert_serializer PostSerializer
35
- #
36
- # # assert that the "PostSerializer" serializer was rendered
37
- # assert_serializer :post_serializer
38
- #
39
- # # assert that the rendered serializer starts with "Post"
40
- # assert_serializer %r{\APost.+\Z}
41
- #
42
- # # assert that no serializer was rendered
43
- # assert_serializer nil
44
- #
45
- #
46
- def assert_serializer(options = {}, message = nil)
47
- # Force body to be read in case the template is being streamed.
48
- response.body
49
-
50
- rendered = @serializers
51
- msg = message || "expecting <#{options.inspect}> but rendering with <#{rendered.keys}>"
52
-
53
- matches_serializer = case options
54
- when lambda { |options| options.kind_of?(Class) && options < ActiveModel::Serializer }
55
- rendered.any? do |serializer, count|
56
- options.name == serializer
57
- end
58
- when Symbol
59
- options = options.to_s.camelize
60
- rendered.any? do |serializer, count|
61
- serializer == options
62
- end
63
- when String
64
- !options.empty? && rendered.any? do |serializer, count|
65
- serializer == options
66
- end
67
- when Regexp
68
- rendered.any? do |serializer, count|
69
- serializer.match(options)
70
- end
71
- when NilClass
72
- rendered.blank?
73
- else
74
- raise ArgumentError, "assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil"
75
- end
76
- assert matches_serializer, msg
77
- end
78
- end
79
- end
@@ -1,65 +0,0 @@
1
- require 'active_model/default_serializer'
2
- require 'active_model/serializable'
3
-
4
- module ActiveModel
5
- class ArraySerializer
6
- include Serializable
7
-
8
- class << self
9
- attr_accessor :_root
10
- alias root _root=
11
- alias root= _root=
12
- end
13
-
14
- def initialize(object, options={})
15
- @object = object
16
- @scope = options[:scope]
17
- @root = options.fetch(:root, self.class._root)
18
- @meta_key = options[:meta_key] || :meta
19
- @meta = options[@meta_key]
20
- @each_serializer = options[:each_serializer]
21
- @resource_name = options[:resource_name]
22
- @only = options[:only] ? Array(options[:only]) : nil
23
- @except = options[:except] ? Array(options[:except]) : nil
24
- @key_format = options[:key_format] || options[:each_serializer].try(:key_format)
25
- end
26
- attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
27
-
28
- def json_key
29
- key = root.nil? ? @resource_name : root
30
-
31
- key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
32
- end
33
-
34
- def serializer_for(item)
35
- serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
36
- serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except)
37
- end
38
-
39
- def serializable_object
40
- @object.map do |item|
41
- serializer_for(item).serializable_object
42
- end
43
- end
44
- alias_method :serializable_array, :serializable_object
45
-
46
- def embedded_in_root_associations
47
- @object.each_with_object({}) do |item, hash|
48
- serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
49
- next if !objects || objects.flatten.empty?
50
-
51
- if hash.has_key?(type)
52
- hash[type].concat(objects).uniq!
53
- else
54
- hash[type] = objects
55
- end
56
- end
57
- end
58
- end
59
-
60
- private
61
- def instrumentation_keys
62
- [:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
63
- end
64
- end
65
- end
@@ -1,32 +0,0 @@
1
- require 'active_model/serializable'
2
-
3
- module ActiveModel
4
- # DefaultSerializer
5
- #
6
- # Provides a constant interface for all items
7
- class DefaultSerializer
8
- include ActiveModel::Serializable
9
-
10
- attr_reader :object
11
-
12
- def initialize(object, options={})
13
- @object = object
14
- @wrap_in_array = options[:_wrap_in_array]
15
- end
16
-
17
- def as_json(options={})
18
- instrument('!serialize') do
19
- return [] if @object.nil? && @wrap_in_array
20
- hash = @object.as_json
21
- @wrap_in_array ? [hash] : hash
22
- end
23
- end
24
- alias serializable_hash as_json
25
- alias serializable_object as_json
26
-
27
- private
28
- def instrumentation_keys
29
- [:object, :wrap_in_array]
30
- end
31
- end
32
- end
@@ -1,40 +0,0 @@
1
- module ActiveModel
2
- module Serializable
3
- def as_json(options={})
4
- instrument('!serialize') do
5
- if root = options.fetch(:root, json_key)
6
- hash = { root => serializable_object }
7
- hash.merge!(serializable_data)
8
- hash
9
- else
10
- serializable_object
11
- end
12
- end
13
- end
14
-
15
- def serializable_data
16
- embedded_in_root_associations.tap do |hash|
17
- if respond_to?(:meta) && meta
18
- hash[meta_key] = meta
19
- end
20
- end
21
- end
22
-
23
- def embedded_in_root_associations
24
- {}
25
- end
26
-
27
- private
28
- def instrument(action, &block)
29
- payload = instrumentation_keys.inject({ serializer: self.class.name }) do |payload, key|
30
- payload[:payload] = self.instance_variable_get(:"@#{key}")
31
- payload
32
- end
33
- ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
34
- end
35
-
36
- def instrumentation_keys
37
- [:object, :scope, :root, :meta_key, :meta, :wrap_in_array, :only, :except, :key_format]
38
- end
39
- end
40
- end
@@ -1,102 +0,0 @@
1
- require 'active_model/default_serializer'
2
-
3
- module ActiveModel
4
- class Serializer
5
- class Association
6
- def initialize(name, options={})
7
- if options.has_key?(:include)
8
- ActiveSupport::Deprecation.warn <<-WARN
9
- ** Notice: include was renamed to embed_in_root. **
10
- WARN
11
- end
12
-
13
- @name = name.to_s
14
- @options = options
15
- self.embed = options.fetch(:embed) { CONFIG.embed }
16
- @embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
17
- @key_format = options.fetch(:key_format) { CONFIG.key_format }
18
- @embed_key = options[:embed_key] || :id
19
- @key = options[:key]
20
- @embedded_key = options[:root] || name
21
- @embed_in_root_key = options.fetch(:embed_in_root_key) { CONFIG.embed_in_root_key }
22
- @embed_namespace = options.fetch(:embed_namespace) { CONFIG.embed_namespace }
23
-
24
- serializer = @options[:serializer]
25
- @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
26
- end
27
-
28
- attr_reader :name, :embed_ids, :embed_objects
29
- attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
30
- alias embed_ids? embed_ids
31
- alias embed_objects? embed_objects
32
- alias embed_in_root? embed_in_root
33
- alias embed_in_root_key? embed_in_root_key
34
- alias embed_namespace? embed_namespace
35
-
36
- def embed=(embed)
37
- @embed_ids = embed == :id || embed == :ids
38
- @embed_objects = embed == :object || embed == :objects
39
- end
40
-
41
- def serializer_from_object(object)
42
- Serializer.serializer_for(object)
43
- end
44
-
45
- def default_serializer
46
- DefaultSerializer
47
- end
48
-
49
- def build_serializer(object, options = {})
50
- serializer_class(object).new(object, options.merge(self.options))
51
- end
52
-
53
- class HasOne < Association
54
- def initialize(name, *args)
55
- super
56
- @root_key = @embedded_key.to_s.pluralize
57
- @key ||= "#{name}_id"
58
- end
59
-
60
- def serializer_class(object)
61
- serializer_from_options || serializer_from_object(object) || default_serializer
62
- end
63
-
64
- def build_serializer(object, options = {})
65
- options[:_wrap_in_array] = embed_in_root?
66
- super
67
- end
68
- end
69
-
70
- class HasMany < Association
71
- def initialize(name, *args)
72
- super
73
- @root_key = @embedded_key
74
- @key ||= "#{name.to_s.singularize}_ids"
75
- end
76
-
77
- def serializer_class(object)
78
- if use_array_serializer?
79
- ArraySerializer
80
- else
81
- serializer_from_options
82
- end
83
- end
84
-
85
- def options
86
- if use_array_serializer?
87
- { each_serializer: serializer_from_options }.merge! super
88
- else
89
- super
90
- end
91
- end
92
-
93
- private
94
-
95
- def use_array_serializer?
96
- !serializer_from_options ||
97
- serializer_from_options && !(serializer_from_options <= ArraySerializer)
98
- end
99
- end
100
- end
101
- end
102
- end
@@ -1,31 +0,0 @@
1
- module ActiveModel
2
- class Serializer
3
- class Config
4
- def initialize(data = {})
5
- @data = data
6
- end
7
-
8
- def each(&block)
9
- @data.each(&block)
10
- end
11
-
12
- def clear
13
- @data.clear
14
- end
15
-
16
- def method_missing(name, *args)
17
- name = name.to_s
18
- return @data[name] if @data.include?(name)
19
- match = name.match(/\A(.*?)([?=]?)\Z/)
20
- case match[2]
21
- when "="
22
- @data[match[1]] = args.first
23
- when "?"
24
- !!@data[match[1]]
25
- end
26
- end
27
- end
28
-
29
- CONFIG = Config.new('embed' => :objects) # :nodoc:
30
- end
31
- 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,14 +0,0 @@
1
- require 'rails/generators'
2
- require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
3
-
4
- module Rails
5
- module Generators
6
- class ScaffoldControllerGenerator
7
- if Rails::VERSION::MAJOR >= 4
8
- source_root File.expand_path('../templates', __FILE__)
9
-
10
- hook_for :serializer, default: true
11
- end
12
- end
13
- end
14
- 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 -%>