gpi-active_model_serializers 0.8.2

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.
@@ -0,0 +1,191 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ class Association #:nodoc:
4
+ # name: The name of the association.
5
+ #
6
+ # options: A hash. These keys are accepted:
7
+ #
8
+ # value: The object we're associating with.
9
+ #
10
+ # serializer: The class used to serialize the association.
11
+ #
12
+ # embed: Define how associations should be embedded.
13
+ # - :objects # Embed associations as full objects.
14
+ # - :ids # Embed only the association ids.
15
+ # - :ids, include: true # Embed the association ids and include objects in the root.
16
+ #
17
+ # include: Used in conjunction with embed :ids. Includes the objects in the root.
18
+ #
19
+ # root: Used in conjunction with include: true. Defines the key used to embed the objects.
20
+ #
21
+ # key: Key name used to store the ids in.
22
+ #
23
+ # embed_key: Method used to fetch ids. Defaults to :id.
24
+ #
25
+ # polymorphic: Is the association is polymorphic?. Values: true or false.
26
+ def initialize(name, options={}, serializer_options={})
27
+ @name = name
28
+ @object = options[:value]
29
+
30
+ embed = options[:embed]
31
+ @embed_ids = embed == :id || embed == :ids
32
+ @embed_objects = embed == :object || embed == :objects
33
+ @embed_key = options[:embed_key] || :id
34
+ @embed_in_root = options[:include]
35
+
36
+ serializer = options[:serializer]
37
+ @serializer_class = serializer.is_a?(String) ? serializer.constantize : serializer
38
+
39
+ @options = options
40
+ @serializer_options = serializer_options
41
+ end
42
+
43
+ attr_reader :object, :root, :name, :embed_ids, :embed_objects, :embed_in_root
44
+ alias embeddable? object
45
+ alias embed_objects? embed_objects
46
+ alias embed_ids? embed_ids
47
+ alias use_id_key? embed_ids?
48
+ alias embed_in_root? embed_in_root
49
+
50
+ def key
51
+ if key = options[:key]
52
+ key
53
+ elsif use_id_key?
54
+ id_key
55
+ else
56
+ name
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :embed_key, :serializer_class, :options, :serializer_options
63
+
64
+ def find_serializable(object)
65
+ if serializer_class
66
+ serializer_class.new(object, serializer_options)
67
+ elsif object.respond_to?(:active_model_serializer) && (ams = object.active_model_serializer)
68
+ options = serializer_options.except(:only, :include)
69
+
70
+ if serializer_options.key?(:include) && serializer_options[:include].include?(name)
71
+ options.merge!(serializer_options[:include][name])
72
+ end
73
+
74
+ ams.new(object, options)
75
+ else
76
+ object
77
+ end
78
+ end
79
+
80
+ class HasMany < Association #:nodoc:
81
+ def root
82
+ options[:root] || name
83
+ end
84
+
85
+ def id_key
86
+ "#{name.to_s.singularize}_ids".to_sym
87
+ end
88
+
89
+ def serializables
90
+ object.map do |item|
91
+ find_serializable(item)
92
+ end
93
+ end
94
+
95
+ def serialize
96
+ object.map do |item|
97
+ find_serializable(item).serializable_hash
98
+ end
99
+ end
100
+
101
+ def serialize_ids
102
+ object.map do |item|
103
+ serializer = find_serializable(item)
104
+ if serializer.respond_to?(embed_key)
105
+ serializer.send(embed_key)
106
+ else
107
+ item.read_attribute_for_serialization(embed_key)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ class HasOne < Association #:nodoc:
114
+ def initialize(name, options={}, serializer_options={})
115
+ super
116
+ @polymorphic = options[:polymorphic]
117
+ end
118
+
119
+ def root
120
+ if root = options[:root]
121
+ root
122
+ elsif polymorphic?
123
+ object.class.to_s.pluralize.demodulize.underscore.to_sym
124
+ else
125
+ name.to_s.pluralize.to_sym
126
+ end
127
+ end
128
+
129
+ def id_key
130
+ "#{name}_id".to_sym
131
+ end
132
+
133
+ def embeddable?
134
+ super || !polymorphic?
135
+ end
136
+
137
+ def serializables
138
+ value = object && find_serializable(object)
139
+ value ? [value] : []
140
+ end
141
+
142
+ def serialize
143
+ if object
144
+ if polymorphic?
145
+ {
146
+ :type => polymorphic_key,
147
+ polymorphic_key => find_serializable(object).serializable_hash
148
+ }
149
+ else
150
+ find_serializable(object).serializable_hash
151
+ end
152
+ end
153
+ end
154
+
155
+ def serialize_ids
156
+ if object
157
+ serializer = find_serializable(object)
158
+ id =
159
+ if serializer.respond_to?(embed_key)
160
+ serializer.send(embed_key)
161
+ else
162
+ object.read_attribute_for_serialization(embed_key)
163
+ end
164
+
165
+ if polymorphic?
166
+ {
167
+ type: polymorphic_key,
168
+ id: id
169
+ }
170
+ else
171
+ id
172
+ end
173
+ end
174
+ end
175
+
176
+ private
177
+
178
+ attr_reader :polymorphic
179
+ alias polymorphic? polymorphic
180
+
181
+ def use_id_key?
182
+ embed_ids? && !polymorphic?
183
+ end
184
+
185
+ def polymorphic_key
186
+ object.class.to_s.demodulize.underscore.to_sym
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,37 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ module Caching
4
+ def to_json(*args)
5
+ if caching_enabled?
6
+ key = expand_cache_key([self.class.to_s.underscore, cache_key, 'to-json'])
7
+ cache.fetch key do
8
+ super
9
+ end
10
+ else
11
+ super
12
+ end
13
+ end
14
+
15
+ def serialize(*args)
16
+ if caching_enabled?
17
+ key = expand_cache_key([self.class.to_s.underscore, cache_key, 'serialize'])
18
+ cache.fetch key do
19
+ serialize_object
20
+ end
21
+ else
22
+ serialize_object
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def caching_enabled?
29
+ perform_caching && cache && respond_to?(:cache_key)
30
+ end
31
+
32
+ def expand_cache_key(*args)
33
+ ActiveSupport::Cache.expand_cache_key(args)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ VERSION = "0.8.2"
4
+ end
5
+ end
@@ -0,0 +1,95 @@
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
+ Rails::Generators.configure!(app.config.generators)
15
+ Rails::Generators.hidden_namespaces.uniq!
16
+ require_relative "generators/resource_override"
17
+ end
18
+
19
+ initializer "include_routes.active_model_serializer" do |app|
20
+ ActiveSupport.on_load(:active_model_serializers) do
21
+ include AbstractController::UrlFor
22
+ extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
23
+ include app.routes.mounted_helpers
24
+ end
25
+ end
26
+
27
+ initializer "caching.active_model_serializer" do |app|
28
+ ActiveModel::Serializer.perform_caching = app.config.action_controller.perform_caching
29
+ ActiveModel::ArraySerializer.perform_caching = app.config.action_controller.perform_caching
30
+
31
+ ActiveModel::Serializer.cache = Rails.cache
32
+ ActiveModel::ArraySerializer.cache = Rails.cache
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ module ActiveModel::SerializerSupport
39
+ extend ActiveSupport::Concern
40
+
41
+ module ClassMethods #:nodoc:
42
+ if "".respond_to?(:safe_constantize)
43
+ def active_model_serializer
44
+ "#{self.name}Serializer".safe_constantize
45
+ end
46
+ else
47
+ def active_model_serializer
48
+ begin
49
+ "#{self.name}Serializer".constantize
50
+ rescue NameError => e
51
+ raise unless e.message =~ /uninitialized constant/
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ # Returns a model serializer for this object considering its namespace.
58
+ def active_model_serializer
59
+ self.class.active_model_serializer
60
+ end
61
+
62
+ alias :read_attribute_for_serialization :send
63
+ end
64
+
65
+ module ActiveModel::ArraySerializerSupport
66
+ def active_model_serializer
67
+ ActiveModel::ArraySerializer
68
+ end
69
+ end
70
+
71
+ Array.send(:include, ActiveModel::ArraySerializerSupport)
72
+ Set.send(:include, ActiveModel::ArraySerializerSupport)
73
+
74
+ {
75
+ active_record: 'ActiveRecord::Relation',
76
+ mongoid: 'Mongoid::Criteria'
77
+ }.each do |orm, rel_class|
78
+ ActiveSupport.on_load(orm) do
79
+ include ActiveModel::SerializerSupport
80
+ rel_class.constantize.send(:include, ActiveModel::ArraySerializerSupport)
81
+ end
82
+ end
83
+
84
+ begin
85
+ require 'action_controller'
86
+ require 'action_controller/serialization'
87
+
88
+ ActiveSupport.on_load(:action_controller) do
89
+ include ::ActionController::Serialization
90
+ end
91
+ rescue LoadError => ex
92
+ # rails on installed, continuing
93
+ end
94
+
95
+ ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)
@@ -0,0 +1,16 @@
1
+ # We do not recommend that you use AM::S in this way, but if you must, here
2
+ # is a mixin that overrides ActiveRecord::Base#to_json and #as_json.
3
+
4
+ module ActiveRecord
5
+ module SerializerOverride
6
+ def to_json options = {}
7
+ active_model_serializer.new(self).to_json options
8
+ end
9
+
10
+ def as_json options={}
11
+ active_model_serializer.new(self).as_json options
12
+ end
13
+ end
14
+
15
+ Base.send(:include, SerializerOverride)
16
+ end
@@ -0,0 +1,13 @@
1
+ require "rails/generators"
2
+ require "rails/generators/rails/resource/resource_generator"
3
+
4
+ module Rails
5
+ module Generators
6
+ ResourceGenerator.class_eval do
7
+ def add_serializer
8
+ invoke "serializer"
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,9 @@
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
@@ -0,0 +1,36 @@
1
+ module Rails
2
+ module Generators
3
+ class SerializerGenerator < NamedBase
4
+ source_root File.expand_path("../templates", __FILE__)
5
+ check_class_collision suffix: "Serializer"
6
+
7
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
8
+
9
+ class_option :parent, type: :string, desc: "The parent class for the generated serializer"
10
+
11
+ def create_serializer_file
12
+ template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
13
+ end
14
+
15
+ private
16
+
17
+ def attributes_names
18
+ [:id] + attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
19
+ end
20
+
21
+ def association_names
22
+ attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
23
+ end
24
+
25
+ def parent_class_name
26
+ if options[:parent]
27
+ options[:parent]
28
+ elsif defined?(::ApplicationSerializer)
29
+ "ApplicationSerializer"
30
+ else
31
+ "ActiveModel::Serializer"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ 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,85 @@
1
+ require "test_helper"
2
+ require "test_fakes"
3
+
4
+ class ArraySerializerTest < ActiveModel::TestCase
5
+ # serialize different typed objects
6
+ def test_array_serializer
7
+ model = Model.new
8
+ user = User.new
9
+ comments = Comment.new(title: "Comment1", id: 1)
10
+
11
+ array = [model, user, comments]
12
+ serializer = array.active_model_serializer.new(array, scope: { scope: true })
13
+ assert_equal([
14
+ { model: "Model" },
15
+ { last_name: "Valim", ok: true, first_name: "Jose", scope: true },
16
+ { title: "Comment1" }
17
+ ], serializer.as_json)
18
+ end
19
+
20
+ def test_array_serializer_with_root
21
+ comment1 = Comment.new(title: "Comment1", id: 1)
22
+ comment2 = Comment.new(title: "Comment2", id: 2)
23
+
24
+ array = [ comment1, comment2 ]
25
+
26
+ serializer = array.active_model_serializer.new(array, root: :comments)
27
+
28
+ assert_equal({ comments: [
29
+ { title: "Comment1" },
30
+ { title: "Comment2" }
31
+ ]}, serializer.as_json)
32
+ end
33
+
34
+ def test_active_model_with_root
35
+ comment1 = ModelWithActiveModelSerializer.new(title: "Comment1")
36
+ comment2 = ModelWithActiveModelSerializer.new(title: "Comment2")
37
+
38
+ array = [ comment1, comment2 ]
39
+
40
+ serializer = array.active_model_serializer.new(array, root: :comments)
41
+
42
+ assert_equal({ comments: [
43
+ { title: "Comment1" },
44
+ { title: "Comment2" }
45
+ ]}, serializer.as_json)
46
+ end
47
+
48
+ def test_array_serializer_with_hash
49
+ hash = { value: "something" }
50
+ array = [hash]
51
+ serializer = array.active_model_serializer.new(array, root: :items)
52
+ assert_equal({ items: [hash.as_json] }, serializer.as_json)
53
+ end
54
+
55
+ def test_array_serializer_with_specified_serializer
56
+ post1 = Post.new(title: "Post1", author: "Author1", id: 1)
57
+ post2 = Post.new(title: "Post2", author: "Author2", id: 2)
58
+
59
+ array = [ post1, post2 ]
60
+
61
+ serializer = array.active_model_serializer.new array, each_serializer: CustomPostSerializer
62
+
63
+ assert_equal([
64
+ { title: "Post1" },
65
+ { title: "Post2" }
66
+ ], serializer.as_json)
67
+ end
68
+
69
+ def test_array_serializer_using_default_serializer
70
+ hash = { "value" => "something" }
71
+ class << hash
72
+ def active_model_serializer
73
+ nil
74
+ end
75
+ end
76
+
77
+ array = [hash]
78
+
79
+ serializer = array.active_model_serializer.new array
80
+
81
+ assert_equal([
82
+ { "value" => "something" }
83
+ ], serializer.as_json)
84
+ end
85
+ end