active_model_serializers 0.8.4 → 0.9.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -45
  3. data/CONTRIBUTING.md +20 -0
  4. data/DESIGN.textile +4 -4
  5. data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
  6. data/README.md +187 -113
  7. data/lib/action_controller/serialization.rb +30 -16
  8. data/lib/active_model/array_serializer.rb +36 -82
  9. data/lib/active_model/default_serializer.rb +22 -0
  10. data/lib/active_model/serializable.rb +25 -0
  11. data/lib/active_model/serializer.rb +126 -447
  12. data/lib/active_model/serializer/associations.rb +53 -211
  13. data/lib/active_model/serializer/config.rb +31 -0
  14. data/lib/active_model/serializer/generators/resource_override.rb +13 -0
  15. data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
  16. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
  17. data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
  18. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
  19. data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
  20. data/lib/active_model/serializer/railtie.rb +10 -0
  21. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  22. data/lib/active_model/serializer_support.rb +5 -0
  23. data/lib/active_model_serializers.rb +7 -86
  24. data/test/coverage_setup.rb +15 -0
  25. data/test/fixtures/active_record.rb +92 -0
  26. data/test/fixtures/poro.rb +64 -0
  27. data/test/integration/action_controller/serialization_test.rb +234 -0
  28. data/test/integration/active_record/active_record_test.rb +77 -0
  29. data/test/integration/generators/resource_generator_test.rb +26 -0
  30. data/test/integration/generators/scaffold_controller_generator_test.rb +67 -0
  31. data/test/integration/generators/serializer_generator_test.rb +41 -0
  32. data/test/test_app.rb +11 -0
  33. data/test/test_helper.rb +7 -41
  34. data/test/tmp/app/serializers/account_serializer.rb +3 -0
  35. data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
  36. data/test/unit/active_model/array_serializer/root_test.rb +102 -0
  37. data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
  38. data/test/unit/active_model/array_serializer/serialization_test.rb +83 -0
  39. data/test/unit/active_model/default_serializer_test.rb +13 -0
  40. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
  41. data/test/unit/active_model/serializer/associations_test.rb +19 -0
  42. data/test/unit/active_model/serializer/attributes_test.rb +41 -0
  43. data/test/unit/active_model/serializer/config_test.rb +86 -0
  44. data/test/unit/active_model/serializer/filter_test.rb +49 -0
  45. data/test/unit/active_model/serializer/has_many_test.rb +173 -0
  46. data/test/unit/active_model/serializer/has_one_test.rb +151 -0
  47. data/test/unit/active_model/serializer/meta_test.rb +39 -0
  48. data/test/unit/active_model/serializer/root_test.rb +117 -0
  49. data/test/unit/active_model/serializer/scope_test.rb +49 -0
  50. metadata +78 -74
  51. data/.gitignore +0 -18
  52. data/.travis.yml +0 -34
  53. data/Gemfile +0 -38
  54. data/Rakefile +0 -22
  55. data/active_model_serializers.gemspec +0 -24
  56. data/appveyor.yml +0 -27
  57. data/bench/perf.rb +0 -43
  58. data/cruft.md +0 -19
  59. data/lib/active_record/serializer_override.rb +0 -16
  60. data/lib/generators/resource_override.rb +0 -13
  61. data/lib/generators/serializer/serializer_generator.rb +0 -42
  62. data/lib/generators/serializer/templates/serializer.rb +0 -19
  63. data/test/array_serializer_test.rb +0 -75
  64. data/test/association_test.rb +0 -592
  65. data/test/caching_test.rb +0 -177
  66. data/test/generators_test.rb +0 -85
  67. data/test/no_serialization_scope_test.rb +0 -34
  68. data/test/serialization_scope_name_test.rb +0 -67
  69. data/test/serialization_test.rb +0 -396
  70. data/test/serializer_support_test.rb +0 -51
  71. data/test/serializer_test.rb +0 -1466
  72. data/test/test_fakes.rb +0 -218
@@ -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,10 @@
1
+ module ActiveModel
2
+ class Railtie < Rails::Railtie
3
+ initializer 'generators' do |app|
4
+ app.load_generators
5
+ require 'active_model/serializer/generators/serializer/serializer_generator'
6
+ require 'active_model/serializer/generators/serializer/scaffold_controller_generator'
7
+ require 'active_model/serializer/generators/resource_override'
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveModel
2
2
  class Serializer
3
- VERSION = "0.8.4"
3
+ VERSION = '0.9.0.alpha1'
4
4
  end
5
5
  end
@@ -0,0 +1,5 @@
1
+ module ActiveModel
2
+ module SerializerSupport
3
+ alias read_attribute_for_serialization send
4
+ end
5
+ end
@@ -1,85 +1,8 @@
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 app.routes.url_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
1
+ require 'active_model'
2
+ require 'active_model/serializer'
3
+ require 'active_model/serializer_support'
4
+ require 'active_model/serializer/version'
5
+ require 'active_model/serializer/railtie' if defined?(Rails)
83
6
 
84
7
  begin
85
8
  require 'action_controller'
@@ -88,8 +11,6 @@ begin
88
11
  ActiveSupport.on_load(:action_controller) do
89
12
  include ::ActionController::Serialization
90
13
  end
91
- rescue LoadError => ex
92
- # rails on installed, continuing
14
+ rescue LoadError
15
+ # rails not installed, continuing
93
16
  end
94
-
95
- ActiveSupport.run_load_hooks(:active_model_serializers, ActiveModel::Serializer)
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'simplecov'
3
+ require 'coveralls'
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
6
+ SimpleCov::Formatter::HTMLFormatter,
7
+ Coveralls::SimpleCov::Formatter
8
+ ]
9
+
10
+ SimpleCov.start do
11
+ add_group "lib", "lib"
12
+ add_group "test", "test"
13
+ end
14
+ rescue LoadError
15
+ end
@@ -0,0 +1,92 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(
4
+ :adapter => 'sqlite3',
5
+ :database => ':memory:'
6
+ )
7
+
8
+ ActiveRecord::Schema.define do
9
+ create_table :ar_posts, force: true do |t|
10
+ t.string :title
11
+ t.text :body
12
+ t.belongs_to :ar_section, index: true
13
+ t.timestamps
14
+ end
15
+
16
+ create_table :ar_comments, force: true do |t|
17
+ t.text :body
18
+ t.belongs_to :ar_post, index: true
19
+ t.timestamps
20
+ end
21
+
22
+ create_table :ar_tags, force: true do |t|
23
+ t.string :name
24
+ end
25
+
26
+ create_table :ar_sections, force: true do |t|
27
+ t.string :name
28
+ end
29
+
30
+ create_table :ar_posts_tags, force: true do |t|
31
+ t.references :ar_post, :ar_tag, index: true
32
+ end
33
+
34
+ create_table :ar_comments_tags, force: true do |t|
35
+ t.references :ar_comment, :ar_tag, index: true
36
+ end
37
+ end
38
+
39
+ class ARPost < ActiveRecord::Base
40
+ has_many :ar_comments, class_name: 'ARComment'
41
+ has_and_belongs_to_many :ar_tags, class_name: 'ARTag', join_table: :ar_posts_tags
42
+ belongs_to :ar_section, class_name: 'ARSection'
43
+ end
44
+
45
+ class ARComment < ActiveRecord::Base
46
+ belongs_to :ar_post, class_name: 'ARPost'
47
+ has_and_belongs_to_many :ar_tags, class_name: 'ARTag', join_table: :ar_comments_tags
48
+ end
49
+
50
+ class ARTag < ActiveRecord::Base
51
+ end
52
+
53
+ class ARSection < ActiveRecord::Base
54
+ end
55
+
56
+ class ARPostSerializer < ActiveModel::Serializer
57
+ attributes :title, :body
58
+
59
+ has_many :ar_comments, :ar_tags
60
+ has_one :ar_section
61
+ end
62
+
63
+ class ARCommentSerializer < ActiveModel::Serializer
64
+ attributes :body
65
+
66
+ has_many :ar_tags
67
+ end
68
+
69
+ class ARTagSerializer < ActiveModel::Serializer
70
+ attributes :name
71
+ end
72
+
73
+ class ARSectionSerializer < ActiveModel::Serializer
74
+ attributes 'name'
75
+ end
76
+
77
+ ARPost.create(title: 'New post',
78
+ body: 'A body!!!',
79
+ ar_section: ARSection.create(name: 'ruby')).tap do |post|
80
+
81
+ short_tag = post.ar_tags.create(name: 'short')
82
+ whiny_tag = post.ar_tags.create(name: 'whiny')
83
+ happy_tag = ARTag.create(name: 'happy')
84
+
85
+ post.ar_comments.create(body: 'what a dumb post').tap do |comment|
86
+ comment.ar_tags.concat happy_tag, whiny_tag
87
+ end
88
+
89
+ post.ar_comments.create(body: 'i liked it').tap do |comment|
90
+ comment.ar_tags.concat happy_tag, short_tag
91
+ end
92
+ end
@@ -0,0 +1,64 @@
1
+ class Model
2
+ def initialize(hash={})
3
+ @attributes = hash
4
+ end
5
+
6
+ def read_attribute_for_serialization(name)
7
+ if name == :id || name == 'id'
8
+ object_id
9
+ else
10
+ @attributes[name]
11
+ end
12
+ end
13
+ end
14
+
15
+
16
+ ###
17
+ ## Models
18
+ ###
19
+ class User < Model
20
+ def profile
21
+ @profile ||= Profile.new(name: 'N1', description: 'D1')
22
+ end
23
+ end
24
+
25
+ class Profile < Model
26
+ end
27
+
28
+ class Post < Model
29
+ def comments
30
+ @comments ||= [Comment.new(content: 'C1'),
31
+ Comment.new(content: 'C2')]
32
+ end
33
+ end
34
+
35
+ class Comment < Model
36
+ end
37
+
38
+ ###
39
+ ## Serializers
40
+ ###
41
+ class UserSerializer < ActiveModel::Serializer
42
+ attributes :name, :email
43
+
44
+ has_one :profile
45
+ end
46
+
47
+ class ProfileSerializer < ActiveModel::Serializer
48
+ def description
49
+ description = object.read_attribute_for_serialization(:description)
50
+ scope ? "#{description} - #{scope}" : description
51
+ end
52
+
53
+ attributes :name, :description
54
+ end
55
+
56
+ class PostSerializer < ActiveModel::Serializer
57
+ attributes :title, :body
58
+
59
+ has_many :comments
60
+ end
61
+
62
+ class CommentSerializer < ActiveModel::Serializer
63
+ attributes :content
64
+ end
@@ -0,0 +1,234 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class ImplicitSerializerTest < ActionController::TestCase
6
+ class MyController < ActionController::Base
7
+ def render_using_implicit_serializer
8
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ end
10
+ end
11
+
12
+ tests MyController
13
+
14
+ def test_render_using_implicit_serializer
15
+ get :render_using_implicit_serializer
16
+ assert_equal 'application/json', @response.content_type
17
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1"}}', @response.body
18
+ end
19
+ end
20
+
21
+ class ImplicitSerializerScopeTest < ActionController::TestCase
22
+ class MyController < ActionController::Base
23
+ def render_using_implicit_serializer_and_scope
24
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
25
+ end
26
+
27
+ private
28
+
29
+ def current_user
30
+ 'current_user'
31
+ end
32
+ end
33
+
34
+ tests MyController
35
+
36
+ def test_render_using_implicit_serializer_and_scope
37
+ get :render_using_implicit_serializer_and_scope
38
+ assert_equal 'application/json', @response.content_type
39
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_user"}}', @response.body
40
+ end
41
+ end
42
+
43
+ class DefaultOptionsForSerializerScopeTest < ActionController::TestCase
44
+ class MyController < ActionController::Base
45
+ def default_serializer_options
46
+ { scope: current_admin }
47
+ end
48
+
49
+ def render_using_scope_set_in_default_serializer_options
50
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
51
+ end
52
+
53
+ private
54
+
55
+ def current_user
56
+ 'current_user'
57
+ end
58
+
59
+ def current_admin
60
+ 'current_admin'
61
+ end
62
+ end
63
+
64
+ tests MyController
65
+
66
+ def test_render_using_scope_set_in_default_serializer_options
67
+ get :render_using_scope_set_in_default_serializer_options
68
+ assert_equal 'application/json', @response.content_type
69
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
70
+ end
71
+ end
72
+
73
+ class ExplicitSerializerScopeTest < ActionController::TestCase
74
+ class MyController < ActionController::Base
75
+ def render_using_implicit_serializer_and_explicit_scope
76
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }), scope: current_admin
77
+ end
78
+
79
+ private
80
+
81
+ def current_user
82
+ 'current_user'
83
+ end
84
+
85
+ def current_admin
86
+ 'current_admin'
87
+ end
88
+ end
89
+
90
+ tests MyController
91
+
92
+ def test_render_using_implicit_serializer_and_explicit_scope
93
+ get :render_using_implicit_serializer_and_explicit_scope
94
+ assert_equal 'application/json', @response.content_type
95
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
96
+ end
97
+ end
98
+
99
+ class OverridingSerializationScopeTest < ActionController::TestCase
100
+ class MyController < ActionController::Base
101
+ def render_overriding_serialization_scope
102
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
103
+ end
104
+
105
+ private
106
+
107
+ def current_user
108
+ 'current_user'
109
+ end
110
+
111
+ def serialization_scope
112
+ 'current_admin'
113
+ end
114
+ end
115
+
116
+ tests MyController
117
+
118
+ def test_render_overriding_serialization_scope
119
+ get :render_overriding_serialization_scope
120
+ assert_equal 'application/json', @response.content_type
121
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_admin"}}', @response.body
122
+ end
123
+ end
124
+
125
+ class CallingSerializationScopeTest < ActionController::TestCase
126
+ class MyController < ActionController::Base
127
+ def render_calling_serialization_scope
128
+ render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
129
+ end
130
+
131
+ private
132
+
133
+ def current_user
134
+ 'current_user'
135
+ end
136
+
137
+ serialization_scope :current_user
138
+ end
139
+
140
+ tests MyController
141
+
142
+ def test_render_calling_serialization_scope
143
+ get :render_calling_serialization_scope
144
+ assert_equal 'application/json', @response.content_type
145
+ assert_equal '{"profile":{"name":"Name 1","description":"Description 1 - current_user"}}', @response.body
146
+ end
147
+ end
148
+
149
+ class JSONDumpSerializerTest < ActionController::TestCase
150
+ class MyController < ActionController::Base
151
+ def render_using_json_dump
152
+ render json: JSON.dump(hello: 'world')
153
+ end
154
+ end
155
+
156
+ tests MyController
157
+
158
+ def test_render_using_json_dump
159
+ get :render_using_json_dump
160
+ assert_equal 'application/json', @response.content_type
161
+ assert_equal '{"hello":"world"}', @response.body
162
+ end
163
+ end
164
+
165
+ class RailsSerializerTest < ActionController::TestCase
166
+ class MyController < ActionController::Base
167
+ def render_using_rails_behavior
168
+ render json: [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })], serializer: false
169
+ end
170
+ end
171
+
172
+ tests MyController
173
+
174
+ def test_render_using_rails_behavior
175
+ get :render_using_rails_behavior
176
+ assert_equal 'application/json', @response.content_type
177
+ assert_equal '[{"attributes":{"name":"Name 1","description":"Description 1","comments":"Comments 1"}}]', @response.body
178
+ end
179
+ end
180
+
181
+ class ArraySerializerTest < ActionController::TestCase
182
+ class MyController < ActionController::Base
183
+ def render_array
184
+ render json: [Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })]
185
+ end
186
+ end
187
+
188
+ tests MyController
189
+
190
+ def test_render_array
191
+ get :render_array
192
+ assert_equal 'application/json', @response.content_type
193
+ assert_equal '{"my":[{"name":"Name 1","description":"Description 1"}]}', @response.body
194
+ end
195
+ end
196
+
197
+ class ArrayEmbedingSerializerTest < ActionController::TestCase
198
+ def setup
199
+ super
200
+ @association = UserSerializer._associations[:profile]
201
+ @old_association = @association.dup
202
+ end
203
+
204
+ def teardown
205
+ super
206
+ UserSerializer._associations[:profile] = @old_association
207
+ end
208
+
209
+ class MyController < ActionController::Base
210
+ def initialize(*)
211
+ super
212
+ @user = User.new({ name: 'Name 1', email: 'mail@server.com', gender: 'M' })
213
+ end
214
+ attr_reader :user
215
+
216
+ def render_array_embeding_in_root
217
+ render json: [@user]
218
+ end
219
+ end
220
+
221
+ tests MyController
222
+
223
+ def test_render_array_embeding_in_root
224
+ @association.embed = :ids
225
+ @association.embed_in_root = true
226
+
227
+ get :render_array_embeding_in_root
228
+ assert_equal 'application/json', @response.content_type
229
+
230
+ assert_equal("{\"my\":[{\"name\":\"Name 1\",\"email\":\"mail@server.com\",\"profile_id\":#{@controller.user.profile.object_id}}],\"profiles\":[{\"name\":\"N1\",\"description\":\"D1\"}]}", @response.body)
231
+ end
232
+ end
233
+ end
234
+ end