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,77 @@
1
+ require 'test_helper'
2
+ require 'fixtures/active_record'
3
+
4
+ module ActiveModel
5
+ class Serializer
6
+ class ActiveRecordTest < ActiveModel::TestCase
7
+ def setup
8
+ @post = ARPost.first
9
+ end
10
+
11
+ def test_serialization_embedding_objects
12
+ post_serializer = ARPostSerializer.new(@post)
13
+
14
+ assert_equal({
15
+ 'ar_post' => {
16
+ title: 'New post', body: 'A body!!!',
17
+ ar_comments: [{ body: 'what a dumb post', ar_tags: [{ name: 'happy' }, { name: 'whiny' }] },
18
+ { body: 'i liked it', ar_tags: [{:name=>"happy"}, {:name=>"short"}] }],
19
+ ar_tags: [{ name: 'short' }, { name: 'whiny' }],
20
+ ar_section: { 'name' => 'ruby' }
21
+ }
22
+ }, post_serializer.as_json)
23
+ end
24
+
25
+ def test_serialization_embedding_ids
26
+ post_serializer = ARPostSerializer.new(@post)
27
+
28
+ embed(ARPostSerializer, embed: :ids) do
29
+ assert_equal({
30
+ 'ar_post' => {
31
+ title: 'New post', body: 'A body!!!',
32
+ 'ar_comment_ids' => [1, 2],
33
+ 'ar_tag_ids' => [1, 2],
34
+ 'ar_section_id' => 1
35
+ }
36
+ }, post_serializer.as_json)
37
+ end
38
+ end
39
+
40
+ def test_serialization_embedding_ids_including_in_root
41
+ post_serializer = ARPostSerializer.new(@post)
42
+
43
+ embed(ARPostSerializer, embed: :ids, embed_in_root: true) do
44
+ embed(ARCommentSerializer, embed: :ids, embed_in_root: true) do
45
+ assert_equal({
46
+ 'ar_post' => {
47
+ title: 'New post', body: 'A body!!!',
48
+ 'ar_comment_ids' => [1, 2],
49
+ 'ar_tag_ids' => [1, 2],
50
+ 'ar_section_id' => 1
51
+ },
52
+ ar_comments: [{ body: 'what a dumb post', 'ar_tag_ids' => [3, 2] },
53
+ { body: 'i liked it', 'ar_tag_ids' => [3, 1] }],
54
+ ar_tags: [{ name: 'happy' }, { name: 'whiny' }, { name: 'short' }],
55
+ 'ar_sections' => [{ 'name' => 'ruby' }]
56
+ }, post_serializer.as_json)
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def embed(serializer_class, options = {})
64
+ old_assocs = Hash[serializer_class._associations.to_a.map { |(name, association)| [name, association.dup] }]
65
+
66
+ serializer_class._associations.each_value do |association|
67
+ association.embed = options[:embed]
68
+ association.embed_in_root = options[:embed_in_root]
69
+ end
70
+
71
+ yield
72
+ ensure
73
+ serializer_class._associations = old_assocs
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+ require 'rails'
3
+ require 'active_model/serializer/railtie'
4
+ require 'test_app'
5
+
6
+ class ResourceGeneratorTest < Rails::Generators::TestCase
7
+ destination File.expand_path('../../../tmp', __FILE__)
8
+ setup :prepare_destination, :copy_routes
9
+
10
+ tests Rails::Generators::ResourceGenerator
11
+ arguments %w(account)
12
+
13
+ def test_serializer_file_is_generated
14
+ run_generator
15
+
16
+ assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ActiveModel::Serializer/
17
+ end
18
+
19
+ private
20
+
21
+ def copy_routes
22
+ config_dir = File.join(destination_root, 'config')
23
+ FileUtils.mkdir_p(config_dir)
24
+ File.write(File.join(config_dir, 'routes.rb'), 'Rails.application.routes.draw { }')
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+ require 'rails'
3
+ require 'active_model/serializer/railtie'
4
+ require 'test_app'
5
+
6
+ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
7
+ destination File.expand_path('../../../tmp', __FILE__)
8
+ setup :prepare_destination
9
+
10
+ tests Rails::Generators::ScaffoldControllerGenerator
11
+ arguments %w(account name:string description:text business:references)
12
+
13
+ def test_generated_controller
14
+ return true if Rails::VERSION::MAJOR < 4
15
+
16
+ run_generator
17
+
18
+ assert_file 'app/controllers/accounts_controller.rb' do |content|
19
+
20
+ assert_instance_method :index, content do |m|
21
+ assert_match /@accounts = Account\.all/, m
22
+ assert_match /format.html/, m
23
+ assert_match /format.json \{ render json: @accounts \}/, m
24
+ end
25
+
26
+ assert_instance_method :show, content do |m|
27
+ assert_match /format.html/, m
28
+ assert_match /format.json \{ render json: @account \}/, m
29
+ end
30
+
31
+ assert_instance_method :new, content do |m|
32
+ assert_match /@account = Account\.new/, m
33
+ end
34
+
35
+ assert_instance_method :edit, content do |m|
36
+ assert m.blank?
37
+ end
38
+
39
+ assert_instance_method :create, content do |m|
40
+ assert_match /@account = Account\.new\(account_params\)/, m
41
+ assert_match /@account\.save/, m
42
+ assert_match /format\.html \{ redirect_to @account, notice: 'Account was successfully created\.' \}/, m
43
+ assert_match /format\.json \{ render json: @account, status: :created \}/, m
44
+ assert_match /format\.html \{ render action: 'new' \}/, m
45
+ assert_match /format\.json \{ render json: @account\.errors, status: :unprocessable_entity \}/, m
46
+ end
47
+
48
+ assert_instance_method :update, content do |m|
49
+ assert_match /format\.html \{ redirect_to @account, notice: 'Account was successfully updated\.' \}/, m
50
+ assert_match /format\.json \{ head :no_content \}/, m
51
+ assert_match /format\.html \{ render action: 'edit' \}/, m
52
+ assert_match /format\.json \{ render json: @account.errors, status: :unprocessable_entity \}/, m
53
+ end
54
+
55
+ assert_instance_method :destroy, content do |m|
56
+ assert_match /@account\.destroy/, m
57
+ assert_match /format\.html { redirect_to accounts_url \}/, m
58
+ assert_match /format\.json \{ head :no_content \}/, m
59
+ end
60
+
61
+ assert_match(/def account_params/, content)
62
+ assert_match(/params\.require\(:account\)\.permit\(:name, :description, :business_id\)/, content)
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+ require 'rails'
3
+ require 'active_model/serializer/railtie'
4
+ require 'test_app'
5
+
6
+ class SerializerGeneratorTest < Rails::Generators::TestCase
7
+ destination File.expand_path('../../../tmp', __FILE__)
8
+ setup :prepare_destination
9
+
10
+ tests Rails::Generators::SerializerGenerator
11
+ arguments %w(account name:string description:text business:references)
12
+
13
+ def test_generates_a_serializer_with_attributes_and_associations
14
+ run_generator
15
+ assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ActiveModel::Serializer/ do |serializer|
16
+ assert_match(/attributes :id, :name, :description/, serializer)
17
+ assert_match(/has_one :business/, serializer)
18
+ end
19
+ end
20
+
21
+ def test_generates_a_namespaced_serializer
22
+ run_generator ['admin/account']
23
+ assert_file 'app/serializers/admin/account_serializer.rb', /class Admin::AccountSerializer < ActiveModel::Serializer/
24
+ end
25
+
26
+ def test_uses_application_serializer_if_one_exists
27
+ Object.const_set(:ApplicationSerializer, Class.new)
28
+ run_generator
29
+ assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < ApplicationSerializer/
30
+ ensure
31
+ Object.send :remove_const, :ApplicationSerializer
32
+ end
33
+
34
+ def test_uses_given_parent
35
+ Object.const_set(:ApplicationSerializer, Class.new)
36
+ run_generator ['Account', '--parent=MySerializer']
37
+ assert_file 'app/serializers/account_serializer.rb', /class AccountSerializer < MySerializer/
38
+ ensure
39
+ Object.send :remove_const, :ApplicationSerializer
40
+ end
41
+ end
data/test/test_app.rb ADDED
@@ -0,0 +1,11 @@
1
+ class TestApp < Rails::Application
2
+ if Rails.version.to_s.first >= '4'
3
+ config.eager_load = false
4
+ config.secret_key_base = 'abc123'
5
+ end
6
+
7
+ # Set up a logger to avoid creating a log directory on every run.
8
+ config.logger = Logger.new(nil)
9
+ end
10
+
11
+ TestApp.initialize!
data/test/test_helper.rb CHANGED
@@ -1,55 +1,21 @@
1
- require "rubygems"
2
- require "bundler/setup"
3
-
4
- require 'rails'
5
- require 'action_controller'
6
- require 'action_controller/test_case'
7
- require 'action_controller/railtie'
8
- require 'active_support/json'
9
-
10
- gem 'minitest'
1
+ require 'bundler/setup'
2
+ require 'coverage_setup'
11
3
  require 'minitest/autorun'
12
- if defined?(Minitest::Test)
13
- $minitest_version = 5 # rubocop:disable Style/GlobalVars
14
- # Minitest 5
15
- # https://github.com/seattlerb/minitest/blob/e21fdda9d/lib/minitest/autorun.rb
16
- # https://github.com/seattlerb/minitest/blob/e21fdda9d/lib/minitest.rb#L45-L59
17
- else
18
- $minitest_version = 4 # rubocop:disable Style/GlobalVars
19
- # Minitest 4
20
- # https://github.com/seattlerb/minitest/blob/644a52fd0/lib/minitest/autorun.rb
21
- # https://github.com/seattlerb/minitest/blob/644a52fd0/lib/minitest/unit.rb#L768-L787
22
- # Ensure backward compatibility with Minitest 4
23
- Minitest = MiniTest unless defined?(Minitest)
24
- Minitest::Test = MiniTest::Unit::TestCase
25
- def Minitest.after_run(&block)
26
- MiniTest::Unit.after_tests(&block)
27
- end
28
- end
29
-
30
-
31
- require "pry"
32
-
33
- require "active_model_serializers"
4
+ require 'active_model_serializers'
5
+ require 'fixtures/poro'
34
6
 
35
7
  module TestHelper
36
8
  Routes = ActionDispatch::Routing::RouteSet.new
37
9
  Routes.draw do
38
- resource :hypermedia
39
10
  get ':controller(/:action(/:id))'
40
11
  get ':controller(/:action)'
41
12
  end
42
13
 
43
14
  ActionController::Base.send :include, Routes.url_helpers
44
- ActiveModel::Serializer.send :include, Routes.url_helpers
45
15
  end
46
16
 
47
- ActiveSupport::TestCase.class_eval do
48
- setup do
49
- @routes = ::TestHelper::Routes
17
+ ActionController::TestCase.class_eval do
18
+ def setup
19
+ @routes = TestHelper::Routes
50
20
  end
51
21
  end
52
-
53
- class Object
54
- undef_method :id if respond_to?(:id)
55
- end
@@ -0,0 +1,3 @@
1
+ class AccountSerializer < MySerializer
2
+ attributes :id
3
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+ require 'active_model/serializer'
3
+
4
+ module ActiveModel
5
+ class ArraySerializer
6
+ class MetaTest < ActiveModel::TestCase
7
+ def setup
8
+ @profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ @profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
10
+ @serializer = ArraySerializer.new([@profile1, @profile2], root: 'profiles')
11
+ end
12
+
13
+ def test_meta
14
+ @serializer.meta = { total: 10 }
15
+
16
+ assert_equal({
17
+ 'profiles' => [
18
+ {
19
+ name: 'Name 1',
20
+ description: 'Description 1'
21
+ }, {
22
+ name: 'Name 2',
23
+ description: 'Description 2'
24
+ }
25
+ ],
26
+ meta: {
27
+ total: 10
28
+ }
29
+ }, @serializer.as_json)
30
+ end
31
+
32
+ def test_meta_using_meta_key
33
+ @serializer.meta_key = :my_meta
34
+ @serializer.meta = { total: 10 }
35
+
36
+ assert_equal({
37
+ 'profiles' => [
38
+ {
39
+ name: 'Name 1',
40
+ description: 'Description 1'
41
+ }, {
42
+ name: 'Name 2',
43
+ description: 'Description 2'
44
+ }
45
+ ],
46
+ my_meta: {
47
+ total: 10
48
+ }
49
+ }, @serializer.as_json)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,102 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class ArraySerializer
5
+ class RootAsOptionTest < ActiveModel::TestCase
6
+ def setup
7
+ @old_root = ArraySerializer._root
8
+ @profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ @profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
10
+ @serializer = ArraySerializer.new([@profile1, @profile2], root: :initialize)
11
+ end
12
+
13
+ def teardown
14
+ ArraySerializer._root = @old_root
15
+ end
16
+
17
+ def test_root_is_not_displayed_using_serializable_array
18
+ assert_equal([
19
+ { name: 'Name 1', description: 'Description 1' },
20
+ { name: 'Name 2', description: 'Description 2' }
21
+ ], @serializer.serializable_array)
22
+ end
23
+
24
+ def test_root_using_as_json
25
+ assert_equal({
26
+ initialize: [
27
+ { name: 'Name 1', description: 'Description 1' },
28
+ { name: 'Name 2', description: 'Description 2' }
29
+ ]
30
+ }, @serializer.as_json)
31
+ end
32
+
33
+ def test_root_as_argument_takes_precedence
34
+ assert_equal({
35
+ argument: [
36
+ { name: 'Name 1', description: 'Description 1' },
37
+ { name: 'Name 2', description: 'Description 2' }
38
+ ]
39
+ }, @serializer.as_json(root: :argument))
40
+ end
41
+
42
+ def test_using_false_root_in_initialize_takes_precedence
43
+ ArraySerializer._root = 'root'
44
+ @serializer = ArraySerializer.new([@profile1, @profile2], root: false)
45
+
46
+ assert_equal([
47
+ { name: 'Name 1', description: 'Description 1' },
48
+ { name: 'Name 2', description: 'Description 2' }
49
+ ], @serializer.as_json)
50
+ end
51
+ end
52
+
53
+ class RootInSerializerTest < ActiveModel::TestCase
54
+ def setup
55
+ @old_root = ArraySerializer._root
56
+ ArraySerializer._root = :in_serializer
57
+ @profile1 = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
58
+ @profile2 = Profile.new({ name: 'Name 2', description: 'Description 2', comments: 'Comments 2' })
59
+ @serializer = ArraySerializer.new([@profile1, @profile2])
60
+ @rooted_serializer = ArraySerializer.new([@profile1, @profile2], root: :initialize)
61
+ end
62
+
63
+ def teardown
64
+ ArraySerializer._root = @old_root
65
+ end
66
+
67
+ def test_root_is_not_displayed_using_serializable_hash
68
+ assert_equal([
69
+ { name: 'Name 1', description: 'Description 1' },
70
+ { name: 'Name 2', description: 'Description 2' }
71
+ ], @serializer.serializable_array)
72
+ end
73
+
74
+ def test_root_using_as_json
75
+ assert_equal({
76
+ in_serializer: [
77
+ { name: 'Name 1', description: 'Description 1' },
78
+ { name: 'Name 2', description: 'Description 2' }
79
+ ]
80
+ }, @serializer.as_json)
81
+ end
82
+
83
+ def test_root_in_initializer_takes_precedence
84
+ assert_equal({
85
+ initialize: [
86
+ { name: 'Name 1', description: 'Description 1' },
87
+ { name: 'Name 2', description: 'Description 2' }
88
+ ]
89
+ }, @rooted_serializer.as_json)
90
+ end
91
+
92
+ def test_root_as_argument_takes_precedence
93
+ assert_equal({
94
+ argument: [
95
+ { name: 'Name 1', description: 'Description 1' },
96
+ { name: 'Name 2', description: 'Description 2' }
97
+ ]
98
+ }, @rooted_serializer.as_json(root: :argument))
99
+ end
100
+ end
101
+ end
102
+ end