active_model_serializers 0.8.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 (98) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +702 -6
  3. data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
  4. data/README.md +195 -536
  5. data/lib/action_controller/serialization.rb +53 -35
  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 +73 -0
  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 +90 -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 +7 -0
  31. data/lib/active_model/serializer.rb +352 -441
  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 +90 -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/caching.rb +25 -0
  53. data/lib/active_model_serializers/model.rb +132 -0
  54. data/lib/active_model_serializers/railtie.rb +52 -0
  55. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  56. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  57. data/lib/active_model_serializers/serialization_context.rb +41 -0
  58. data/lib/active_model_serializers/test/schema.rb +140 -0
  59. data/lib/active_model_serializers/test/serializer.rb +127 -0
  60. data/lib/active_model_serializers/test.rb +9 -0
  61. data/lib/active_model_serializers.rb +49 -83
  62. data/lib/generators/rails/USAGE +6 -0
  63. data/lib/generators/rails/resource_override.rb +12 -0
  64. data/lib/generators/rails/serializer_generator.rb +38 -0
  65. data/lib/generators/rails/templates/serializer.rb.erb +8 -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 +291 -77
  71. data/.gitignore +0 -18
  72. data/.travis.yml +0 -29
  73. data/DESIGN.textile +0 -586
  74. data/Gemfile +0 -6
  75. data/Gemfile.edge +0 -9
  76. data/Rakefile +0 -18
  77. data/active_model_serializers.gemspec +0 -25
  78. data/bench/perf.rb +0 -43
  79. data/cruft.md +0 -19
  80. data/lib/active_model/array_serializer.rb +0 -104
  81. data/lib/active_model/serializer/associations.rb +0 -233
  82. data/lib/active_model/serializers/version.rb +0 -5
  83. data/lib/active_record/serializer_override.rb +0 -16
  84. data/lib/generators/resource_override.rb +0 -13
  85. data/lib/generators/serializer/USAGE +0 -9
  86. data/lib/generators/serializer/serializer_generator.rb +0 -42
  87. data/lib/generators/serializer/templates/serializer.rb +0 -19
  88. data/test/array_serializer_test.rb +0 -54
  89. data/test/association_test.rb +0 -592
  90. data/test/caching_test.rb +0 -96
  91. data/test/generators_test.rb +0 -85
  92. data/test/no_serialization_scope_test.rb +0 -34
  93. data/test/serialization_scope_name_test.rb +0 -67
  94. data/test/serialization_test.rb +0 -394
  95. data/test/serializer_support_test.rb +0 -51
  96. data/test/serializer_test.rb +0 -1452
  97. data/test/test_fakes.rb +0 -194
  98. data/test/test_helper.rb +0 -41
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/array/extract_options'
4
+ module ActiveModelSerializers
5
+ class SerializationContext
6
+ class << self
7
+ attr_writer :url_helpers, :default_url_options
8
+ def url_helpers
9
+ @url_helpers ||= Module.new
10
+ end
11
+
12
+ def default_url_options
13
+ @default_url_options ||= {}
14
+ end
15
+ end
16
+ module UrlHelpers
17
+ def self.included(base)
18
+ base.send(:include, SerializationContext.url_helpers)
19
+ end
20
+
21
+ def default_url_options
22
+ SerializationContext.default_url_options
23
+ end
24
+ end
25
+
26
+ attr_reader :request_url, :query_parameters, :key_transform
27
+
28
+ def initialize(*args)
29
+ options = args.extract_options!
30
+ if args.size == 1
31
+ request = args.pop
32
+ options[:request_url] = request.original_url[/\A[^?]+/]
33
+ options[:query_parameters] = request.query_parameters
34
+ end
35
+ @request_url = options.delete(:request_url)
36
+ @query_parameters = options.delete(:query_parameters)
37
+ @url_helpers = options.delete(:url_helpers) || self.class.url_helpers
38
+ @default_url_options = options.delete(:default_url_options) || self.class.default_url_options
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module Test
5
+ module Schema
6
+ # A Minitest Assertion that test the response is valid against a schema.
7
+ # @param schema_path [String] a custom schema path
8
+ # @param message [String] a custom error message
9
+ # @return [Boolean] true when the response is valid
10
+ # @return [Minitest::Assertion] when the response is invalid
11
+ # @example
12
+ # get :index
13
+ # assert_response_schema
14
+ def assert_response_schema(schema_path = nil, message = nil)
15
+ matcher = AssertResponseSchema.new(schema_path, request, response, message)
16
+ assert(matcher.call, matcher.message)
17
+ end
18
+
19
+ def assert_request_schema(schema_path = nil, message = nil)
20
+ matcher = AssertRequestSchema.new(schema_path, request, response, message)
21
+ assert(matcher.call, matcher.message)
22
+ end
23
+
24
+ # May be renamed
25
+ def assert_request_response_schema(schema_path = nil, message = nil)
26
+ assert_request_schema(schema_path, message)
27
+ assert_response_schema(schema_path, message)
28
+ end
29
+
30
+ def assert_schema(payload, schema_path = nil, message = nil)
31
+ matcher = AssertSchema.new(schema_path, request, response, message, payload)
32
+ assert(matcher.call, matcher.message)
33
+ end
34
+
35
+ MissingSchema = Class.new(Minitest::Assertion)
36
+ InvalidSchemaError = Class.new(Minitest::Assertion)
37
+
38
+ class AssertSchema
39
+ attr_reader :schema_path, :request, :response, :message, :payload
40
+
41
+ # Interface may change.
42
+ def initialize(schema_path, request, response, message, payload = nil)
43
+ require_json_schema!
44
+ @request = request
45
+ @response = response
46
+ @payload = payload
47
+ @schema_path = schema_path || schema_path_default
48
+ @message = message
49
+ @document_store = JsonSchema::DocumentStore.new
50
+ add_schema_to_document_store
51
+ end
52
+
53
+ def call
54
+ json_schema.expand_references!(store: document_store)
55
+ status, errors = json_schema.validate(response_body)
56
+ @message = [message, errors.map(&:to_s).to_sentence].compact.join(': ')
57
+ status
58
+ end
59
+
60
+ protected
61
+
62
+ attr_reader :document_store
63
+
64
+ def controller_path
65
+ request.filtered_parameters.with_indifferent_access[:controller]
66
+ end
67
+
68
+ def action
69
+ request.filtered_parameters.with_indifferent_access[:action]
70
+ end
71
+
72
+ def schema_directory
73
+ ActiveModelSerializers.config.schema_path
74
+ end
75
+
76
+ def schema_full_path
77
+ "#{schema_directory}/#{schema_path}"
78
+ end
79
+
80
+ def schema_path_default
81
+ "#{controller_path}/#{action}.json"
82
+ end
83
+
84
+ def schema_data
85
+ load_json_file(schema_full_path)
86
+ end
87
+
88
+ def response_body
89
+ load_json(response.body)
90
+ end
91
+
92
+ def request_params
93
+ request.env['action_dispatch.request.request_parameters']
94
+ end
95
+
96
+ def json_schema
97
+ @json_schema ||= JsonSchema.parse!(schema_data)
98
+ end
99
+
100
+ def add_schema_to_document_store
101
+ Dir.glob("#{schema_directory}/**/*.json").each do |path|
102
+ schema_data = load_json_file(path)
103
+ extra_schema = JsonSchema.parse!(schema_data)
104
+ document_store.add_schema(extra_schema)
105
+ end
106
+ end
107
+
108
+ def load_json(json)
109
+ JSON.parse(json)
110
+ rescue JSON::ParserError => ex
111
+ raise InvalidSchemaError, ex.message
112
+ end
113
+
114
+ def load_json_file(path)
115
+ load_json(File.read(path))
116
+ rescue Errno::ENOENT
117
+ raise MissingSchema, "No Schema file at #{schema_full_path}"
118
+ end
119
+
120
+ def require_json_schema!
121
+ require 'json_schema'
122
+ rescue LoadError
123
+ raise LoadError, "You don't have json_schema installed in your application. Please add it to your Gemfile and run bundle install"
124
+ end
125
+ end
126
+ class AssertResponseSchema < AssertSchema
127
+ def initialize(*)
128
+ super
129
+ @payload = response_body
130
+ end
131
+ end
132
+ class AssertRequestSchema < AssertSchema
133
+ def initialize(*)
134
+ super
135
+ @payload = request_params
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ module ActiveModelSerializers
5
+ module Test
6
+ module Serializer
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ setup :setup_serialization_subscriptions
11
+ teardown :teardown_serialization_subscriptions
12
+ end
13
+
14
+ # Asserts that the request was rendered with the appropriate serializers.
15
+ #
16
+ # # assert that the "PostSerializer" serializer was rendered
17
+ # assert_serializer "PostSerializer"
18
+ #
19
+ # # return a custom error message
20
+ # assert_serializer "PostSerializer", "PostSerializer not rendered"
21
+ #
22
+ # # assert that the instance of PostSerializer was rendered
23
+ # assert_serializer PostSerializer
24
+ #
25
+ # # assert that the "PostSerializer" serializer was rendered
26
+ # assert_serializer :post_serializer
27
+ #
28
+ # # assert that the rendered serializer starts with "Post"
29
+ # assert_serializer %r{\APost.+\Z}
30
+ #
31
+ # # assert that no serializer was rendered
32
+ # assert_serializer nil
33
+ #
34
+ def assert_serializer(expectation, message = nil)
35
+ @assert_serializer.expectation = expectation
36
+ @assert_serializer.message = message
37
+ @assert_serializer.response = response
38
+ assert(@assert_serializer.matches?, @assert_serializer.message)
39
+ end
40
+
41
+ class AssertSerializer
42
+ attr_reader :serializers, :message
43
+ attr_accessor :response, :expectation
44
+
45
+ def initialize
46
+ @serializers = Set.new
47
+ @_subscribers = []
48
+ end
49
+
50
+ def message=(message)
51
+ @message = message || "expecting <#{expectation.inspect}> but rendering with <#{serializers.to_a}>"
52
+ end
53
+
54
+ def matches?
55
+ # Force body to be read in case the template is being streamed.
56
+ response.body
57
+
58
+ case expectation
59
+ when a_serializer? then matches_class?
60
+ when Symbol then matches_symbol?
61
+ when String then matches_string?
62
+ when Regexp then matches_regexp?
63
+ when NilClass then matches_nil?
64
+ else fail ArgumentError, 'assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil'
65
+ end
66
+ end
67
+
68
+ def subscribe
69
+ @_subscribers << ActiveSupport::Notifications.subscribe(event_name) do |_name, _start, _finish, _id, payload|
70
+ serializer = payload[:serializer].name
71
+ serializers << serializer
72
+ end
73
+ end
74
+
75
+ def unsubscribe
76
+ @_subscribers.each do |subscriber|
77
+ ActiveSupport::Notifications.unsubscribe(subscriber)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def matches_class?
84
+ serializers.include?(expectation.name)
85
+ end
86
+
87
+ def matches_symbol?
88
+ camelize_expectation = expectation.to_s.camelize
89
+ serializers.include?(camelize_expectation)
90
+ end
91
+
92
+ def matches_string?
93
+ !expectation.empty? && serializers.include?(expectation)
94
+ end
95
+
96
+ def matches_regexp?
97
+ serializers.any? do |serializer|
98
+ serializer.match(expectation)
99
+ end
100
+ end
101
+
102
+ def matches_nil?
103
+ serializers.empty?
104
+ end
105
+
106
+ def a_serializer?
107
+ ->(exp) { exp.is_a?(Class) && exp < ActiveModel::Serializer }
108
+ end
109
+
110
+ def event_name
111
+ ::ActiveModelSerializers::Logging::RENDER_EVENT
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def setup_serialization_subscriptions
118
+ @assert_serializer = AssertSerializer.new
119
+ @assert_serializer.subscribe
120
+ end
121
+
122
+ def teardown_serialization_subscriptions
123
+ @assert_serializer.unsubscribe
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveModelSerializers
4
+ module Test
5
+ extend ActiveSupport::Autoload
6
+ autoload :Serializer
7
+ autoload :Schema
8
+ end
9
+ end
@@ -1,97 +1,63 @@
1
- require "active_support"
2
- require "active_support/core_ext/string/inflections"
3
- require "active_support/notifications"
4
- require "active_model"
5
- require "active_model/array_serializer"
6
- require "active_model/serializer"
7
- require "active_model/serializer/associations"
8
- require "set"
9
-
10
- if defined?(Rails)
11
- module ActiveModel
12
- class Railtie < Rails::Railtie
13
- generators do |app|
14
- app ||= Rails.application # Rails 3.0.x does not yield `app`
15
-
16
- Rails::Generators.configure!(app.config.generators)
17
- Rails::Generators.hidden_namespaces.uniq!
18
- require_relative "generators/resource_override"
19
- end
20
-
21
- initializer "include_routes.active_model_serializer" do |app|
22
- ActiveSupport.on_load(:active_model_serializers) do
23
- include AbstractController::UrlFor
24
- extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
25
- include app.routes.mounted_helpers
26
- end
27
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+ require 'active_support'
5
+ require 'active_support/core_ext/object/with_options'
6
+ require 'active_support/core_ext/string/inflections'
7
+ require 'active_support/json'
8
+ module ActiveModelSerializers
9
+ extend ActiveSupport::Autoload
10
+ eager_autoload do
11
+ autoload :Model
12
+ autoload :Callbacks
13
+ autoload :SerializableResource
14
+ autoload :SerializationContext
15
+ autoload :Logging
16
+ autoload :Test
17
+ autoload :Adapter
18
+ autoload :JsonPointer
19
+ autoload :Deprecate
20
+ autoload :LookupChain
21
+ autoload :Deserialization
22
+ end
28
23
 
29
- initializer "caching.active_model_serializer" do |app|
30
- ActiveModel::Serializer.perform_caching = app.config.action_controller.perform_caching
31
- ActiveModel::ArraySerializer.perform_caching = app.config.action_controller.perform_caching
24
+ class << self; attr_accessor :logger; end
25
+ self.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
32
26
 
33
- ActiveModel::Serializer.cache = Rails.cache
34
- ActiveModel::ArraySerializer.cache = Rails.cache
35
- end
36
- end
27
+ def self.config
28
+ ActiveModel::Serializer.config
37
29
  end
38
- end
39
30
 
40
- module ActiveModel::SerializerSupport
41
- extend ActiveSupport::Concern
31
+ # The file name and line number of the caller of the caller of this method.
32
+ def self.location_of_caller
33
+ caller[1] =~ /(.*?):(\d+).*?$/i
34
+ file = Regexp.last_match(1)
35
+ lineno = Regexp.last_match(2).to_i
42
36
 
43
- module ClassMethods #:nodoc:
44
- if "".respond_to?(:safe_constantize)
45
- def active_model_serializer
46
- "#{self.name}Serializer".safe_constantize
47
- end
48
- else
49
- def active_model_serializer
50
- begin
51
- "#{self.name}Serializer".constantize
52
- rescue NameError => e
53
- raise unless e.message =~ /uninitialized constant/
54
- end
55
- end
56
- end
37
+ [file, lineno]
57
38
  end
58
39
 
59
- # Returns a model serializer for this object considering its namespace.
60
- def active_model_serializer
61
- self.class.active_model_serializer
40
+ # Memoized default include directive
41
+ # @return [JSONAPI::IncludeDirective]
42
+ def self.default_include_directive
43
+ @default_include_directive ||= JSONAPI::IncludeDirective.new(config.default_includes, allow_wildcard: true)
62
44
  end
63
45
 
64
- alias :read_attribute_for_serialization :send
65
- end
66
-
67
- module ActiveModel::ArraySerializerSupport
68
- def active_model_serializer
69
- ActiveModel::ArraySerializer
46
+ def self.silence_warnings
47
+ original_verbose = $VERBOSE
48
+ $VERBOSE = nil
49
+ yield
50
+ ensure
51
+ $VERBOSE = original_verbose
70
52
  end
71
- end
72
-
73
- Array.send(:include, ActiveModel::ArraySerializerSupport)
74
- Set.send(:include, ActiveModel::ArraySerializerSupport)
75
53
 
76
- {
77
- :active_record => 'ActiveRecord::Relation',
78
- :mongoid => 'Mongoid::Criteria'
79
- }.each do |orm, rel_class|
80
- ActiveSupport.on_load(orm) do
81
- include ActiveModel::SerializerSupport
82
- rel_class.constantize.send(:include, ActiveModel::ArraySerializerSupport)
54
+ def self.eager_load!
55
+ super
56
+ ActiveModel::Serializer.eager_load!
83
57
  end
84
- end
85
58
 
86
- begin
87
- require 'action_controller'
88
- require 'action_controller/serialization'
89
-
90
- ActiveSupport.on_load(:action_controller) do
91
- include ::ActionController::Serialization
92
- end
93
- rescue LoadError => ex
94
- # rails on installed, continuing
59
+ require 'active_model/serializer/version'
60
+ require 'active_model/serializer'
61
+ require 'active_model/serializable_resource'
62
+ require 'active_model_serializers/railtie' if defined?(::Rails::Railtie)
95
63
  end
96
-
97
- ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Generates a serializer for the given resource.
3
+
4
+ Example:
5
+ `rails generate serializer Account name created_at`
6
+
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/rails/resource/resource_generator'
5
+
6
+ module Rails
7
+ module Generators
8
+ class ResourceGenerator
9
+ hook_for :serializer, default: true, type: :boolean
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Generators
5
+ class SerializerGenerator < NamedBase
6
+ source_root File.expand_path('../templates', __FILE__)
7
+ check_class_collision suffix: 'Serializer'
8
+
9
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
10
+
11
+ class_option :parent, type: :string, desc: 'The parent class for the generated serializer'
12
+
13
+ def create_serializer_file
14
+ template 'serializer.rb.erb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
15
+ end
16
+
17
+ private
18
+
19
+ def attributes_names
20
+ [:id] + attributes.reject(&:reference?).map! { |a| a.name.to_sym }
21
+ end
22
+
23
+ def association_names
24
+ attributes.select(&:reference?).map! { |a| a.name.to_sym }
25
+ end
26
+
27
+ def parent_class_name
28
+ if options[:parent]
29
+ options[:parent]
30
+ elsif 'ApplicationSerializer'.safe_constantize
31
+ 'ApplicationSerializer'
32
+ else
33
+ 'ActiveModel::Serializer'
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Serializer < <%= parent_class_name %>
3
+ attributes <%= attributes_names.map(&:inspect).join(", ") %>
4
+ <% association_names.each do |attribute| -%>
5
+ has_one :<%= attribute %>
6
+ <% end -%>
7
+ end
8
+ <% end -%>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # To add Grape support, require 'grape/active_model_serializers' in the base of your Grape endpoints
4
+ # Then add 'include Grape::ActiveModelSerializers' to enable the formatter and helpers
5
+ require 'active_model_serializers'
6
+ require 'grape/formatters/active_model_serializers'
7
+ require 'grape/helpers/active_model_serializers'
8
+
9
+ module Grape
10
+ module ActiveModelSerializers
11
+ extend ActiveSupport::Concern
12
+
13
+ included do
14
+ formatter :json, Grape::Formatters::ActiveModelSerializers
15
+ helpers Grape::Helpers::ActiveModelSerializers
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Grape response formatter that can be used as 'formatter :json, Grape::Formatters::ActiveModelSerializers'
4
+ #
5
+ # Serializer options can be passed as a hash from your Grape endpoint using env[:active_model_serializer_options],
6
+ # or better yet user the render helper in Grape::Helpers::ActiveModelSerializers
7
+
8
+ require 'active_model_serializers/serialization_context'
9
+
10
+ module Grape
11
+ module Formatters
12
+ module ActiveModelSerializers
13
+ def self.call(resource, env)
14
+ serializer_options = build_serializer_options(env)
15
+ ::ActiveModelSerializers::SerializableResource.new(resource, serializer_options).to_json
16
+ end
17
+
18
+ def self.build_serializer_options(env)
19
+ ams_options = env[:active_model_serializer_options] || {}
20
+
21
+ # Add serialization context
22
+ ams_options.fetch(:serialization_context) do
23
+ request = env['grape.request']
24
+ ams_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
25
+ request_url: request.url[/\A[^?]+/],
26
+ query_parameters: request.params
27
+ )
28
+ end
29
+
30
+ ams_options
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Helpers can be included in your Grape endpoint as: helpers Grape::Helpers::ActiveModelSerializers
4
+
5
+ module Grape
6
+ module Helpers
7
+ module ActiveModelSerializers
8
+ # A convenience method for passing ActiveModelSerializers serializer options
9
+ #
10
+ # Example: To include relationships in the response: render(post, include: ['comments'])
11
+ #
12
+ # Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
13
+ def render(resource, active_model_serializer_options = {})
14
+ env[:active_model_serializer_options] = active_model_serializer_options
15
+ resource
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'rubocop'
5
+ require 'rubocop/rake_task'
6
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
7
+ else
8
+ require 'rbconfig'
9
+ # https://github.com/bundler/bundler/blob/1b3eb2465a/lib/bundler/constants.rb#L2
10
+ windows_platforms = /(msdos|mswin|djgpp|mingw)/
11
+ if RbConfig::CONFIG['host_os'] =~ windows_platforms
12
+ desc 'No-op rubocop on Windows-- unsupported platform'
13
+ task :rubocop do
14
+ puts 'Skipping rubocop on Windows'
15
+ end
16
+ elsif defined?(::Rubinius)
17
+ desc 'No-op rubocop to avoid rbx segfault'
18
+ task :rubocop do
19
+ puts 'Skipping rubocop on rbx due to segfault'
20
+ puts 'https://github.com/rubinius/rubinius/issues/3499'
21
+ end
22
+ else
23
+ Rake::Task[:rubocop].clear if Rake::Task.task_defined?(:rubocop)
24
+ patterns = [
25
+ 'Gemfile',
26
+ 'Rakefile',
27
+ 'lib/**/*.{rb,rake}',
28
+ 'config/**/*.rb',
29
+ 'app/**/*.rb',
30
+ 'test/**/*.rb'
31
+ ]
32
+ desc 'Execute rubocop'
33
+ RuboCop::RakeTask.new(:rubocop) do |task|
34
+ task.options = ['--rails', '--display-cop-names', '--display-style-guide']
35
+ task.formatters = ['progress']
36
+ task.patterns = patterns
37
+ task.fail_on_error = true
38
+ end
39
+
40
+ namespace :rubocop do
41
+ desc 'Auto-gen rubocop config'
42
+ task :auto_gen_config do
43
+ options = ['--auto-gen-config'].concat patterns
44
+ require 'benchmark'
45
+ result = 0
46
+ cli = RuboCop::CLI.new
47
+ time = Benchmark.realtime do
48
+ result = cli.run(options)
49
+ end
50
+ puts "Finished in #{time} seconds" if cli.options[:debug]
51
+ abort('RuboCop failed!') if result.nonzero?
52
+ end
53
+ end
54
+ end
55
+ end