active_model_serializers 0.8.3 → 0.10.0.rc2

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +18 -20
  4. data/CHANGELOG.md +8 -67
  5. data/CONTRIBUTING.md +31 -0
  6. data/Gemfile +14 -1
  7. data/{MIT-LICENSE.txt → LICENSE.txt} +3 -2
  8. data/README.md +169 -495
  9. data/Rakefile +6 -12
  10. data/active_model_serializers.gemspec +21 -19
  11. data/lib/action_controller/serialization.rb +36 -27
  12. data/lib/active_model/serializer/adapter/flatten_json.rb +12 -0
  13. data/lib/active_model/serializer/adapter/fragment_cache.rb +78 -0
  14. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +15 -0
  15. data/lib/active_model/serializer/adapter/json.rb +50 -0
  16. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +23 -0
  17. data/lib/active_model/serializer/adapter/json_api.rb +156 -0
  18. data/lib/active_model/serializer/adapter/null.rb +11 -0
  19. data/lib/active_model/serializer/adapter.rb +96 -0
  20. data/lib/active_model/serializer/array_serializer.rb +35 -0
  21. data/lib/active_model/serializer/configuration.rb +13 -0
  22. data/lib/active_model/serializer/fieldset.rb +40 -0
  23. data/lib/active_model/serializer/railtie.rb +8 -0
  24. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  25. data/lib/active_model/serializer.rb +177 -440
  26. data/lib/active_model_serializers.rb +10 -86
  27. data/lib/generators/serializer/USAGE +0 -3
  28. data/lib/generators/serializer/resource_override.rb +12 -0
  29. data/lib/generators/serializer/serializer_generator.rb +1 -6
  30. data/lib/generators/serializer/templates/serializer.rb +2 -13
  31. data/test/action_controller/adapter_selector_test.rb +53 -0
  32. data/test/action_controller/explicit_serializer_test.rb +134 -0
  33. data/test/action_controller/json_api_linked_test.rb +179 -0
  34. data/test/action_controller/rescue_from_test.rb +32 -0
  35. data/test/{serialization_scope_name_test.rb → action_controller/serialization_scope_name_test.rb} +7 -11
  36. data/test/action_controller/serialization_test.rb +383 -0
  37. data/test/adapter/fragment_cache_test.rb +27 -0
  38. data/test/adapter/json/belongs_to_test.rb +48 -0
  39. data/test/adapter/json/collection_test.rb +73 -0
  40. data/test/adapter/json/has_many_test.rb +36 -0
  41. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  42. data/test/adapter/json_api/collection_test.rb +96 -0
  43. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  44. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  45. data/test/adapter/json_api/has_many_test.rb +110 -0
  46. data/test/adapter/json_api/has_one_test.rb +61 -0
  47. data/test/adapter/json_api/linked_test.rb +283 -0
  48. data/test/adapter/json_test.rb +34 -0
  49. data/test/adapter/null_test.rb +25 -0
  50. data/test/adapter_test.rb +43 -0
  51. data/test/array_serializer_test.rb +31 -63
  52. data/test/fixtures/poro.rb +230 -0
  53. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  54. data/test/{generators_test.rb → generators/serializer_generator_test.rb} +2 -36
  55. data/test/serializers/adapter_for_test.rb +50 -0
  56. data/test/serializers/associations_test.rb +127 -0
  57. data/test/serializers/attribute_test.rb +38 -0
  58. data/test/serializers/attributes_test.rb +63 -0
  59. data/test/serializers/cache_test.rb +138 -0
  60. data/test/serializers/configuration_test.rb +15 -0
  61. data/test/serializers/fieldset_test.rb +26 -0
  62. data/test/serializers/meta_test.rb +107 -0
  63. data/test/serializers/options_test.rb +21 -0
  64. data/test/serializers/serializer_for_test.rb +65 -0
  65. data/test/serializers/urls_test.rb +26 -0
  66. data/test/test_helper.rb +28 -16
  67. metadata +109 -43
  68. data/DESIGN.textile +0 -586
  69. data/Gemfile.edge +0 -9
  70. data/bench/perf.rb +0 -43
  71. data/cruft.md +0 -19
  72. data/lib/active_model/array_serializer.rb +0 -104
  73. data/lib/active_model/serializer/associations.rb +0 -233
  74. data/lib/active_record/serializer_override.rb +0 -16
  75. data/lib/generators/resource_override.rb +0 -13
  76. data/test/association_test.rb +0 -592
  77. data/test/caching_test.rb +0 -96
  78. data/test/no_serialization_scope_test.rb +0 -34
  79. data/test/serialization_test.rb +0 -392
  80. data/test/serializer_support_test.rb +0 -51
  81. data/test/serializer_test.rb +0 -1465
  82. data/test/test_fakes.rb +0 -217
@@ -0,0 +1,138 @@
1
+ require 'test_helper'
2
+ module ActiveModel
3
+ class Serializer
4
+ class CacheTest < Minitest::Test
5
+ def setup
6
+ ActionController::Base.cache_store.clear
7
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
8
+ @post = Post.new(title: 'New Post', body: 'Body')
9
+ @bio = Bio.new(id: 1, content: 'AMS Contributor')
10
+ @author = Author.new(name: 'Joao M. D. Moura')
11
+ @blog = Blog.new(id: 999, name: "Custom blog", writer: @author, articles: [])
12
+ @role = Role.new(name: 'Great Author')
13
+ @location = Location.new(lat: '-23.550520', lng: '-46.633309')
14
+ @place = Place.new(name: 'Amazing Place')
15
+ @author.posts = [@post]
16
+ @author.roles = [@role]
17
+ @role.author = @author
18
+ @author.bio = @bio
19
+ @bio.author = @author
20
+ @post.comments = [@comment]
21
+ @post.author = @author
22
+ @comment.post = @post
23
+ @comment.author = @author
24
+ @post.blog = @blog
25
+ @location.place = @place
26
+
27
+ @location_serializer = LocationSerializer.new(@location)
28
+ @bio_serializer = BioSerializer.new(@bio)
29
+ @role_serializer = RoleSerializer.new(@role)
30
+ @post_serializer = PostSerializer.new(@post)
31
+ @author_serializer = AuthorSerializer.new(@author)
32
+ @comment_serializer = CommentSerializer.new(@comment)
33
+ @blog_serializer = BlogSerializer.new(@blog)
34
+ end
35
+
36
+ def test_cache_definition
37
+ assert_equal(ActionController::Base.cache_store, @post_serializer.class._cache)
38
+ assert_equal(ActionController::Base.cache_store, @author_serializer.class._cache)
39
+ assert_equal(ActionController::Base.cache_store, @comment_serializer.class._cache)
40
+ end
41
+
42
+ def test_cache_key_definition
43
+ assert_equal('post', @post_serializer.class._cache_key)
44
+ assert_equal('writer', @author_serializer.class._cache_key)
45
+ assert_equal(nil, @comment_serializer.class._cache_key)
46
+ end
47
+
48
+ def test_cache_key_interpolation_with_updated_at
49
+ author = render_object_with_cache(@author)
50
+ assert_equal(nil, ActionController::Base.cache_store.fetch(@author.cache_key))
51
+ assert_equal(@author_serializer.attributes.to_json, ActionController::Base.cache_store.fetch("#{@author_serializer.class._cache_key}/#{@author_serializer.object.id}-#{@author_serializer.object.updated_at}").to_json)
52
+ end
53
+
54
+ def test_default_cache_key_fallback
55
+ comment = render_object_with_cache(@comment)
56
+ assert_equal(@comment_serializer.attributes.to_json, ActionController::Base.cache_store.fetch(@comment.cache_key).to_json)
57
+ end
58
+
59
+ def test_cache_options_definition
60
+ assert_equal({expires_in: 0.1, skip_digest: true}, @post_serializer.class._cache_options)
61
+ assert_equal(nil, @blog_serializer.class._cache_options)
62
+ assert_equal({expires_in: 1.day, skip_digest: true}, @comment_serializer.class._cache_options)
63
+ end
64
+
65
+ def test_fragment_cache_definition
66
+ assert_equal([:name], @role_serializer.class._cache_only)
67
+ assert_equal([:content], @bio_serializer.class._cache_except)
68
+ end
69
+
70
+ def test_associations_separately_cache
71
+ ActionController::Base.cache_store.clear
72
+ assert_equal(nil, ActionController::Base.cache_store.fetch(@post.cache_key))
73
+ assert_equal(nil, ActionController::Base.cache_store.fetch(@comment.cache_key))
74
+
75
+ post = render_object_with_cache(@post)
76
+
77
+ assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
78
+ assert_equal(@comment_serializer.attributes, ActionController::Base.cache_store.fetch(@comment.cache_key))
79
+ end
80
+
81
+ def test_associations_cache_when_updated
82
+ # Clean the Cache
83
+ ActionController::Base.cache_store.clear
84
+
85
+ # Generate a new Cache of Post object and each objects related to it.
86
+ render_object_with_cache(@post)
87
+
88
+ # Check if if cache the objects separately
89
+ assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
90
+ assert_equal(@comment_serializer.attributes, ActionController::Base.cache_store.fetch(@comment.cache_key))
91
+
92
+ # Simulating update on comments relationship with Post
93
+ new_comment = Comment.new(id: 2, body: 'ZOMG A NEW COMMENT')
94
+ new_comment_serializer = CommentSerializer.new(new_comment)
95
+ @post.comments = [new_comment]
96
+
97
+ # Ask for the serialized object
98
+ render_object_with_cache(@post)
99
+
100
+ # Check if the the new comment was cached
101
+ assert_equal(new_comment_serializer.attributes, ActionController::Base.cache_store.fetch(new_comment.cache_key))
102
+ assert_equal(@post_serializer.attributes, ActionController::Base.cache_store.fetch(@post.cache_key))
103
+ end
104
+
105
+ def test_fragment_fetch_with_virtual_associations
106
+ expected_result = {
107
+ id: @location.id,
108
+ lat: @location.lat,
109
+ lng: @location.lng,
110
+ place: 'Nowhere'
111
+ }
112
+
113
+ hash = render_object_with_cache(@location)
114
+
115
+ assert_equal(hash, expected_result)
116
+ assert_equal({place: 'Nowhere'}, ActionController::Base.cache_store.fetch(@location.cache_key))
117
+ end
118
+
119
+ def test_uses_file_digest_in_cahe_key
120
+ blog = render_object_with_cache(@blog)
121
+ assert_equal(@blog_serializer.attributes, ActionController::Base.cache_store.fetch(@blog.cache_key_with_digest))
122
+ end
123
+
124
+ def _cache_digest_definition
125
+ assert_equal(::Model::FILE_DIGEST, @post_serializer.class._cache_digest)
126
+ end
127
+
128
+ private
129
+ def render_object_with_cache(obj)
130
+ serializer_class = ActiveModel::Serializer.serializer_for(obj)
131
+ serializer = serializer_class.new(obj)
132
+ adapter = ActiveModel::Serializer.adapter.new(serializer)
133
+ adapter.serializable_hash
134
+ end
135
+ end
136
+ end
137
+ end
138
+
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class ConfigurationTest < Minitest::Test
6
+ def test_array_serializer
7
+ assert_equal ActiveModel::Serializer::ArraySerializer, ActiveModel::Serializer.config.array_serializer
8
+ end
9
+
10
+ def test_default_adapter
11
+ assert_equal :flatten_json, ActiveModel::Serializer.config.adapter
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class FieldsetTest < Minitest::Test
6
+
7
+ def test_fieldset_with_hash
8
+ fieldset = ActiveModel::Serializer::Fieldset.new({'post' => ['id', 'title'], 'coment' => ['body']})
9
+
10
+ assert_equal(
11
+ {:post=>[:id, :title], :coment=>[:body]},
12
+ fieldset.fields
13
+ )
14
+ end
15
+
16
+ def test_fieldset_with_array_of_fields_and_root_name
17
+ fieldset = ActiveModel::Serializer::Fieldset.new(['title'], 'post')
18
+
19
+ assert_equal(
20
+ {:post => [:title]},
21
+ fieldset.fields
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class MetaTest < Minitest::Test
6
+ def setup
7
+ ActionController::Base.cache_store.clear
8
+ @blog = Blog.new(id: 1,
9
+ name: 'AMS Hints',
10
+ writer: Author.new(id: 2, name: "Steve"),
11
+ articles: [Post.new(id: 3, title: "AMS")])
12
+ end
13
+
14
+ def test_meta_is_present_with_root
15
+ serializer = AlternateBlogSerializer.new(@blog, meta: {total: 10})
16
+ adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
17
+ expected = {
18
+ alternate_blog: {
19
+ id: 1,
20
+ title: "AMS Hints"
21
+ },
22
+ "meta" => {
23
+ total: 10
24
+ }
25
+ }
26
+ assert_equal expected, adapter.as_json
27
+ end
28
+
29
+ def test_meta_is_not_included_when_root_is_missing
30
+ adapter = load_adapter(meta: {total: 10})
31
+ expected = {
32
+ id: 1,
33
+ title: "AMS Hints"
34
+ }
35
+ assert_equal expected, adapter.as_json
36
+ end
37
+
38
+ def test_meta_key_is_used
39
+ serializer = AlternateBlogSerializer.new(@blog, root: 'blog', meta: {total: 10}, meta_key: "haha_meta")
40
+ adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
41
+ expected = {
42
+ alternate_blog: {
43
+ id: 1,
44
+ title: "AMS Hints"
45
+ },
46
+ "haha_meta" => {
47
+ total: 10
48
+ }
49
+ }
50
+ assert_equal expected, adapter.as_json
51
+ end
52
+
53
+ def test_meta_is_not_present_on_arrays_without_root
54
+ serializer = ArraySerializer.new([@blog], meta: {total: 10})
55
+ adapter = ActiveModel::Serializer::Adapter::FlattenJson.new(serializer)
56
+ expected = [{
57
+ id: 1,
58
+ name: "AMS Hints",
59
+ writer: {
60
+ id: 2,
61
+ name: "Steve"
62
+ },
63
+ articles: [{
64
+ id: 3,
65
+ title: "AMS",
66
+ body: nil
67
+ }]
68
+ }]
69
+ assert_equal expected, adapter.as_json
70
+ end
71
+
72
+ def test_meta_is_present_on_arrays_with_root
73
+ serializer = ArraySerializer.new([@blog], meta: {total: 10}, meta_key: "haha_meta")
74
+ adapter = ActiveModel::Serializer::Adapter::Json.new(serializer, root: 'blog')
75
+ expected = {
76
+ blogs: [{
77
+ id: 1,
78
+ name: "AMS Hints",
79
+ writer: {
80
+ id: 2,
81
+ name: "Steve"
82
+ },
83
+ articles: [{
84
+ id: 3,
85
+ title: "AMS",
86
+ body: nil
87
+ }]
88
+ }],
89
+ 'haha_meta' => {
90
+ total: 10
91
+ }
92
+ }
93
+ assert_equal expected, adapter.as_json
94
+ end
95
+
96
+ private
97
+
98
+ def load_adapter(options)
99
+ adapter_opts, serializer_opts =
100
+ options.partition { |k, _| ActionController::Serialization::ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
101
+
102
+ serializer = AlternateBlogSerializer.new(@blog, serializer_opts)
103
+ ActiveModel::Serializer::Adapter::FlattenJson.new(serializer, adapter_opts)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class OptionsTest < Minitest::Test
6
+ def setup
7
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1')
8
+ end
9
+
10
+ def test_options_are_accessible
11
+ @profile_serializer = ProfileSerializer.new(@profile, my_options: :accessible)
12
+ assert @profile_serializer.arguments_passed_in?
13
+ end
14
+
15
+ def test_no_option_is_passed_in
16
+ @profile_serializer = ProfileSerializer.new(@profile)
17
+ refute @profile_serializer.arguments_passed_in?
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,65 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class SerializerForTest < Minitest::Test
6
+ class ArraySerializerTest < Minitest::Test
7
+ def setup
8
+ @array = [1, 2, 3]
9
+ @previous_array_serializer = ActiveModel::Serializer.config.array_serializer
10
+ end
11
+
12
+ def teardown
13
+ ActiveModel::Serializer.config.array_serializer = @previous_array_serializer
14
+ end
15
+
16
+ def test_serializer_for_array
17
+ serializer = ActiveModel::Serializer.serializer_for(@array)
18
+ assert_equal ActiveModel::Serializer.config.array_serializer, serializer
19
+ end
20
+
21
+ def test_overwritten_serializer_for_array
22
+ new_array_serializer = Class.new
23
+ ActiveModel::Serializer.config.array_serializer = new_array_serializer
24
+ serializer = ActiveModel::Serializer.serializer_for(@array)
25
+ assert_equal new_array_serializer, serializer
26
+ end
27
+ end
28
+
29
+ class SerializerTest < Minitest::Test
30
+ class MyProfile < Profile
31
+ end
32
+ class CustomProfile
33
+ def serializer_class; ProfileSerializer; end
34
+ end
35
+
36
+ def setup
37
+ @profile = Profile.new
38
+ @my_profile = MyProfile.new
39
+ @custom_profile = CustomProfile.new
40
+ @model = ::Model.new
41
+ end
42
+
43
+ def test_serializer_for_existing_serializer
44
+ serializer = ActiveModel::Serializer.serializer_for(@profile)
45
+ assert_equal ProfileSerializer, serializer
46
+ end
47
+
48
+ def test_serializer_for_not_existing_serializer
49
+ serializer = ActiveModel::Serializer.serializer_for(@model)
50
+ assert_equal nil, serializer
51
+ end
52
+
53
+ def test_serializer_inherited_serializer
54
+ serializer = ActiveModel::Serializer.serializer_for(@my_profile)
55
+ assert_equal ProfileSerializer, serializer
56
+ end
57
+
58
+ def test_serializer_custom_serializer
59
+ serializer = ActiveModel::Serializer.serializer_for(@custom_profile)
60
+ assert_equal ProfileSerializer, serializer
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ class UrlsTest < Minitest::Test
6
+
7
+ def setup
8
+ @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ @post = Post.new({ title: 'New Post', body: 'Body' })
10
+ @comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
11
+ @post.comments = [@comment]
12
+
13
+ @profile_serializer = ProfileSerializer.new(@profile)
14
+ @post_serializer = PostSerializer.new(@post)
15
+ end
16
+
17
+ def test_urls_definition
18
+ assert_equal([:posts, :comments], @profile_serializer.class._urls)
19
+ end
20
+
21
+ def test_url_definition
22
+ assert_equal([:comments], @post_serializer.class._urls)
23
+ end
24
+ end
25
+ end
26
+ end
data/test/test_helper.rb CHANGED
@@ -1,32 +1,44 @@
1
- require "rubygems"
2
- require "bundler/setup"
1
+ require 'bundler/setup'
3
2
 
4
- require "pry"
3
+ require 'rails'
4
+ require 'action_controller'
5
+ require 'action_controller/test_case'
6
+ require 'action_controller/railtie'
7
+ require 'active_support/json'
8
+ require 'minitest/autorun'
9
+ require 'fileutils'
10
+ # Ensure backward compatibility with Minitest 4
11
+ Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
5
12
 
6
- require "active_model_serializers"
7
- require "active_support/json"
8
- require "minitest/autorun"
13
+ require 'active_model_serializers'
9
14
 
10
- require 'rails'
15
+ class Foo < Rails::Application
16
+ if Rails::VERSION::MAJOR >= 4
17
+ config.eager_load = false
18
+ config.secret_key_base = 'abc123'
19
+ config.action_controller.perform_caching = true
20
+ config.active_support.test_order = :random
21
+ config.logger = Logger.new(nil)
22
+ ActionController::Base.cache_store = :memory_store
23
+ end
24
+ end
25
+ FileUtils.mkdir_p(File.expand_path('../../tmp/cache', __FILE__))
26
+ Foo.initialize!
27
+
28
+ require 'fixtures/poro'
11
29
 
12
30
  module TestHelper
13
31
  Routes = ActionDispatch::Routing::RouteSet.new
14
32
  Routes.draw do
15
- resource :hypermedia
16
33
  get ':controller(/:action(/:id))'
17
34
  get ':controller(/:action)'
18
35
  end
19
36
 
20
37
  ActionController::Base.send :include, Routes.url_helpers
21
- ActiveModel::Serializer.send :include, Routes.url_helpers
22
38
  end
23
39
 
24
- ActiveSupport::TestCase.class_eval do
25
- setup do
26
- @routes = ::TestHelper::Routes
40
+ ActionController::TestCase.class_eval do
41
+ def setup
42
+ @routes = TestHelper::Routes
27
43
  end
28
44
  end
29
-
30
- class Object
31
- undef_method :id if respond_to?(:id)
32
- end