gpi-active_model_serializers 0.8.2

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