active_model_serializers 0.9.0 → 0.10.12

Sign up to get free protection for your applications and to get access to all the features.
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 -%>