active_model_serializers 0.8.3 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +104 -0
- data/.rubocop_todo.yml +167 -0
- data/.simplecov +110 -0
- data/.travis.yml +39 -24
- data/CHANGELOG.md +465 -6
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +50 -1
- data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
- data/README.md +102 -590
- data/Rakefile +93 -8
- data/active_model_serializers.gemspec +65 -23
- data/appveyor.yml +24 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/serve_benchmark +39 -0
- data/docs/ARCHITECTURE.md +126 -0
- data/docs/README.md +40 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +245 -0
- data/docs/general/caching.md +52 -0
- data/docs/general/configuration_options.md +100 -0
- data/docs/general/deserialization.md +100 -0
- data/docs/general/getting_started.md +133 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/key_transforms.md +40 -0
- data/docs/general/logging.md +14 -0
- data/docs/general/rendering.md +255 -0
- data/docs/general/serializers.md +372 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +139 -0
- data/docs/howto/add_root_key.md +51 -0
- data/docs/howto/outside_controller_use.md +58 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +32 -0
- data/docs/howto/test.md +152 -0
- data/docs/integrations/ember-and-json-api.md +112 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +31 -36
- data/lib/active_model/serializable_resource.rb +11 -0
- data/lib/active_model/serializer/adapter/attributes.rb +15 -0
- data/lib/active_model/serializer/adapter/base.rb +16 -0
- data/lib/active_model/serializer/adapter/json.rb +15 -0
- data/lib/active_model/serializer/adapter/json_api.rb +15 -0
- data/lib/active_model/serializer/adapter/null.rb +15 -0
- data/lib/active_model/serializer/adapter.rb +24 -0
- data/lib/active_model/serializer/array_serializer.rb +9 -0
- data/lib/active_model/serializer/association.rb +19 -0
- data/lib/active_model/serializer/associations.rb +87 -220
- data/lib/active_model/serializer/attribute.rb +25 -0
- data/lib/active_model/serializer/attributes.rb +82 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
- data/lib/active_model/serializer/caching.rb +333 -0
- data/lib/active_model/serializer/collection_reflection.rb +7 -0
- data/lib/active_model/serializer/collection_serializer.rb +64 -0
- data/lib/active_model/serializer/configuration.rb +35 -0
- data/lib/active_model/serializer/error_serializer.rb +10 -0
- data/lib/active_model/serializer/errors_serializer.rb +27 -0
- data/lib/active_model/serializer/field.rb +90 -0
- data/lib/active_model/serializer/fieldset.rb +31 -0
- data/lib/active_model/serializer/has_many_reflection.rb +10 -0
- data/lib/active_model/serializer/has_one_reflection.rb +10 -0
- data/lib/active_model/serializer/include_tree.rb +111 -0
- data/lib/active_model/serializer/links.rb +35 -0
- data/lib/active_model/serializer/lint.rb +146 -0
- data/lib/active_model/serializer/meta.rb +29 -0
- data/lib/active_model/serializer/null.rb +17 -0
- data/lib/active_model/serializer/reflection.rb +147 -0
- data/lib/active_model/serializer/singular_reflection.rb +7 -0
- data/lib/active_model/serializer/type.rb +25 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +158 -481
- data/lib/active_model_serializers/adapter/attributes.rb +76 -0
- data/lib/active_model_serializers/adapter/base.rb +83 -0
- data/lib/active_model_serializers/adapter/json.rb +21 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +62 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +37 -0
- data/lib/active_model_serializers/adapter/json_api.rb +516 -0
- data/lib/active_model_serializers/adapter/null.rb +9 -0
- data/lib/active_model_serializers/adapter.rb +92 -0
- data/lib/active_model_serializers/callbacks.rb +55 -0
- data/lib/active_model_serializers/deprecate.rb +55 -0
- data/lib/active_model_serializers/deserialization.rb +13 -0
- data/lib/active_model_serializers/json_pointer.rb +14 -0
- data/lib/active_model_serializers/key_transform.rb +70 -0
- data/lib/active_model_serializers/logging.rb +122 -0
- data/lib/active_model_serializers/model.rb +49 -0
- data/lib/active_model_serializers/railtie.rb +46 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +65 -0
- data/lib/active_model_serializers/serializable_resource.rb +81 -0
- data/lib/active_model_serializers/serialization_context.rb +32 -0
- data/lib/active_model_serializers/test/schema.rb +138 -0
- data/lib/active_model_serializers/test/serializer.rb +125 -0
- data/lib/active_model_serializers/test.rb +7 -0
- data/lib/active_model_serializers.rb +32 -89
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +10 -0
- data/lib/generators/rails/serializer_generator.rb +36 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +14 -0
- data/lib/grape/formatters/active_model_serializers.rb +15 -0
- data/lib/grape/helpers/active_model_serializers.rb +16 -0
- data/test/action_controller/adapter_selector_test.rb +53 -0
- data/test/action_controller/explicit_serializer_test.rb +134 -0
- data/test/action_controller/json/include_test.rb +167 -0
- data/test/action_controller/json_api/deserialization_test.rb +112 -0
- data/test/action_controller/json_api/errors_test.rb +41 -0
- data/test/action_controller/json_api/linked_test.rb +197 -0
- data/test/action_controller/json_api/pagination_test.rb +116 -0
- data/test/action_controller/json_api/transform_test.rb +181 -0
- data/test/action_controller/serialization_scope_name_test.rb +229 -0
- data/test/action_controller/serialization_test.rb +469 -0
- data/test/active_model_serializers/adapter_for_test.rb +208 -0
- data/test/active_model_serializers/json_pointer_test.rb +20 -0
- data/test/active_model_serializers/key_transform_test.rb +263 -0
- data/test/active_model_serializers/logging_test.rb +77 -0
- data/test/active_model_serializers/model_test.rb +9 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +58 -0
- data/test/active_model_serializers/test/schema_test.rb +130 -0
- data/test/active_model_serializers/test/serializer_test.rb +62 -0
- data/test/active_record_test.rb +9 -0
- data/test/adapter/deprecation_test.rb +100 -0
- data/test/adapter/json/belongs_to_test.rb +45 -0
- data/test/adapter/json/collection_test.rb +90 -0
- data/test/adapter/json/has_many_test.rb +45 -0
- data/test/adapter/json/transform_test.rb +93 -0
- data/test/adapter/json_api/belongs_to_test.rb +155 -0
- data/test/adapter/json_api/collection_test.rb +95 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +87 -0
- data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
- data/test/adapter/json_api/has_many_test.rb +144 -0
- data/test/adapter/json_api/has_one_test.rb +80 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +392 -0
- data/test/adapter/json_api/links_test.rb +93 -0
- data/test/adapter/json_api/pagination_links_test.rb +166 -0
- data/test/adapter/json_api/parse_test.rb +137 -0
- data/test/adapter/json_api/relationship_test.rb +161 -0
- data/test/adapter/json_api/relationships_test.rb +199 -0
- data/test/adapter/json_api/resource_identifier_test.rb +85 -0
- data/test/adapter/json_api/resource_meta_test.rb +100 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
- data/test/adapter/json_api/transform_test.rb +502 -0
- data/test/adapter/json_api/type_test.rb +61 -0
- data/test/adapter/json_test.rb +45 -0
- data/test/adapter/null_test.rb +23 -0
- data/test/adapter/polymorphic_test.rb +171 -0
- data/test/adapter_test.rb +67 -0
- data/test/array_serializer_test.rb +20 -73
- data/test/benchmark/app.rb +65 -0
- data/test/benchmark/benchmarking_support.rb +67 -0
- data/test/benchmark/bm_caching.rb +119 -0
- data/test/benchmark/bm_transform.rb +34 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +84 -0
- data/test/benchmark/fixtures.rb +219 -0
- data/test/cache_test.rb +485 -0
- data/test/collection_serializer_test.rb +110 -0
- data/test/fixtures/active_record.rb +78 -0
- data/test/fixtures/poro.rb +282 -0
- data/test/generators/scaffold_controller_generator_test.rb +24 -0
- data/test/generators/serializer_generator_test.rb +57 -0
- data/test/grape_test.rb +82 -0
- data/test/include_tree/from_include_args_test.rb +26 -0
- data/test/include_tree/from_string_test.rb +94 -0
- data/test/include_tree/include_args_to_hash_test.rb +64 -0
- data/test/lint_test.rb +49 -0
- data/test/logger_test.rb +18 -0
- data/test/poro_test.rb +9 -0
- data/test/serializable_resource_test.rb +83 -0
- data/test/serializers/association_macros_test.rb +36 -0
- data/test/serializers/associations_test.rb +295 -0
- data/test/serializers/attribute_test.rb +151 -0
- data/test/serializers/attributes_test.rb +52 -0
- data/test/serializers/caching_configuration_test_isolated.rb +170 -0
- data/test/serializers/configuration_test.rb +32 -0
- data/test/serializers/fieldset_test.rb +14 -0
- data/test/serializers/meta_test.rb +196 -0
- data/test/serializers/options_test.rb +21 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
- data/test/serializers/root_test.rb +21 -0
- data/test/serializers/serialization_test.rb +55 -0
- data/test/serializers/serializer_for_test.rb +134 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +79 -0
- data/test/support/rails5_shims.rb +47 -0
- data/test/support/rails_app.rb +45 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
- data/test/support/schemas/custom/show.json +7 -0
- data/test/support/schemas/hyper_schema.json +93 -0
- data/test/support/schemas/render_using_json_api.json +43 -0
- data/test/support/schemas/simple_json_pointers.json +10 -0
- data/test/support/serialization_testing.rb +53 -0
- data/test/test_helper.rb +48 -23
- metadata +449 -43
- data/DESIGN.textile +0 -586
- data/Gemfile.edge +0 -9
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_model/array_serializer.rb +0 -104
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/USAGE +0 -9
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
data/test/cache_test.rb
ADDED
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
require 'tempfile'
|
|
4
|
+
|
|
5
|
+
module ActiveModelSerializers
|
|
6
|
+
class CacheTest < ActiveSupport::TestCase
|
|
7
|
+
UncachedAuthor = Class.new(Author) do
|
|
8
|
+
# To confirm cache_key is set using updated_at and cache_key option passed to cache
|
|
9
|
+
undef_method :cache_key
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Article = Class.new(::Model) do
|
|
13
|
+
# To confirm error is raised when cache_key is not set and cache_key option not passed to cache
|
|
14
|
+
undef_method :cache_key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
ArticleSerializer = Class.new(ActiveModel::Serializer) do
|
|
18
|
+
cache only: [:place], skip_digest: true
|
|
19
|
+
attributes :title
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
InheritedRoleSerializer = Class.new(RoleSerializer) do
|
|
23
|
+
cache key: 'inherited_role', only: [:name, :special_attribute]
|
|
24
|
+
attribute :special_attribute
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
setup do
|
|
28
|
+
cache_store.clear
|
|
29
|
+
@comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
30
|
+
@post = Post.new(title: 'New Post', body: 'Body')
|
|
31
|
+
@bio = Bio.new(id: 1, content: 'AMS Contributor')
|
|
32
|
+
@author = Author.new(name: 'Joao M. D. Moura')
|
|
33
|
+
@blog = Blog.new(id: 999, name: 'Custom blog', writer: @author, articles: [])
|
|
34
|
+
@role = Role.new(name: 'Great Author')
|
|
35
|
+
@location = Location.new(lat: '-23.550520', lng: '-46.633309')
|
|
36
|
+
@place = Place.new(name: 'Amazing Place')
|
|
37
|
+
@author.posts = [@post]
|
|
38
|
+
@author.roles = [@role]
|
|
39
|
+
@role.author = @author
|
|
40
|
+
@author.bio = @bio
|
|
41
|
+
@bio.author = @author
|
|
42
|
+
@post.comments = [@comment]
|
|
43
|
+
@post.author = @author
|
|
44
|
+
@comment.post = @post
|
|
45
|
+
@comment.author = @author
|
|
46
|
+
@post.blog = @blog
|
|
47
|
+
@location.place = @place
|
|
48
|
+
|
|
49
|
+
@location_serializer = LocationSerializer.new(@location)
|
|
50
|
+
@bio_serializer = BioSerializer.new(@bio)
|
|
51
|
+
@role_serializer = RoleSerializer.new(@role)
|
|
52
|
+
@post_serializer = PostSerializer.new(@post)
|
|
53
|
+
@author_serializer = AuthorSerializer.new(@author)
|
|
54
|
+
@comment_serializer = CommentSerializer.new(@comment)
|
|
55
|
+
@blog_serializer = BlogSerializer.new(@blog)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def test_explicit_cache_store
|
|
59
|
+
default_store = Class.new(ActiveModel::Serializer) do
|
|
60
|
+
cache
|
|
61
|
+
end
|
|
62
|
+
explicit_store = Class.new(ActiveModel::Serializer) do
|
|
63
|
+
cache cache_store: ActiveSupport::Cache::FileStore
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
assert ActiveSupport::Cache::MemoryStore, ActiveModelSerializers.config.cache_store
|
|
67
|
+
assert ActiveSupport::Cache::MemoryStore, default_store.cache_store
|
|
68
|
+
assert ActiveSupport::Cache::FileStore, explicit_store.cache_store
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_inherited_cache_configuration
|
|
72
|
+
inherited_serializer = Class.new(PostSerializer)
|
|
73
|
+
|
|
74
|
+
assert_equal PostSerializer._cache_key, inherited_serializer._cache_key
|
|
75
|
+
assert_equal PostSerializer._cache_options, inherited_serializer._cache_options
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_override_cache_configuration
|
|
79
|
+
inherited_serializer = Class.new(PostSerializer) do
|
|
80
|
+
cache key: 'new-key'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
assert_equal PostSerializer._cache_key, 'post'
|
|
84
|
+
assert_equal inherited_serializer._cache_key, 'new-key'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_cache_definition
|
|
88
|
+
assert_equal(cache_store, @post_serializer.class._cache)
|
|
89
|
+
assert_equal(cache_store, @author_serializer.class._cache)
|
|
90
|
+
assert_equal(cache_store, @comment_serializer.class._cache)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_cache_key_definition
|
|
94
|
+
assert_equal('post', @post_serializer.class._cache_key)
|
|
95
|
+
assert_equal('writer', @author_serializer.class._cache_key)
|
|
96
|
+
assert_equal(nil, @comment_serializer.class._cache_key)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_cache_key_interpolation_with_updated_at_when_cache_key_is_not_defined_on_object
|
|
100
|
+
uncached_author = UncachedAuthor.new(name: 'Joao M. D. Moura')
|
|
101
|
+
uncached_author_serializer = AuthorSerializer.new(uncached_author)
|
|
102
|
+
|
|
103
|
+
render_object_with_cache(uncached_author)
|
|
104
|
+
key = "#{uncached_author_serializer.class._cache_key}/#{uncached_author_serializer.object.id}-#{uncached_author_serializer.object.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
|
|
105
|
+
key = "#{key}/#{adapter.cached_name}"
|
|
106
|
+
assert_equal(uncached_author_serializer.attributes.to_json, cache_store.fetch(key).to_json)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_default_cache_key_fallback
|
|
110
|
+
render_object_with_cache(@comment)
|
|
111
|
+
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
|
112
|
+
assert_equal(@comment_serializer.attributes.to_json, cache_store.fetch(key).to_json)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_error_is_raised_if_cache_key_is_not_defined_on_object_or_passed_as_cache_option
|
|
116
|
+
article = Article.new(title: 'Must Read')
|
|
117
|
+
e = assert_raises ActiveModel::Serializer::UndefinedCacheKey do
|
|
118
|
+
render_object_with_cache(article)
|
|
119
|
+
end
|
|
120
|
+
assert_match(/ActiveModelSerializers::CacheTest::Article must define #cache_key, or the 'key:' option must be passed into 'CachedActiveModelSerializers_CacheTest_ArticleSerializer.cache'/, e.message)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_cache_options_definition
|
|
124
|
+
assert_equal({ expires_in: 0.1, skip_digest: true }, @post_serializer.class._cache_options)
|
|
125
|
+
assert_equal(nil, @blog_serializer.class._cache_options)
|
|
126
|
+
assert_equal({ expires_in: 1.day, skip_digest: true }, @comment_serializer.class._cache_options)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_fragment_cache_definition
|
|
130
|
+
assert_equal([:name], @role_serializer.class._cache_only)
|
|
131
|
+
assert_equal([:content], @bio_serializer.class._cache_except)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_associations_separately_cache
|
|
135
|
+
cache_store.clear
|
|
136
|
+
assert_equal(nil, cache_store.fetch(@post.cache_key))
|
|
137
|
+
assert_equal(nil, cache_store.fetch(@comment.cache_key))
|
|
138
|
+
|
|
139
|
+
Timecop.freeze(Time.current) do
|
|
140
|
+
render_object_with_cache(@post)
|
|
141
|
+
|
|
142
|
+
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
|
143
|
+
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
|
144
|
+
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
|
145
|
+
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_associations_cache_when_updated
|
|
150
|
+
Timecop.freeze(Time.current) do
|
|
151
|
+
# Generate a new Cache of Post object and each objects related to it.
|
|
152
|
+
render_object_with_cache(@post)
|
|
153
|
+
|
|
154
|
+
# Check if it cached the objects separately
|
|
155
|
+
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
|
156
|
+
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
|
157
|
+
key = "#{@comment.cache_key}/#{adapter.cached_name}"
|
|
158
|
+
assert_equal(@comment_serializer.attributes, cache_store.fetch(key))
|
|
159
|
+
|
|
160
|
+
# Simulating update on comments relationship with Post
|
|
161
|
+
new_comment = Comment.new(id: 2567, body: 'ZOMG A NEW COMMENT')
|
|
162
|
+
new_comment_serializer = CommentSerializer.new(new_comment)
|
|
163
|
+
@post.comments = [new_comment]
|
|
164
|
+
|
|
165
|
+
# Ask for the serialized object
|
|
166
|
+
render_object_with_cache(@post)
|
|
167
|
+
|
|
168
|
+
# Check if the the new comment was cached
|
|
169
|
+
key = "#{new_comment.cache_key}/#{adapter.cached_name}"
|
|
170
|
+
assert_equal(new_comment_serializer.attributes, cache_store.fetch(key))
|
|
171
|
+
key = "#{@post.cache_key}/#{adapter.cached_name}"
|
|
172
|
+
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_fragment_fetch_with_virtual_associations
|
|
177
|
+
expected_result = {
|
|
178
|
+
id: @location.id,
|
|
179
|
+
lat: @location.lat,
|
|
180
|
+
lng: @location.lng,
|
|
181
|
+
place: 'Nowhere'
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
hash = render_object_with_cache(@location)
|
|
185
|
+
|
|
186
|
+
assert_equal(hash, expected_result)
|
|
187
|
+
key = "#{@location.cache_key}/#{adapter.cached_name}"
|
|
188
|
+
assert_equal({ place: 'Nowhere' }, cache_store.fetch(key))
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_fragment_cache_with_inheritance
|
|
192
|
+
inherited = render_object_with_cache(@role, serializer: InheritedRoleSerializer)
|
|
193
|
+
base = render_object_with_cache(@role)
|
|
194
|
+
|
|
195
|
+
assert_includes(inherited.keys, :special_attribute)
|
|
196
|
+
refute_includes(base.keys, :special_attribute)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def test_uses_adapter_in_cache_key
|
|
200
|
+
render_object_with_cache(@post)
|
|
201
|
+
key = "#{@post.cache_key}/#{adapter.class.to_s.demodulize.underscore}"
|
|
202
|
+
assert_equal(@post_serializer.attributes, cache_store.fetch(key))
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Based on original failing test by @kevintyll
|
|
206
|
+
# rubocop:disable Metrics/AbcSize
|
|
207
|
+
def test_a_serializer_rendered_by_two_adapter_returns_differently_cached_attributes
|
|
208
|
+
Object.const_set(:Alert, Class.new(ActiveModelSerializers::Model) do
|
|
209
|
+
attr_accessor :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
|
|
210
|
+
end)
|
|
211
|
+
Object.const_set(:UncachedAlertSerializer, Class.new(ActiveModel::Serializer) do
|
|
212
|
+
attributes :id, :status, :resource, :started_at, :ended_at, :updated_at, :created_at
|
|
213
|
+
end)
|
|
214
|
+
Object.const_set(:AlertSerializer, Class.new(UncachedAlertSerializer) do
|
|
215
|
+
cache
|
|
216
|
+
end)
|
|
217
|
+
|
|
218
|
+
alert = Alert.new(
|
|
219
|
+
id: 1,
|
|
220
|
+
status: 'fail',
|
|
221
|
+
resource: 'resource-1',
|
|
222
|
+
started_at: Time.new(2016, 3, 31, 21, 36, 35, 0),
|
|
223
|
+
ended_at: nil,
|
|
224
|
+
updated_at: Time.new(2016, 3, 31, 21, 27, 35, 0),
|
|
225
|
+
created_at: Time.new(2016, 3, 31, 21, 37, 35, 0)
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
expected_cached_attributes = {
|
|
229
|
+
id: 1,
|
|
230
|
+
status: 'fail',
|
|
231
|
+
resource: 'resource-1',
|
|
232
|
+
started_at: alert.started_at,
|
|
233
|
+
ended_at: nil,
|
|
234
|
+
updated_at: alert.updated_at,
|
|
235
|
+
created_at: alert.created_at
|
|
236
|
+
}
|
|
237
|
+
expected_cached_jsonapi_attributes = {
|
|
238
|
+
id: '1',
|
|
239
|
+
type: 'alerts',
|
|
240
|
+
attributes: {
|
|
241
|
+
status: 'fail',
|
|
242
|
+
resource: 'resource-1',
|
|
243
|
+
started_at: alert.started_at,
|
|
244
|
+
ended_at: nil,
|
|
245
|
+
updated_at: alert.updated_at,
|
|
246
|
+
created_at: alert.created_at
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
# Assert attributes are serialized correctly
|
|
251
|
+
serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :attributes)
|
|
252
|
+
attributes_serialization = serializable_alert.as_json
|
|
253
|
+
assert_equal expected_cached_attributes, alert.attributes
|
|
254
|
+
assert_equal alert.attributes, attributes_serialization
|
|
255
|
+
attributes_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
|
|
256
|
+
assert_equal attributes_serialization, cache_store.fetch(attributes_cache_key)
|
|
257
|
+
|
|
258
|
+
serializable_alert = serializable(alert, serializer: AlertSerializer, adapter: :json_api)
|
|
259
|
+
jsonapi_cache_key = serializable_alert.adapter.serializer.cache_key(serializable_alert.adapter)
|
|
260
|
+
# Assert cache keys differ
|
|
261
|
+
refute_equal attributes_cache_key, jsonapi_cache_key
|
|
262
|
+
# Assert (cached) serializations differ
|
|
263
|
+
jsonapi_serialization = serializable_alert.as_json
|
|
264
|
+
assert_equal alert.status, jsonapi_serialization.fetch(:data).fetch(:attributes).fetch(:status)
|
|
265
|
+
serializable_alert = serializable(alert, serializer: UncachedAlertSerializer, adapter: :json_api)
|
|
266
|
+
assert_equal serializable_alert.as_json, jsonapi_serialization
|
|
267
|
+
|
|
268
|
+
cached_serialization = cache_store.fetch(jsonapi_cache_key)
|
|
269
|
+
assert_equal expected_cached_jsonapi_attributes, cached_serialization
|
|
270
|
+
ensure
|
|
271
|
+
Object.send(:remove_const, :Alert)
|
|
272
|
+
Object.send(:remove_const, :AlertSerializer)
|
|
273
|
+
Object.send(:remove_const, :UncachedAlertSerializer)
|
|
274
|
+
end
|
|
275
|
+
# rubocop:enable Metrics/AbcSize
|
|
276
|
+
|
|
277
|
+
def test_uses_file_digest_in_cache_key
|
|
278
|
+
render_object_with_cache(@blog)
|
|
279
|
+
key = "#{@blog.cache_key}/#{adapter.cached_name}/#{::Model::FILE_DIGEST}"
|
|
280
|
+
assert_equal(@blog_serializer.attributes, cache_store.fetch(key))
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def test_cache_digest_definition
|
|
284
|
+
assert_equal(::Model::FILE_DIGEST, @post_serializer.class._cache_digest)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def test_object_cache_keys
|
|
288
|
+
serializable = ActiveModelSerializers::SerializableResource.new([@comment, @comment])
|
|
289
|
+
include_tree = ActiveModel::Serializer::IncludeTree.from_include_args('*')
|
|
290
|
+
|
|
291
|
+
actual = ActiveModel::Serializer.object_cache_keys(serializable.adapter.serializer, serializable.adapter, include_tree)
|
|
292
|
+
|
|
293
|
+
assert_equal 3, actual.size
|
|
294
|
+
assert actual.any? { |key| key == "comment/1/#{serializable.adapter.cached_name}" }
|
|
295
|
+
assert actual.any? { |key| key =~ %r{post/post-\d+} }
|
|
296
|
+
assert actual.any? { |key| key =~ %r{author/author-\d+} }
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def test_cached_attributes
|
|
300
|
+
serializer = ActiveModel::Serializer::CollectionSerializer.new([@comment, @comment])
|
|
301
|
+
|
|
302
|
+
Timecop.freeze(Time.current) do
|
|
303
|
+
render_object_with_cache(@comment)
|
|
304
|
+
|
|
305
|
+
attributes = Adapter::Attributes.new(serializer)
|
|
306
|
+
attributes.send(:cache_attributes)
|
|
307
|
+
cached_attributes = attributes.instance_variable_get(:@cached_attributes)
|
|
308
|
+
|
|
309
|
+
assert_equal cached_attributes["#{@comment.cache_key}/#{attributes.cached_name}"], Comment.new(id: 1, body: 'ZOMG A COMMENT').attributes
|
|
310
|
+
assert_equal cached_attributes["#{@comment.post.cache_key}/#{attributes.cached_name}"], Post.new(id: 'post', title: 'New Post', body: 'Body').attributes
|
|
311
|
+
|
|
312
|
+
writer = @comment.post.blog.writer
|
|
313
|
+
writer_cache_key = writer.cache_key
|
|
314
|
+
|
|
315
|
+
assert_equal cached_attributes["#{writer_cache_key}/#{attributes.cached_name}"], Author.new(id: 'author', name: 'Joao M. D. Moura').attributes
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def test_serializer_file_path_on_nix
|
|
320
|
+
path = '/Users/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb'
|
|
321
|
+
caller_line = "#{path}:1:in `<top (required)>'"
|
|
322
|
+
assert_equal caller_line[ActiveModel::Serializer::CALLER_FILE], path
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def test_serializer_file_path_on_windows
|
|
326
|
+
path = 'c:/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb'
|
|
327
|
+
caller_line = "#{path}:1:in `<top (required)>'"
|
|
328
|
+
assert_equal caller_line[ActiveModel::Serializer::CALLER_FILE], path
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def test_serializer_file_path_with_space
|
|
332
|
+
path = '/Users/git/ember js/ember-crm-backend/app/serializers/lead_serializer.rb'
|
|
333
|
+
caller_line = "#{path}:1:in `<top (required)>'"
|
|
334
|
+
assert_equal caller_line[ActiveModel::Serializer::CALLER_FILE], path
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def test_serializer_file_path_with_submatch
|
|
338
|
+
# The submatch in the path ensures we're using a correctly greedy regexp.
|
|
339
|
+
path = '/Users/git/ember js/ember:123:in x/app/serializers/lead_serializer.rb'
|
|
340
|
+
caller_line = "#{path}:1:in `<top (required)>'"
|
|
341
|
+
assert_equal caller_line[ActiveModel::Serializer::CALLER_FILE], path
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def test_digest_caller_file
|
|
345
|
+
contents = "puts 'AMS rocks'!"
|
|
346
|
+
dir = Dir.mktmpdir('space char')
|
|
347
|
+
file = Tempfile.new('some_ruby.rb', dir)
|
|
348
|
+
file.write(contents)
|
|
349
|
+
path = file.path
|
|
350
|
+
caller_line = "#{path}:1:in `<top (required)>'"
|
|
351
|
+
file.close
|
|
352
|
+
assert_equal ActiveModel::Serializer.digest_caller_file(caller_line), Digest::MD5.hexdigest(contents)
|
|
353
|
+
ensure
|
|
354
|
+
file.unlink
|
|
355
|
+
FileUtils.remove_entry dir
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def test_warn_on_serializer_not_defined_in_file
|
|
359
|
+
called = false
|
|
360
|
+
serializer = Class.new(ActiveModel::Serializer)
|
|
361
|
+
assert_output(nil, /_cache_digest/) do
|
|
362
|
+
serializer.digest_caller_file('')
|
|
363
|
+
called = true
|
|
364
|
+
end
|
|
365
|
+
assert called
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def test_cached_false_without_cache_store
|
|
369
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
370
|
+
serializer._cache = nil
|
|
371
|
+
end
|
|
372
|
+
refute cached_serializer.class.cache_enabled?
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def test_cached_true_with_cache_store_and_without_cache_only_and_cache_except
|
|
376
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
377
|
+
serializer._cache = Object
|
|
378
|
+
end
|
|
379
|
+
assert cached_serializer.class.cache_enabled?
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def test_cached_false_with_cache_store_and_with_cache_only
|
|
383
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
384
|
+
serializer._cache = Object
|
|
385
|
+
serializer._cache_only = [:name]
|
|
386
|
+
end
|
|
387
|
+
refute cached_serializer.class.cache_enabled?
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def test_cached_false_with_cache_store_and_with_cache_except
|
|
391
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
392
|
+
serializer._cache = Object
|
|
393
|
+
serializer._cache_except = [:content]
|
|
394
|
+
end
|
|
395
|
+
refute cached_serializer.class.cache_enabled?
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def test_fragment_cached_false_without_cache_store
|
|
399
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
400
|
+
serializer._cache = nil
|
|
401
|
+
serializer._cache_only = [:name]
|
|
402
|
+
end
|
|
403
|
+
refute cached_serializer.class.fragment_cache_enabled?
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def test_fragment_cached_true_with_cache_store_and_cache_only
|
|
407
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
408
|
+
serializer._cache = Object
|
|
409
|
+
serializer._cache_only = [:name]
|
|
410
|
+
end
|
|
411
|
+
assert cached_serializer.class.fragment_cache_enabled?
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def test_fragment_cached_true_with_cache_store_and_cache_except
|
|
415
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
416
|
+
serializer._cache = Object
|
|
417
|
+
serializer._cache_except = [:content]
|
|
418
|
+
end
|
|
419
|
+
assert cached_serializer.class.fragment_cache_enabled?
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def test_fragment_cached_false_with_cache_store_and_cache_except_and_cache_only
|
|
423
|
+
cached_serializer = build_cached_serializer do |serializer|
|
|
424
|
+
serializer._cache = Object
|
|
425
|
+
serializer._cache_except = [:content]
|
|
426
|
+
serializer._cache_only = [:name]
|
|
427
|
+
end
|
|
428
|
+
refute cached_serializer.class.fragment_cache_enabled?
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def test_fragment_fetch_with_virtual_attributes
|
|
432
|
+
@author = Author.new(name: 'Joao M. D. Moura')
|
|
433
|
+
@role = Role.new(name: 'Great Author', description: nil)
|
|
434
|
+
@role.author = [@author]
|
|
435
|
+
@role_serializer = RoleSerializer.new(@role)
|
|
436
|
+
@role_hash = @role_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@role_serializer))
|
|
437
|
+
|
|
438
|
+
expected_result = {
|
|
439
|
+
id: @role.id,
|
|
440
|
+
description: @role.description,
|
|
441
|
+
slug: "#{@role.name}-#{@role.id}",
|
|
442
|
+
name: @role.name
|
|
443
|
+
}
|
|
444
|
+
assert_equal(@role_hash, expected_result)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def test_fragment_fetch_with_namespaced_object
|
|
448
|
+
@spam = Spam::UnrelatedLink.new(id: 'spam-id-1')
|
|
449
|
+
@spam_serializer = Spam::UnrelatedLinkSerializer.new(@spam)
|
|
450
|
+
@spam_hash = @spam_serializer.fetch_fragment_cache(ActiveModelSerializers::Adapter.configured_adapter.new(@spam_serializer))
|
|
451
|
+
expected_result = {
|
|
452
|
+
id: @spam.id
|
|
453
|
+
}
|
|
454
|
+
assert_equal(@spam_hash, expected_result)
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
private
|
|
458
|
+
|
|
459
|
+
def cache_store
|
|
460
|
+
ActiveModelSerializers.config.cache_store
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
def build_cached_serializer
|
|
464
|
+
serializer = Class.new(ActiveModel::Serializer)
|
|
465
|
+
serializer._cache_key = nil
|
|
466
|
+
serializer._cache_options = nil
|
|
467
|
+
yield serializer if block_given?
|
|
468
|
+
serializer.new(Object)
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def render_object_with_cache(obj, options = {})
|
|
472
|
+
@serializable_resource = serializable(obj, options)
|
|
473
|
+
@serializable_resource.serializable_hash
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def adapter
|
|
477
|
+
@serializable_resource.adapter
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
def cached_serialization(serializer)
|
|
481
|
+
cache_key = serializer.cache_key(adapter)
|
|
482
|
+
cache_store.fetch(cache_key)
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActiveModel
|
|
4
|
+
class Serializer
|
|
5
|
+
class CollectionSerializerTest < ActiveSupport::TestCase
|
|
6
|
+
MessagesSerializer = Class.new(ActiveModel::Serializer) do
|
|
7
|
+
type 'messages'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def setup
|
|
11
|
+
@comment = Comment.new
|
|
12
|
+
@post = Post.new
|
|
13
|
+
@resource = build_named_collection @comment, @post
|
|
14
|
+
@serializer = collection_serializer.new(@resource, { some: :options })
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def collection_serializer
|
|
18
|
+
CollectionSerializer
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def build_named_collection(*resource)
|
|
22
|
+
resource.define_singleton_method(:name) { 'MeResource' }
|
|
23
|
+
resource
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_has_object_reader_serializer_interface
|
|
27
|
+
assert_equal @serializer.object, @resource
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_respond_to_each
|
|
31
|
+
assert_respond_to @serializer, :each
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_each_object_should_be_serialized_with_appropriate_serializer
|
|
35
|
+
serializers = @serializer.to_a
|
|
36
|
+
|
|
37
|
+
assert_kind_of CommentSerializer, serializers.first
|
|
38
|
+
assert_kind_of Comment, serializers.first.object
|
|
39
|
+
|
|
40
|
+
assert_kind_of PostSerializer, serializers.last
|
|
41
|
+
assert_kind_of Post, serializers.last.object
|
|
42
|
+
|
|
43
|
+
assert_equal :options, serializers.last.custom_options[:some]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_serializer_option_not_passed_to_each_serializer
|
|
47
|
+
serializers = collection_serializer.new([@post], { serializer: PostSerializer }).to_a
|
|
48
|
+
|
|
49
|
+
refute serializers.first.custom_options.key?(:serializer)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_root_default
|
|
53
|
+
@serializer = collection_serializer.new([@comment, @post])
|
|
54
|
+
assert_nil @serializer.root
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_root
|
|
58
|
+
expected = 'custom_root'
|
|
59
|
+
@serializer = collection_serializer.new([@comment, @post], root: expected)
|
|
60
|
+
assert_equal expected, @serializer.root
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_root_with_no_serializers
|
|
64
|
+
expected = 'custom_root'
|
|
65
|
+
@serializer = collection_serializer.new([], root: expected)
|
|
66
|
+
assert_equal expected, @serializer.root
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_json_key_with_resource_with_serializer
|
|
70
|
+
singular_key = @serializer.send(:serializers).first.json_key
|
|
71
|
+
assert_equal singular_key.pluralize, @serializer.json_key
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_json_key_with_resource_with_name_and_no_serializers
|
|
75
|
+
serializer = collection_serializer.new(build_named_collection)
|
|
76
|
+
assert_equal 'me_resources', serializer.json_key
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_json_key_with_resource_with_nil_name_and_no_serializers
|
|
80
|
+
resource = []
|
|
81
|
+
resource.define_singleton_method(:name) { nil }
|
|
82
|
+
serializer = collection_serializer.new(resource)
|
|
83
|
+
assert_nil serializer.json_key
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_json_key_with_resource_without_name_and_no_serializers
|
|
87
|
+
serializer = collection_serializer.new([])
|
|
88
|
+
assert_nil serializer.json_key
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_json_key_with_empty_resources_with_serializer
|
|
92
|
+
resource = []
|
|
93
|
+
serializer = collection_serializer.new(resource, serializer: MessagesSerializer)
|
|
94
|
+
assert_equal 'messages', serializer.json_key
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_json_key_with_root
|
|
98
|
+
expected = 'custom_root'
|
|
99
|
+
serializer = collection_serializer.new(@resource, root: expected)
|
|
100
|
+
assert_equal expected, serializer.json_key
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_json_key_with_root_and_no_serializers
|
|
104
|
+
expected = 'custom_root'
|
|
105
|
+
serializer = collection_serializer.new(build_named_collection, root: expected)
|
|
106
|
+
assert_equal expected, serializer.json_key
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
|
|
3
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
|
4
|
+
ActiveRecord::Schema.define do
|
|
5
|
+
self.verbose = false
|
|
6
|
+
create_table :posts, force: true do |t|
|
|
7
|
+
t.string :title
|
|
8
|
+
t.text :body
|
|
9
|
+
t.references :author
|
|
10
|
+
t.timestamps null: false
|
|
11
|
+
end
|
|
12
|
+
create_table :authors, force: true do |t|
|
|
13
|
+
t.string :name
|
|
14
|
+
t.timestamps null: false
|
|
15
|
+
end
|
|
16
|
+
create_table :comments, force: true do |t|
|
|
17
|
+
t.text :contents
|
|
18
|
+
t.references :author
|
|
19
|
+
t.references :post
|
|
20
|
+
t.timestamp null: false
|
|
21
|
+
end
|
|
22
|
+
create_table :employees, force: true do |t|
|
|
23
|
+
t.string :name
|
|
24
|
+
t.string :email
|
|
25
|
+
t.timestamp null: false
|
|
26
|
+
end
|
|
27
|
+
create_table :object_tags, force: true do |t|
|
|
28
|
+
t.string :poly_tag_id
|
|
29
|
+
t.string :taggable_type
|
|
30
|
+
t.string :taggable_id
|
|
31
|
+
t.timestamp null: false
|
|
32
|
+
end
|
|
33
|
+
create_table :poly_tags, force: true do |t|
|
|
34
|
+
t.string :phrase
|
|
35
|
+
t.timestamp null: false
|
|
36
|
+
end
|
|
37
|
+
create_table :pictures, force: true do |t|
|
|
38
|
+
t.string :title
|
|
39
|
+
t.string :imageable_type
|
|
40
|
+
t.string :imageable_id
|
|
41
|
+
t.timestamp null: false
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module ARModels
|
|
46
|
+
class Post < ActiveRecord::Base
|
|
47
|
+
has_many :comments
|
|
48
|
+
belongs_to :author
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class Comment < ActiveRecord::Base
|
|
52
|
+
belongs_to :post
|
|
53
|
+
belongs_to :author
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class Author < ActiveRecord::Base
|
|
57
|
+
has_many :posts
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class PostSerializer < ActiveModel::Serializer
|
|
61
|
+
attributes :id, :title, :body
|
|
62
|
+
|
|
63
|
+
has_many :comments
|
|
64
|
+
belongs_to :author
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class CommentSerializer < ActiveModel::Serializer
|
|
68
|
+
attributes :id, :contents
|
|
69
|
+
|
|
70
|
+
belongs_to :author
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class AuthorSerializer < ActiveModel::Serializer
|
|
74
|
+
attributes :id, :name
|
|
75
|
+
|
|
76
|
+
has_many :posts
|
|
77
|
+
end
|
|
78
|
+
end
|