From f00fe5595ddf741dc26127ed8fe81adad833ead5 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 08:17:36 +0400 Subject: [PATCH 01/26] * Rename NullAdapter to SimpleAdapter * Introduce abstract Adapter class * Organaze test structure to match convemtions --- lib/action_controller/serialization.rb | 2 +- lib/active_model/serializer.rb | 1 + lib/active_model/serializer/adapter.rb | 20 +++++++++++++++ .../{null_adapter.rb => simple_adapter.rb} | 6 +---- lib/active_model_serializers.rb | 2 +- .../simple_adapter_test.rb} | 6 ++--- test/adapter_test.rb | 25 +++++++++++++++++++ 7 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 lib/active_model/serializer/adapter.rb rename lib/active_model/serializer/adapter/{null_adapter.rb => simple_adapter.rb} (72%) rename test/{adapters/null_adapter_test.rb => adapter/simple_adapter_test.rb} (76%) create mode 100644 test/adapter_test.rb diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index d51aba0f3..f5d13287e 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -12,7 +12,7 @@ def _render_option_json(resource, options) if serializer # omg hax object = serializer.new(resource) - adapter = ActiveModel::Serializer::Adapter::NullAdapter.new(object) + adapter = ActiveModel::Serializer::Adapter::SimpleAdapter.new(object) super(adapter, options) else diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index c06c58a0e..255665c70 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -3,6 +3,7 @@ class Serializer extend ActiveSupport::Autoload autoload :Configuration autoload :ArraySerializer + autoload :Adapter include Configuration class << self diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb new file mode 100644 index 000000000..e35c4595e --- /dev/null +++ b/lib/active_model/serializer/adapter.rb @@ -0,0 +1,20 @@ +module ActiveModel + class Serializer + class Adapter + extend ActiveSupport::Autoload + autoload :SimpleAdapter + + def initialize(serializer) + @attributes = serializer.attributes + end + + def serializable_hash(options = {}) + raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' + end + + def to_json(options = {}) + raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' + end + end + end +end diff --git a/lib/active_model/serializer/adapter/null_adapter.rb b/lib/active_model/serializer/adapter/simple_adapter.rb similarity index 72% rename from lib/active_model/serializer/adapter/null_adapter.rb rename to lib/active_model/serializer/adapter/simple_adapter.rb index 7ef77f21b..907493071 100644 --- a/lib/active_model/serializer/adapter/null_adapter.rb +++ b/lib/active_model/serializer/adapter/simple_adapter.rb @@ -1,11 +1,7 @@ module ActiveModel class Serializer class Adapter - class NullAdapter - def initialize(adapter) - @attributes = adapter.attributes - end - + class SimpleAdapter < Adapter def to_json(options={}) @attributes.each_with_object({}) do |(attr, value), h| h[attr] = value diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb index f77742900..894ca8695 100644 --- a/lib/active_model_serializers.rb +++ b/lib/active_model_serializers.rb @@ -1,7 +1,7 @@ require "active_model" require "active_model/serializer/version" require "active_model/serializer" -require "active_model/serializer/adapter/null_adapter" +require "active_model/serializer/adapter/simple_adapter" begin require 'action_controller' diff --git a/test/adapters/null_adapter_test.rb b/test/adapter/simple_adapter_test.rb similarity index 76% rename from test/adapters/null_adapter_test.rb rename to test/adapter/simple_adapter_test.rb index b50e9e126..e03740269 100644 --- a/test/adapters/null_adapter_test.rb +++ b/test/adapter/simple_adapter_test.rb @@ -3,15 +3,15 @@ module ActiveModel class Serializer class Adapter - class NullAdapterTest < Minitest::Test + class SimpleAdapterTest < Minitest::Test def setup @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) @profile_serializer = ProfileSerializer.new(@profile) - @adapter = NullAdapter.new(@profile_serializer) + @adapter = SimpleAdapter.new(@profile_serializer) end - def test_null_adapter + def test_simple_adapter assert_equal('{"name":"Name 1","description":"Description 1"}', @adapter.to_json) diff --git a/test/adapter_test.rb b/test/adapter_test.rb new file mode 100644 index 000000000..f9a787731 --- /dev/null +++ b/test/adapter_test.rb @@ -0,0 +1,25 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class AdapterTest < Minitest::Test + def setup + profile = Profile.new + serializer = ProfileSerializer.new(profile) + @adapter = ActiveModel::Serializer::Adapter.new(serializer) + end + + def test_serializable_hash_is_abstract_method + assert_raises(NotImplementedError) do + @adapter.serializable_hash(only: [:name]) + end + end + + def test_serializable_hash_is_abstract_method + assert_raises(NotImplementedError) do + @adapter.to_json(only: [:name]) + end + end + end + end +end From 56725b45a68ee13b1e5fa1d009a57c91bc14bbd0 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 08:23:13 +0400 Subject: [PATCH 02/26] Add NullAdapater --- lib/active_model/serializer/adapter.rb | 1 + .../serializer/adapter/null_adapter.rb | 15 +++++++++++++ test/adapter/null_adapter_test.rb | 21 +++++++++++++++++++ test/adapter_test.rb | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lib/active_model/serializer/adapter/null_adapter.rb create mode 100644 test/adapter/null_adapter_test.rb diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index e35c4595e..299a3d1f7 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -3,6 +3,7 @@ class Serializer class Adapter extend ActiveSupport::Autoload autoload :SimpleAdapter + autoload :NullAdapter def initialize(serializer) @attributes = serializer.attributes diff --git a/lib/active_model/serializer/adapter/null_adapter.rb b/lib/active_model/serializer/adapter/null_adapter.rb new file mode 100644 index 000000000..31b8d4ceb --- /dev/null +++ b/lib/active_model/serializer/adapter/null_adapter.rb @@ -0,0 +1,15 @@ +module ActiveModel + class Serializer + class Adapter + class NullAdapter < Adapter + def serializable_hash(options = {}) + {} + end + + def to_json(options = {}) + serializable_hash.to_json + end + end + end + end +end diff --git a/test/adapter/null_adapter_test.rb b/test/adapter/null_adapter_test.rb new file mode 100644 index 000000000..fd56b7ba2 --- /dev/null +++ b/test/adapter/null_adapter_test.rb @@ -0,0 +1,21 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class NullAdapterTest < Minitest::Test + def setup + profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) + serializer = ProfileSerializer.new(profile) + + @adapter = NullAdapter.new(serializer) + end + + def test_it_returns_empty_json + assert_equal('{}', @adapter.to_json) + end + end + end + end +end + diff --git a/test/adapter_test.rb b/test/adapter_test.rb index f9a787731..bf72aabe8 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -15,7 +15,7 @@ def test_serializable_hash_is_abstract_method end end - def test_serializable_hash_is_abstract_method + def test_to_json_is_abstract_method assert_raises(NotImplementedError) do @adapter.to_json(only: [:name]) end From 6cc4fa0258aa57b361160afb2771ab54356416eb Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 08:54:46 +0400 Subject: [PATCH 03/26] * Configure adapter using ActiveModel::Serializer.config.adapter * Get adapter instance using ActiveModel::Serializer::Adapter.adapter_for(serializer) --- README.md | 8 +++- lib/action_controller/serialization.rb | 2 +- lib/active_model/serializer/adapter.rb | 18 +++++++ lib/active_model/serializer/configuration.rb | 1 + test/adapter_test.rb | 49 ++++++++++++++++++++ test/serializers/configuration_test.rb | 4 ++ 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 666d9a2ff..8d7049a51 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,13 @@ by AMS. If you want to use a different adapter, such as a HalAdapter, you can change this in an initializer: ```ruby -ActiveModel::Serializer.default_adapter = ActiveModel::Serializer::Adapter::HalAdapter +ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::HalAdapter +``` + +or + +```ruby +ActiveModel::Serializer.config.adapter = :hal ``` You won't need to implement an adapter unless you wish to use a new format or diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index f5d13287e..9b80887f0 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -12,7 +12,7 @@ def _render_option_json(resource, options) if serializer # omg hax object = serializer.new(resource) - adapter = ActiveModel::Serializer::Adapter::SimpleAdapter.new(object) + adapter = ActiveModel::Serializer::Adapter.adapter_for(object) super(adapter, options) else diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 299a3d1f7..d5cd935d9 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -16,6 +16,24 @@ def serializable_hash(options = {}) def to_json(options = {}) raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' end + + def self.adapter_for(serializer) + adapter_class = case serializer.config.adapter + when Symbol + class_name = "ActiveModel::Serializer::Adapter::#{serializer.config.adapter.to_s.classify}Adapter" + if Object.const_defined?(class_name) + Object.const_get(class_name) + end + when Class + serializer.config.adapter + end + unless adapter_class + valid_adapters = self.constants.map { |klass| ":#{klass.to_s.sub('Adapter', '').downcase}" } + raise ArgumentError, "Unknown adapter: #{serializer.config.adapter}. Valid adapters are: #{valid_adapters}" + end + + adapter_class.new(serializer) + end end end end diff --git a/lib/active_model/serializer/configuration.rb b/lib/active_model/serializer/configuration.rb index ac89443cf..87ed16ab9 100644 --- a/lib/active_model/serializer/configuration.rb +++ b/lib/active_model/serializer/configuration.rb @@ -6,6 +6,7 @@ module Configuration included do |base| base.config.array_serializer = ActiveModel::Serializer::ArraySerializer + base.config.adapter = :simple end end end diff --git a/test/adapter_test.rb b/test/adapter_test.rb index bf72aabe8..32ef6957d 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -21,5 +21,54 @@ def test_to_json_is_abstract_method end end end + + class AdapterForTest < Minitest::Test + def setup + profile = Profile.new + @serializer = ProfileSerializer.new(profile) + @previous_adapter = ActiveModel::Serializer.config.adapter + end + + def teardown + ActiveModel::Serializer.config.adapter = @previous_adapter + end + + def test_returns_default_adapter + adapter = Adapter.adapter_for(@serializer) + assert_kind_of ActiveModel::Serializer::Adapter::SimpleAdapter, adapter + end + + def test_overwrite_adapter_with_symbol + ActiveModel::Serializer.config.adapter = :null + + adapter = Adapter.adapter_for(@serializer) + assert_kind_of ActiveModel::Serializer::Adapter::NullAdapter, adapter + ensure + + end + + def test_overwrite_adapter_with_class + ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::NullAdapter + + adapter = Adapter.adapter_for(@serializer) + assert_kind_of ActiveModel::Serializer::Adapter::NullAdapter, adapter + end + + def test_raises_exception_if_invalid_symbol_given + ActiveModel::Serializer.config.adapter = :unknown + + assert_raises ArgumentError do + Adapter.adapter_for(@serializer) + end + end + + def test_raises_exception_if_it_does_not_know_hot_to_infer_adapter + ActiveModel::Serializer.config.adapter = 42 + + assert_raises ArgumentError do + Adapter.adapter_for(@serializer) + end + end + end end end diff --git a/test/serializers/configuration_test.rb b/test/serializers/configuration_test.rb index 911102292..438372692 100644 --- a/test/serializers/configuration_test.rb +++ b/test/serializers/configuration_test.rb @@ -6,6 +6,10 @@ class ConfigurationTest < Minitest::Test def test_array_serializer assert_equal ActiveModel::Serializer::ArraySerializer, ActiveModel::Serializer.config.array_serializer end + + def test_adapter + assert_equal :simple, ActiveModel::Serializer.config.adapter + end end end end From 553c470e109f69c1689d2b0b0de8f31fcad04ddc Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 09:09:01 +0400 Subject: [PATCH 04/26] Serializer should be available wiithing adapter to inspect attributes and assotions --- lib/active_model/serializer/adapter.rb | 4 +++- lib/active_model/serializer/adapter/simple_adapter.rb | 2 +- test/adapter_test.rb | 8 ++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index d5cd935d9..345c788ca 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -5,8 +5,10 @@ class Adapter autoload :SimpleAdapter autoload :NullAdapter + attr_reader :serializer + def initialize(serializer) - @attributes = serializer.attributes + @serializer = serializer end def serializable_hash(options = {}) diff --git a/lib/active_model/serializer/adapter/simple_adapter.rb b/lib/active_model/serializer/adapter/simple_adapter.rb index 907493071..02b244aef 100644 --- a/lib/active_model/serializer/adapter/simple_adapter.rb +++ b/lib/active_model/serializer/adapter/simple_adapter.rb @@ -3,7 +3,7 @@ class Serializer class Adapter class SimpleAdapter < Adapter def to_json(options={}) - @attributes.each_with_object({}) do |(attr, value), h| + serializer.attributes.each_with_object({}) do |(attr, value), h| h[attr] = value end.to_json # FIXME: why does passing options here cause {}? end diff --git a/test/adapter_test.rb b/test/adapter_test.rb index 32ef6957d..fdc88e4b5 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -5,8 +5,8 @@ class Serializer class AdapterTest < Minitest::Test def setup profile = Profile.new - serializer = ProfileSerializer.new(profile) - @adapter = ActiveModel::Serializer::Adapter.new(serializer) + @serializer = ProfileSerializer.new(profile) + @adapter = ActiveModel::Serializer::Adapter.new(@serializer) end def test_serializable_hash_is_abstract_method @@ -20,6 +20,10 @@ def test_to_json_is_abstract_method @adapter.to_json(only: [:name]) end end + + def test_serializer + assert_equal @serializer, @adapter.serializer + end end class AdapterForTest < Minitest::Test From 7b7d4d890723746ecfb906020164c2c10eee706a Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 09:15:07 +0400 Subject: [PATCH 05/26] Test for SimpleAdapter#serializable_hash --- lib/active_model/serializer/adapter/simple_adapter.rb | 8 ++++++-- test/adapter/simple_adapter_test.rb | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/active_model/serializer/adapter/simple_adapter.rb b/lib/active_model/serializer/adapter/simple_adapter.rb index 02b244aef..da3978969 100644 --- a/lib/active_model/serializer/adapter/simple_adapter.rb +++ b/lib/active_model/serializer/adapter/simple_adapter.rb @@ -2,10 +2,14 @@ module ActiveModel class Serializer class Adapter class SimpleAdapter < Adapter - def to_json(options={}) + def serializable_hash(options = {}) serializer.attributes.each_with_object({}) do |(attr, value), h| h[attr] = value - end.to_json # FIXME: why does passing options here cause {}? + end + end + + def to_json(options={}) + serializable_hash(options).to_json end end end diff --git a/test/adapter/simple_adapter_test.rb b/test/adapter/simple_adapter_test.rb index e03740269..5805184fb 100644 --- a/test/adapter/simple_adapter_test.rb +++ b/test/adapter/simple_adapter_test.rb @@ -11,6 +11,10 @@ def setup @adapter = SimpleAdapter.new(@profile_serializer) end + def test_serializable_hash + assert_equal({name: 'Name 1', description: 'Description 1'}, @adapter.serializable_hash) + end + def test_simple_adapter assert_equal('{"name":"Name 1","description":"Description 1"}', @adapter.to_json) From 2c7906e9ff067e205d2123c4c85ff09cbc9e2fe8 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 09:15:54 +0400 Subject: [PATCH 06/26] Test for NullAdapter#serializable_hash --- test/adapter/null_adapter_test.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/adapter/null_adapter_test.rb b/test/adapter/null_adapter_test.rb index fd56b7ba2..717d7f796 100644 --- a/test/adapter/null_adapter_test.rb +++ b/test/adapter/null_adapter_test.rb @@ -11,6 +11,10 @@ def setup @adapter = NullAdapter.new(serializer) end + def test_serializable_hash + assert_equal({}, @adapter.serializable_hash) + end + def test_it_returns_empty_json assert_equal('{}', @adapter.to_json) end From a6f9dae560dbb3639745efe8d787af4420f4d696 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 09:33:14 +0400 Subject: [PATCH 07/26] Concrete adapter should provide serializable hash for Adapter#to_json method --- lib/active_model/serializer/adapter.rb | 4 ++-- lib/active_model/serializer/adapter/null_adapter.rb | 4 ---- lib/active_model/serializer/adapter/simple_adapter.rb | 4 ---- test/adapter_test.rb | 6 ------ 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 345c788ca..5c2b299e1 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -15,8 +15,8 @@ def serializable_hash(options = {}) raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' end - def to_json(options = {}) - raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' + def to_json(options={}) + serializable_hash(options).to_json end def self.adapter_for(serializer) diff --git a/lib/active_model/serializer/adapter/null_adapter.rb b/lib/active_model/serializer/adapter/null_adapter.rb index 31b8d4ceb..38dd0738f 100644 --- a/lib/active_model/serializer/adapter/null_adapter.rb +++ b/lib/active_model/serializer/adapter/null_adapter.rb @@ -5,10 +5,6 @@ class NullAdapter < Adapter def serializable_hash(options = {}) {} end - - def to_json(options = {}) - serializable_hash.to_json - end end end end diff --git a/lib/active_model/serializer/adapter/simple_adapter.rb b/lib/active_model/serializer/adapter/simple_adapter.rb index da3978969..ebc22a87f 100644 --- a/lib/active_model/serializer/adapter/simple_adapter.rb +++ b/lib/active_model/serializer/adapter/simple_adapter.rb @@ -7,10 +7,6 @@ def serializable_hash(options = {}) h[attr] = value end end - - def to_json(options={}) - serializable_hash(options).to_json - end end end end diff --git a/test/adapter_test.rb b/test/adapter_test.rb index fdc88e4b5..e3d3eb828 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -15,12 +15,6 @@ def test_serializable_hash_is_abstract_method end end - def test_to_json_is_abstract_method - assert_raises(NotImplementedError) do - @adapter.to_json(only: [:name]) - end - end - def test_serializer assert_equal @serializer, @adapter.serializer end From b1f7a5ccda1fab89f5a8f93c57d9a76d4055d977 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 11:02:39 +0400 Subject: [PATCH 08/26] Move Adapter.adapter_for to Serializer.adapter --- lib/action_controller/serialization.rb | 2 +- lib/active_model/serializer.rb | 18 ++++++++++ lib/active_model/serializer/adapter.rb | 18 ---------- test/adapter_test.rb | 49 ------------------------- test/serializers/adapter_for_test.rb | 50 ++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 test/serializers/adapter_for_test.rb diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index 9b80887f0..a69109e5b 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -12,7 +12,7 @@ def _render_option_json(resource, options) if serializer # omg hax object = serializer.new(resource) - adapter = ActiveModel::Serializer::Adapter.adapter_for(object) + adapter = ActiveModel::Serializer.adapter.new(object) super(adapter, options) else diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 255665c70..7addc6e66 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -74,6 +74,24 @@ def self.serializer_for(resource) end end + def self.adapter + adapter_class = case config.adapter + when Symbol + class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}Adapter" + if Object.const_defined?(class_name) + Object.const_get(class_name) + end + when Class + config.adapter + end + unless adapter_class + valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.sub('Adapter', '').downcase}" } + raise ArgumentError, "Unknown adapter: #{config.adapter}. Valid adapters are: #{valid_adapters}" + end + + adapter_class + end + attr_accessor :object def initialize(object) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 5c2b299e1..b5fe211c8 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -18,24 +18,6 @@ def serializable_hash(options = {}) def to_json(options={}) serializable_hash(options).to_json end - - def self.adapter_for(serializer) - adapter_class = case serializer.config.adapter - when Symbol - class_name = "ActiveModel::Serializer::Adapter::#{serializer.config.adapter.to_s.classify}Adapter" - if Object.const_defined?(class_name) - Object.const_get(class_name) - end - when Class - serializer.config.adapter - end - unless adapter_class - valid_adapters = self.constants.map { |klass| ":#{klass.to_s.sub('Adapter', '').downcase}" } - raise ArgumentError, "Unknown adapter: #{serializer.config.adapter}. Valid adapters are: #{valid_adapters}" - end - - adapter_class.new(serializer) - end end end end diff --git a/test/adapter_test.rb b/test/adapter_test.rb index e3d3eb828..737e0c4e7 100644 --- a/test/adapter_test.rb +++ b/test/adapter_test.rb @@ -19,54 +19,5 @@ def test_serializer assert_equal @serializer, @adapter.serializer end end - - class AdapterForTest < Minitest::Test - def setup - profile = Profile.new - @serializer = ProfileSerializer.new(profile) - @previous_adapter = ActiveModel::Serializer.config.adapter - end - - def teardown - ActiveModel::Serializer.config.adapter = @previous_adapter - end - - def test_returns_default_adapter - adapter = Adapter.adapter_for(@serializer) - assert_kind_of ActiveModel::Serializer::Adapter::SimpleAdapter, adapter - end - - def test_overwrite_adapter_with_symbol - ActiveModel::Serializer.config.adapter = :null - - adapter = Adapter.adapter_for(@serializer) - assert_kind_of ActiveModel::Serializer::Adapter::NullAdapter, adapter - ensure - - end - - def test_overwrite_adapter_with_class - ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::NullAdapter - - adapter = Adapter.adapter_for(@serializer) - assert_kind_of ActiveModel::Serializer::Adapter::NullAdapter, adapter - end - - def test_raises_exception_if_invalid_symbol_given - ActiveModel::Serializer.config.adapter = :unknown - - assert_raises ArgumentError do - Adapter.adapter_for(@serializer) - end - end - - def test_raises_exception_if_it_does_not_know_hot_to_infer_adapter - ActiveModel::Serializer.config.adapter = 42 - - assert_raises ArgumentError do - Adapter.adapter_for(@serializer) - end - end - end end end diff --git a/test/serializers/adapter_for_test.rb b/test/serializers/adapter_for_test.rb new file mode 100644 index 000000000..668dd6b08 --- /dev/null +++ b/test/serializers/adapter_for_test.rb @@ -0,0 +1,50 @@ +module ActiveModel + class Serializer + class AdapterForTest < Minitest::Test + def setup + @previous_adapter = ActiveModel::Serializer.config.adapter + end + + def teardown + ActiveModel::Serializer.config.adapter = @previous_adapter + end + + def test_returns_default_adapter + adapter = ActiveModel::Serializer.adapter + assert_equal ActiveModel::Serializer::Adapter::SimpleAdapter, adapter + end + + def test_overwrite_adapter_with_symbol + ActiveModel::Serializer.config.adapter = :null + + adapter = ActiveModel::Serializer.adapter + assert_equal ActiveModel::Serializer::Adapter::NullAdapter, adapter + ensure + + end + + def test_overwrite_adapter_with_class + ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::NullAdapter + + adapter = ActiveModel::Serializer.adapter + assert_equal ActiveModel::Serializer::Adapter::NullAdapter, adapter + end + + def test_raises_exception_if_invalid_symbol_given + ActiveModel::Serializer.config.adapter = :unknown + + assert_raises ArgumentError do + ActiveModel::Serializer.adapter + end + end + + def test_raises_exception_if_it_does_not_know_hot_to_infer_adapter + ActiveModel::Serializer.config.adapter = 42 + + assert_raises ArgumentError do + ActiveModel::Serializer.adapter + end + end + end + end +end From fa4ee9d645dba6131fdf5515a93dfeec31d772dc Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Wed, 27 Aug 2014 11:21:01 +0400 Subject: [PATCH 09/26] Add Serializer#associations --- lib/active_model/serializer.rb | 4 ++++ test/serializers/associations_test.rb | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 7addc6e66..f0fe62ae6 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -103,5 +103,9 @@ def attributes hash[name] = send(name) end end + + def associations + self.class._associations.dup + end end end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index e019c0734..46dcb63b1 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -60,6 +60,25 @@ def test_has_one assert_equal({post: {type: :belongs_to, options: {}}}, @comment_serializer.class._associations) end + + def test_associations + @comment_serializer_class.class_eval do + belongs_to :post + has_many :comments + end + + expected_associations = { + post: { + type: :belongs_to, + options: {} + }, + comments: { + type: :has_many, + options: {} + }, + } + assert_equal(expected_associations, @comment_serializer.associations) + end end end end From 466c7d5dd863aae294b2c4b4c26ad4f16843485e Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 18:46:19 +0400 Subject: [PATCH 10/26] Wrap association into Serializers --- lib/active_model/serializer.rb | 15 ++++- .../serializer/array_serializer.rb | 6 +- test/serializers/associations_test.rb | 58 ++++++------------- 3 files changed, 35 insertions(+), 44 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index f0fe62ae6..106c5e712 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -98,14 +98,23 @@ def initialize(object) @object = object end - def attributes + def attributes(options = {}) self.class._attributes.dup.each_with_object({}) do |name, hash| hash[name] = send(name) end end - def associations - self.class._associations.dup + def associations(options = {}) + self.class._associations.dup.each_with_object({}) do |(name, value), hash| + association = object.send(name) + serializer_class = ActiveModel::Serializer.serializer_for(association) + if serializer_class + serializer = serializer_class.new(association) + hash[name] = serializer + else + hash[name] = association + end + end end end end diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index d385d6bf4..13ab08c70 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -1,7 +1,9 @@ module ActiveModel class Serializer - class ArraySerializer - + class ArraySerializer < Serializer + def initialize(object) + @object = object + end end end end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 46dcb63b1..45fbd8d16 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -26,58 +26,38 @@ def method_missing(meth, *args) end end end + Post = Class.new(Model) + Comment = Class.new(Model) + PostSerializer = Class.new(ActiveModel::Serializer) do + attributes :title, :body + + has_many :comments + end + + CommentSerializer = Class.new(ActiveModel::Serializer) do + attributes :id, :body + + belongs_to :post + end def setup - @post = Model.new({ title: 'New Post', body: 'Body' }) - @comment = Model.new({ id: 1, body: 'ZOMG A COMMENT' }) + @post = Post.new({ title: 'New Post', body: 'Body' }) + @comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' }) @post.comments = [@comment] @comment.post = @post - @post_serializer_class = def_serializer do - attributes :title, :body - end - - @comment_serializer_class = def_serializer do - attributes :id, :body - end - - @post_serializer = @post_serializer_class.new(@post) - @comment_serializer = @comment_serializer_class.new(@comment) + @post_serializer = PostSerializer.new(@post) + @comment_serializer = CommentSerializer.new(@comment) end def test_has_many - @post_serializer_class.class_eval do - has_many :comments - end - assert_equal({comments: {type: :has_many, options: {}}}, @post_serializer.class._associations) + assert_kind_of(ActiveModel::Serializer::ArraySerializer, @post_serializer.associations[:comments]) end def test_has_one - @comment_serializer_class.class_eval do - belongs_to :post - end - assert_equal({post: {type: :belongs_to, options: {}}}, @comment_serializer.class._associations) - end - - def test_associations - @comment_serializer_class.class_eval do - belongs_to :post - has_many :comments - end - - expected_associations = { - post: { - type: :belongs_to, - options: {} - }, - comments: { - type: :has_many, - options: {} - }, - } - assert_equal(expected_associations, @comment_serializer.associations) + assert_kind_of(PostSerializer, @comment_serializer.associations[:post]) end end end From 597765e3b0c1e5eae07cef4be14b59d00760e111 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 18:55:27 +0400 Subject: [PATCH 11/26] start implementing json_api adapter to understand how associations should work --- lib/active_model/serializer/adapter.rb | 1 + .../serializer/adapter/json_api_adapter.rb | 24 ++++++++++++++ test/adapter/json_api_adapter_test.rb | 31 +++++++++++++++++++ test/fixtures/poro.rb | 10 ++++++ test/test_helper.rb | 4 +++ 5 files changed, 70 insertions(+) create mode 100644 lib/active_model/serializer/adapter/json_api_adapter.rb create mode 100644 test/adapter/json_api_adapter_test.rb diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index b5fe211c8..ae831bb32 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -4,6 +4,7 @@ class Adapter extend ActiveSupport::Autoload autoload :SimpleAdapter autoload :NullAdapter + autoload :JsonApiAdapter attr_reader :serializer diff --git a/lib/active_model/serializer/adapter/json_api_adapter.rb b/lib/active_model/serializer/adapter/json_api_adapter.rb new file mode 100644 index 000000000..5f5df7193 --- /dev/null +++ b/lib/active_model/serializer/adapter/json_api_adapter.rb @@ -0,0 +1,24 @@ +module ActiveModel + class Serializer + class Adapter + class JsonApiAdapter < Adapter + def serializable_hash(options = {}) + hash = serializer.attributes.each_with_object({}) do |(attr, value), h| + h[attr] = value + end + + serializer.associations(only: [:id]).each_with_object({}) do |(attr, value), h| + case value + when ActiveModel::Serializer::ArraySerializer + # process has_many association + when ActiveModel::Serializer + # process belongs_to association + else + # what? + end + end + end + end + end + end +end diff --git a/test/adapter/json_api_adapter_test.rb b/test/adapter/json_api_adapter_test.rb new file mode 100644 index 000000000..c49a90c1e --- /dev/null +++ b/test/adapter/json_api_adapter_test.rb @@ -0,0 +1,31 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class JsonApiTest < Minitest::Test + def setup + @post = ::Model.new(title: 'New Post', body: 'Body') + @first_comment = ::Model.new(id: 1, body: 'ZOMG A COMMENT') + @second_comment = ::Model.new(id: 2, body: 'ZOMG ANOTHER COMMENT') + @post.comments = [@first_comment, @second_comment] + @first_comment.post = @post + @second_comment.post = @post + + @post_serializer_class = def_serializer do + attributes :title, :body + has_many :comments + end + + @post_serializer = @post_serializer_class.new(@post) + @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@post_serializer) + end + + def test_includes_comment_ids + assert_equal(['1', '2'], @adapter.serializable_hash[:comments]) + end + end + end + end +end + diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index 005948119..8876a73de 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -10,6 +10,16 @@ def read_attribute_for_serialization(name) @attributes[name] end end + + def method_missing(meth, *args) + if meth.to_s =~ /^(.*)=$/ + @attributes[$1.to_sym] = args[0] + elsif @attributes.key?(meth) + @attributes[meth] + else + super + end + end end class Profile < Model diff --git a/test/test_helper.rb b/test/test_helper.rb index 3fd3776c3..0f5c013b0 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -25,3 +25,7 @@ def setup @routes = TestHelper::Routes end end + +def def_serializer(&block) + Class.new(ActiveModel::Serializer, &block) +end From 1b718b6d48c2003b04a04421e7964b32f8bb1824 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 18:56:22 +0400 Subject: [PATCH 12/26] fix spelling --- lib/active_model/serializer/adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index ae831bb32..cba336193 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -13,7 +13,7 @@ def initialize(serializer) end def serializable_hash(options = {}) - raise NotImplementedError, 'This is abstract method. Should be implemented at concrete adapter.' + raise NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' end def to_json(options={}) From c1fdfc1cdc0e34745ce2e591e8541d782799ee2b Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 19:16:24 +0400 Subject: [PATCH 13/26] First try to implement ArraySerializer --- lib/active_model/serializer.rb | 7 +----- .../serializer/adapter/json_api_adapter.rb | 25 ++++++++++--------- .../serializer/array_serializer.rb | 7 ++++++ test/adapter/json_api_adapter_test.rb | 15 ++++------- test/fixtures/poro.rb | 21 +++++++++++++++- test/serializers/associations_test.rb | 16 ------------ 6 files changed, 46 insertions(+), 45 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 106c5e712..1bfdf825d 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -108,12 +108,7 @@ def associations(options = {}) self.class._associations.dup.each_with_object({}) do |(name, value), hash| association = object.send(name) serializer_class = ActiveModel::Serializer.serializer_for(association) - if serializer_class - serializer = serializer_class.new(association) - hash[name] = serializer - else - hash[name] = association - end + hash[name] = serializer_class.new(association) end end end diff --git a/lib/active_model/serializer/adapter/json_api_adapter.rb b/lib/active_model/serializer/adapter/json_api_adapter.rb index 5f5df7193..14094417f 100644 --- a/lib/active_model/serializer/adapter/json_api_adapter.rb +++ b/lib/active_model/serializer/adapter/json_api_adapter.rb @@ -3,20 +3,21 @@ class Serializer class Adapter class JsonApiAdapter < Adapter def serializable_hash(options = {}) - hash = serializer.attributes.each_with_object({}) do |(attr, value), h| - h[attr] = value - end + hash = serializer.attributes - serializer.associations(only: [:id]).each_with_object({}) do |(attr, value), h| - case value - when ActiveModel::Serializer::ArraySerializer - # process has_many association - when ActiveModel::Serializer - # process belongs_to association - else - # what? - end + associations = serializer.associations(only: [:id]).each_with_object({}) do |(attr, value), h| + h[attr] = case value + when ActiveModel::Serializer::ArraySerializer + value.attributes(options).map do |item| + item.id + end.to_a + when ActiveModel::Serializer + # process belongs_to association + else + # what? + end end + hash.merge(associations) end end end diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index 13ab08c70..c2751f4bd 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -4,6 +4,13 @@ class ArraySerializer < Serializer def initialize(object) @object = object end + + def attributes(options = {}) + object.map do |item| + serializer_class = ActiveModel::Serializer.serializer_for(item) + serializer_class.new(item) + end + end end end end diff --git a/test/adapter/json_api_adapter_test.rb b/test/adapter/json_api_adapter_test.rb index c49a90c1e..dc09e3971 100644 --- a/test/adapter/json_api_adapter_test.rb +++ b/test/adapter/json_api_adapter_test.rb @@ -5,24 +5,19 @@ class Serializer class Adapter class JsonApiTest < Minitest::Test def setup - @post = ::Model.new(title: 'New Post', body: 'Body') - @first_comment = ::Model.new(id: 1, body: 'ZOMG A COMMENT') - @second_comment = ::Model.new(id: 2, body: 'ZOMG ANOTHER COMMENT') + @post = Post.new(title: 'New Post', body: 'Body') + @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') @post.comments = [@first_comment, @second_comment] @first_comment.post = @post @second_comment.post = @post - @post_serializer_class = def_serializer do - attributes :title, :body - has_many :comments - end - - @post_serializer = @post_serializer_class.new(@post) + @post_serializer = PostSerializer.new(@post) @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@post_serializer) end def test_includes_comment_ids - assert_equal(['1', '2'], @adapter.serializable_hash[:comments]) + assert_equal([1, 2], @adapter.serializable_hash[:comments]) end end end diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index 8876a73de..8359fcb74 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -5,12 +5,16 @@ def initialize(hash={}) def read_attribute_for_serialization(name) if name == :id || name == 'id' - object_id + id else @attributes[name] end end + def id + @attributes[:id] || @attributes['id'] || object_id + end + def method_missing(meth, *args) if meth.to_s =~ /^(.*)=$/ @attributes[$1.to_sym] = args[0] @@ -28,3 +32,18 @@ class Profile < Model class ProfileSerializer < ActiveModel::Serializer attributes :name, :description end + +Post = Class.new(Model) +Comment = Class.new(Model) + +PostSerializer = Class.new(ActiveModel::Serializer) do + attributes :title, :body, :id + + has_many :comments +end + +CommentSerializer = Class.new(ActiveModel::Serializer) do + attributes :id, :body + + belongs_to :post +end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 45fbd8d16..56603b2c5 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -3,10 +3,6 @@ module ActiveModel class Serializer class AssocationsTest < Minitest::Test - def def_serializer(&block) - Class.new(ActiveModel::Serializer, &block) - end - class Model def initialize(hash={}) @attributes = hash @@ -26,19 +22,7 @@ def method_missing(meth, *args) end end end - Post = Class.new(Model) - Comment = Class.new(Model) - PostSerializer = Class.new(ActiveModel::Serializer) do - attributes :title, :body - - has_many :comments - end - - CommentSerializer = Class.new(ActiveModel::Serializer) do - attributes :id, :body - belongs_to :post - end def setup @post = Post.new({ title: 'New Post', body: 'Body' }) From 85b4b85bb3c4222bc5027edc3710fd4167d86e85 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 22:58:30 +0400 Subject: [PATCH 14/26] Remove 1.9.3 from CI build as we dropped support --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 49262de18..eef6521ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: ruby rvm: - - 1.9.3 - 2.0.0 - 2.1.1 - jruby-19mode From 85ff8123fdcd9cbaa980f5e203195a784f9a5dc1 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Thu, 28 Aug 2014 23:03:23 +0400 Subject: [PATCH 15/26] Include Enumerable to ArraySerializer --- lib/active_model/serializer/adapter/json_api_adapter.rb | 4 +--- lib/active_model/serializer/array_serializer.rb | 9 ++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/active_model/serializer/adapter/json_api_adapter.rb b/lib/active_model/serializer/adapter/json_api_adapter.rb index 14094417f..d82fdd7ff 100644 --- a/lib/active_model/serializer/adapter/json_api_adapter.rb +++ b/lib/active_model/serializer/adapter/json_api_adapter.rb @@ -8,9 +8,7 @@ def serializable_hash(options = {}) associations = serializer.associations(only: [:id]).each_with_object({}) do |(attr, value), h| h[attr] = case value when ActiveModel::Serializer::ArraySerializer - value.attributes(options).map do |item| - item.id - end.to_a + value.map(&:id) when ActiveModel::Serializer # process belongs_to association else diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index c2751f4bd..de4adfdc7 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -1,12 +1,11 @@ module ActiveModel class Serializer class ArraySerializer < Serializer - def initialize(object) - @object = object - end + include Enumerable + delegate :each, to: :object - def attributes(options = {}) - object.map do |item| + def initialize(object) + @object = object.map do |item| serializer_class = ActiveModel::Serializer.serializer_for(item) serializer_class.new(item) end From 3dd4928279bfbca638f9ff43673fc50717547381 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 10:58:14 +0400 Subject: [PATCH 16/26] * Do not ingerit array serializer from Serializer * Tests for ArraySerializer --- .../serializer/array_serializer.rb | 12 ++++----- test/array_serializer_test.rb | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 test/array_serializer_test.rb diff --git a/lib/active_model/serializer/array_serializer.rb b/lib/active_model/serializer/array_serializer.rb index de4adfdc7..697c44542 100644 --- a/lib/active_model/serializer/array_serializer.rb +++ b/lib/active_model/serializer/array_serializer.rb @@ -1,13 +1,13 @@ module ActiveModel class Serializer - class ArraySerializer < Serializer + class ArraySerializer include Enumerable - delegate :each, to: :object + delegate :each, to: :@objects - def initialize(object) - @object = object.map do |item| - serializer_class = ActiveModel::Serializer.serializer_for(item) - serializer_class.new(item) + def initialize(objects, options = {}) + @objects = objects.map do |object| + serializer_class = ActiveModel::Serializer.serializer_for(object) + serializer_class.new(object) end end end diff --git a/test/array_serializer_test.rb b/test/array_serializer_test.rb new file mode 100644 index 000000000..66840a4ac --- /dev/null +++ b/test/array_serializer_test.rb @@ -0,0 +1,27 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class ArraySerializerTest < Minitest::Test + def setup + @comment = Comment.new + @post= Post.new + @serializer = ArraySerializer.new([@comment, @post]) + end + + def test_respond_to_each + assert_respond_to @serializer, :each + end + + def test_each_object_should_be_serializer_with_appropriate_serializer + serializers = @serializer.to_a + + assert_kind_of CommentSerializer, serializers.first + assert_kind_of Comment, serializers.first.object + + assert_kind_of PostSerializer, serializers.last + assert_kind_of Post, serializers.last.object + end + end + end +end From 6496b0846437cd335b69df4e9fe79d93cdb9bade Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 11:01:39 +0400 Subject: [PATCH 17/26] rename simple adapter to json --- lib/active_model/serializer/adapter.rb | 2 +- .../serializer/adapter/{simple_adapter.rb => json_adapter.rb} | 2 +- lib/active_model/serializer/configuration.rb | 2 +- lib/active_model_serializers.rb | 1 - test/adapter/{simple_adapter_test.rb => json_adapter_test.rb} | 4 ++-- test/serializers/adapter_for_test.rb | 2 +- test/serializers/configuration_test.rb | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) rename lib/active_model/serializer/adapter/{simple_adapter.rb => json_adapter.rb} (87%) rename test/adapter/{simple_adapter_test.rb => json_adapter_test.rb} (85%) diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index cba336193..87da12233 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -2,7 +2,7 @@ module ActiveModel class Serializer class Adapter extend ActiveSupport::Autoload - autoload :SimpleAdapter + autoload :JsonAdapter autoload :NullAdapter autoload :JsonApiAdapter diff --git a/lib/active_model/serializer/adapter/simple_adapter.rb b/lib/active_model/serializer/adapter/json_adapter.rb similarity index 87% rename from lib/active_model/serializer/adapter/simple_adapter.rb rename to lib/active_model/serializer/adapter/json_adapter.rb index ebc22a87f..8aba1c691 100644 --- a/lib/active_model/serializer/adapter/simple_adapter.rb +++ b/lib/active_model/serializer/adapter/json_adapter.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer class Adapter - class SimpleAdapter < Adapter + class JsonAdapter < Adapter def serializable_hash(options = {}) serializer.attributes.each_with_object({}) do |(attr, value), h| h[attr] = value diff --git a/lib/active_model/serializer/configuration.rb b/lib/active_model/serializer/configuration.rb index 87ed16ab9..ef57262c4 100644 --- a/lib/active_model/serializer/configuration.rb +++ b/lib/active_model/serializer/configuration.rb @@ -6,7 +6,7 @@ module Configuration included do |base| base.config.array_serializer = ActiveModel::Serializer::ArraySerializer - base.config.adapter = :simple + base.config.adapter = :json end end end diff --git a/lib/active_model_serializers.rb b/lib/active_model_serializers.rb index 894ca8695..c96b90a92 100644 --- a/lib/active_model_serializers.rb +++ b/lib/active_model_serializers.rb @@ -1,7 +1,6 @@ require "active_model" require "active_model/serializer/version" require "active_model/serializer" -require "active_model/serializer/adapter/simple_adapter" begin require 'action_controller' diff --git a/test/adapter/simple_adapter_test.rb b/test/adapter/json_adapter_test.rb similarity index 85% rename from test/adapter/simple_adapter_test.rb rename to test/adapter/json_adapter_test.rb index 5805184fb..b4dfa3739 100644 --- a/test/adapter/simple_adapter_test.rb +++ b/test/adapter/json_adapter_test.rb @@ -3,12 +3,12 @@ module ActiveModel class Serializer class Adapter - class SimpleAdapterTest < Minitest::Test + class JsonAdapterTest < Minitest::Test def setup @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) @profile_serializer = ProfileSerializer.new(@profile) - @adapter = SimpleAdapter.new(@profile_serializer) + @adapter = JsonAdapter.new(@profile_serializer) end def test_serializable_hash diff --git a/test/serializers/adapter_for_test.rb b/test/serializers/adapter_for_test.rb index 668dd6b08..651e511ae 100644 --- a/test/serializers/adapter_for_test.rb +++ b/test/serializers/adapter_for_test.rb @@ -11,7 +11,7 @@ def teardown def test_returns_default_adapter adapter = ActiveModel::Serializer.adapter - assert_equal ActiveModel::Serializer::Adapter::SimpleAdapter, adapter + assert_equal ActiveModel::Serializer::Adapter::JsonAdapter, adapter end def test_overwrite_adapter_with_symbol diff --git a/test/serializers/configuration_test.rb b/test/serializers/configuration_test.rb index 438372692..eec004364 100644 --- a/test/serializers/configuration_test.rb +++ b/test/serializers/configuration_test.rb @@ -8,7 +8,7 @@ def test_array_serializer end def test_adapter - assert_equal :simple, ActiveModel::Serializer.config.adapter + assert_equal :json, ActiveModel::Serializer.config.adapter end end end From 6bb4501f67fe89cdb27537a71d8623178d9e5b63 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 11:37:27 +0400 Subject: [PATCH 18/26] JsonApi adapter: serialize association --- .../serializer/adapter/json_api_adapter.rb | 36 +++++++++++++------ test/adapter/json_api/belongs_to_test.rb | 29 +++++++++++++++ test/adapter/json_api/has_many.rb | 34 ++++++++++++++++++ test/adapter/json_api_adapter_test.rb | 26 -------------- 4 files changed, 88 insertions(+), 37 deletions(-) create mode 100644 test/adapter/json_api/belongs_to_test.rb create mode 100644 test/adapter/json_api/has_many.rb delete mode 100644 test/adapter/json_api_adapter_test.rb diff --git a/lib/active_model/serializer/adapter/json_api_adapter.rb b/lib/active_model/serializer/adapter/json_api_adapter.rb index d82fdd7ff..0a5ce947a 100644 --- a/lib/active_model/serializer/adapter/json_api_adapter.rb +++ b/lib/active_model/serializer/adapter/json_api_adapter.rb @@ -3,19 +3,33 @@ class Serializer class Adapter class JsonApiAdapter < Adapter def serializable_hash(options = {}) - hash = serializer.attributes + @hash = serializer.attributes - associations = serializer.associations(only: [:id]).each_with_object({}) do |(attr, value), h| - h[attr] = case value - when ActiveModel::Serializer::ArraySerializer - value.map(&:id) - when ActiveModel::Serializer - # process belongs_to association - else - # what? - end + serializer.associations.each do |name, association| + @hash[:links] ||= {} + @hash[:linked] ||= {} + if association.respond_to?(:each) + add_links(name, association) + else + add_link(name, association) + end end - hash.merge(associations) + @hash + end + + def add_links(name, serializers) + @hash[:links][name] ||= [] + @hash[:linked][name] ||= [] + @hash[:links][name] += serializers.map(&:id) + @hash[:linked][name] += serializers.map(&:attributes) + end + + def add_link(name, serializer) + plural_name = name.to_s.pluralize.to_sym + @hash[:linked][plural_name] ||= [] + + @hash[:links][name] = serializer.id + @hash[:linked][plural_name].push serializer.attributes end end end diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb new file mode 100644 index 000000000..d4beddf90 --- /dev/null +++ b/test/adapter/json_api/belongs_to_test.rb @@ -0,0 +1,29 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class JsonApiAdapter + class BelongsToTest < Minitest::Test + def setup + @post = Post.new(id: 42, title: 'New Post', body: 'Body') + @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @post.comments = [@comment] + @comment.post = @post + + @serializer = CommentSerializer.new(@comment) + @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@serializer) + end + + def test_includes_post_id + assert_equal(42, @adapter.serializable_hash[:links][:post]) + end + + def test_includes_linked_post + assert_equal([{id: 42, title: 'New Post', body: 'Body'}], @adapter.serializable_hash[:linked][:posts]) + end + end + end + end + end +end diff --git a/test/adapter/json_api/has_many.rb b/test/adapter/json_api/has_many.rb new file mode 100644 index 000000000..d9377a82e --- /dev/null +++ b/test/adapter/json_api/has_many.rb @@ -0,0 +1,34 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class JsonApiAdapter + class HasManyTest < Minitest::Test + def setup + @post = Post.new(title: 'New Post', body: 'Body') + @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') + @post.comments = [@first_comment, @second_comment] + @first_comment.post = @post + @second_comment.post = @post + + @serializer = PostSerializer.new(@post) + @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@serializer) + end + + def test_includes_comment_ids + assert_equal([1, 2], @adapter.serializable_hash[:links][:comments]) + end + + def test_includes_linked_comments + assert_equal([ + {id: 1, body: 'ZOMG A COMMENT'}, + {id: 2, body: 'ZOMG ANOTHER COMMENT'} + ], @adapter.serializable_hash[:linked][:comments]) + end + end + end + end + end +end diff --git a/test/adapter/json_api_adapter_test.rb b/test/adapter/json_api_adapter_test.rb deleted file mode 100644 index dc09e3971..000000000 --- a/test/adapter/json_api_adapter_test.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'test_helper' - -module ActiveModel - class Serializer - class Adapter - class JsonApiTest < Minitest::Test - def setup - @post = Post.new(title: 'New Post', body: 'Body') - @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') - @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') - @post.comments = [@first_comment, @second_comment] - @first_comment.post = @post - @second_comment.post = @post - - @post_serializer = PostSerializer.new(@post) - @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@post_serializer) - end - - def test_includes_comment_ids - assert_equal([1, 2], @adapter.serializable_hash[:comments]) - end - end - end - end -end - From e45e5a82b70d2e93bdea0eb80bd864b89906f33a Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 11:40:56 +0400 Subject: [PATCH 19/26] Remove 'Adapter' suffix from adapters since they are in Adapter:: namespace --- lib/active_model/serializer.rb | 2 +- lib/active_model/serializer/adapter.rb | 6 +++--- .../serializer/adapter/{json_adapter.rb => json.rb} | 2 +- .../adapter/{json_api_adapter.rb => json_api.rb} | 2 +- .../serializer/adapter/{null_adapter.rb => null.rb} | 2 +- test/adapter/json_api/belongs_to_test.rb | 4 ++-- test/adapter/json_api/has_many.rb | 2 +- test/adapter/{json_adapter_test.rb => json_test.rb} | 2 +- test/adapter/{null_adapter_test.rb => null_test.rb} | 4 ++-- test/serializers/adapter_for_test.rb | 8 ++++---- 10 files changed, 17 insertions(+), 17 deletions(-) rename lib/active_model/serializer/adapter/{json_adapter.rb => json.rb} (88%) rename lib/active_model/serializer/adapter/{json_api_adapter.rb => json_api.rb} (96%) rename lib/active_model/serializer/adapter/{null_adapter.rb => null.rb} (81%) rename test/adapter/{json_adapter_test.rb => json_test.rb} (92%) rename test/adapter/{null_adapter_test.rb => null_test.rb} (84%) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 1bfdf825d..0191a8830 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -77,7 +77,7 @@ def self.serializer_for(resource) def self.adapter adapter_class = case config.adapter when Symbol - class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}Adapter" + class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" if Object.const_defined?(class_name) Object.const_get(class_name) end diff --git a/lib/active_model/serializer/adapter.rb b/lib/active_model/serializer/adapter.rb index 87da12233..2fae98ffe 100644 --- a/lib/active_model/serializer/adapter.rb +++ b/lib/active_model/serializer/adapter.rb @@ -2,9 +2,9 @@ module ActiveModel class Serializer class Adapter extend ActiveSupport::Autoload - autoload :JsonAdapter - autoload :NullAdapter - autoload :JsonApiAdapter + autoload :Json + autoload :Null + autoload :JsonApi attr_reader :serializer diff --git a/lib/active_model/serializer/adapter/json_adapter.rb b/lib/active_model/serializer/adapter/json.rb similarity index 88% rename from lib/active_model/serializer/adapter/json_adapter.rb rename to lib/active_model/serializer/adapter/json.rb index 8aba1c691..68dba2209 100644 --- a/lib/active_model/serializer/adapter/json_adapter.rb +++ b/lib/active_model/serializer/adapter/json.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer class Adapter - class JsonAdapter < Adapter + class Json < Adapter def serializable_hash(options = {}) serializer.attributes.each_with_object({}) do |(attr, value), h| h[attr] = value diff --git a/lib/active_model/serializer/adapter/json_api_adapter.rb b/lib/active_model/serializer/adapter/json_api.rb similarity index 96% rename from lib/active_model/serializer/adapter/json_api_adapter.rb rename to lib/active_model/serializer/adapter/json_api.rb index 0a5ce947a..22b44f898 100644 --- a/lib/active_model/serializer/adapter/json_api_adapter.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer class Adapter - class JsonApiAdapter < Adapter + class JsonApi < Adapter def serializable_hash(options = {}) @hash = serializer.attributes diff --git a/lib/active_model/serializer/adapter/null_adapter.rb b/lib/active_model/serializer/adapter/null.rb similarity index 81% rename from lib/active_model/serializer/adapter/null_adapter.rb rename to lib/active_model/serializer/adapter/null.rb index 38dd0738f..547c08ba8 100644 --- a/lib/active_model/serializer/adapter/null_adapter.rb +++ b/lib/active_model/serializer/adapter/null.rb @@ -1,7 +1,7 @@ module ActiveModel class Serializer class Adapter - class NullAdapter < Adapter + class Null < Adapter def serializable_hash(options = {}) {} end diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index d4beddf90..151fd8cce 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -3,7 +3,7 @@ module ActiveModel class Serializer class Adapter - class JsonApiAdapter + class JsonApi class BelongsToTest < Minitest::Test def setup @post = Post.new(id: 42, title: 'New Post', body: 'Body') @@ -12,7 +12,7 @@ def setup @comment.post = @post @serializer = CommentSerializer.new(@comment) - @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@serializer) + @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer) end def test_includes_post_id diff --git a/test/adapter/json_api/has_many.rb b/test/adapter/json_api/has_many.rb index d9377a82e..ad8c3c2f1 100644 --- a/test/adapter/json_api/has_many.rb +++ b/test/adapter/json_api/has_many.rb @@ -3,7 +3,7 @@ module ActiveModel class Serializer class Adapter - class JsonApiAdapter + class JsonApi class HasManyTest < Minitest::Test def setup @post = Post.new(title: 'New Post', body: 'Body') diff --git a/test/adapter/json_adapter_test.rb b/test/adapter/json_test.rb similarity index 92% rename from test/adapter/json_adapter_test.rb rename to test/adapter/json_test.rb index b4dfa3739..f8e753da6 100644 --- a/test/adapter/json_adapter_test.rb +++ b/test/adapter/json_test.rb @@ -8,7 +8,7 @@ def setup @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) @profile_serializer = ProfileSerializer.new(@profile) - @adapter = JsonAdapter.new(@profile_serializer) + @adapter = Json.new(@profile_serializer) end def test_serializable_hash diff --git a/test/adapter/null_adapter_test.rb b/test/adapter/null_test.rb similarity index 84% rename from test/adapter/null_adapter_test.rb rename to test/adapter/null_test.rb index 717d7f796..9f23b778e 100644 --- a/test/adapter/null_adapter_test.rb +++ b/test/adapter/null_test.rb @@ -3,12 +3,12 @@ module ActiveModel class Serializer class Adapter - class NullAdapterTest < Minitest::Test + class NullTest < Minitest::Test def setup profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) serializer = ProfileSerializer.new(profile) - @adapter = NullAdapter.new(serializer) + @adapter = Null.new(serializer) end def test_serializable_hash diff --git a/test/serializers/adapter_for_test.rb b/test/serializers/adapter_for_test.rb index 651e511ae..606410803 100644 --- a/test/serializers/adapter_for_test.rb +++ b/test/serializers/adapter_for_test.rb @@ -11,23 +11,23 @@ def teardown def test_returns_default_adapter adapter = ActiveModel::Serializer.adapter - assert_equal ActiveModel::Serializer::Adapter::JsonAdapter, adapter + assert_equal ActiveModel::Serializer::Adapter::Json, adapter end def test_overwrite_adapter_with_symbol ActiveModel::Serializer.config.adapter = :null adapter = ActiveModel::Serializer.adapter - assert_equal ActiveModel::Serializer::Adapter::NullAdapter, adapter + assert_equal ActiveModel::Serializer::Adapter::Null, adapter ensure end def test_overwrite_adapter_with_class - ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::NullAdapter + ActiveModel::Serializer.config.adapter = ActiveModel::Serializer::Adapter::Null adapter = ActiveModel::Serializer.adapter - assert_equal ActiveModel::Serializer::Adapter::NullAdapter, adapter + assert_equal ActiveModel::Serializer::Adapter::Null, adapter end def test_raises_exception_if_invalid_symbol_given From 139609355f0b2e87a547f6520f2bd5d5c2702545 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 13:01:01 +0400 Subject: [PATCH 20/26] Object.const_get differs on 2.0 and 2.1.2. So rescue from NameError --- lib/active_model/serializer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 00d107676..373e90786 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -80,8 +80,10 @@ def self.adapter adapter_class = case config.adapter when Symbol class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" - if Object.const_defined?(class_name) + begin Object.const_get(class_name) + rescue NameError + nil end when Class config.adapter From 77847d7c02e2de9bf90b90bad76be5221778cd64 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 13:48:06 +0400 Subject: [PATCH 21/26] User String#constantize instead of Object.const_get --- lib/active_model/serializer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 373e90786..e21d99df4 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -69,7 +69,7 @@ def self.serializer_for(resource) serializer_name = "#{resource.class.name}Serializer" begin - Object.const_get(serializer_name) + serializer_name.constantize rescue NameError nil end @@ -81,7 +81,7 @@ def self.adapter when Symbol class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" begin - Object.const_get(class_name) + class_name.constantize rescue NameError nil end From 7293072670ced148b4609fa679e93bd3020835cb Mon Sep 17 00:00:00 2001 From: Tema Bolshakov Date: Fri, 29 Aug 2014 13:48:39 +0400 Subject: [PATCH 22/26] Revert "Remove 1.9.3 from CI build as we dropped support" This reverts commit 85b4b85bb3c4222bc5027edc3710fd4167d86e85. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 617012415..d54edc2cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: ruby rvm: + - 1.9.3 - 2.0.0 - 2.1.1 - jruby-19mode From ff37b6260d3757faa44a51e5d675ed0dce45f840 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov and Dmitry Myaskovskiy Date: Fri, 29 Aug 2014 19:40:01 +0400 Subject: [PATCH 23/26] test for json adapter --- lib/active_model/serializer/adapter/json.rb | 11 ++++++-- test/adapter/json/belongs_to_test.rb | 25 +++++++++++++++++ test/adapter/json/has_many_test.rb | 31 +++++++++++++++++++++ test/adapter/json_api/has_many.rb | 2 +- test/adapter/json_test.rb | 27 +++++++++--------- 5 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 test/adapter/json/belongs_to_test.rb create mode 100644 test/adapter/json/has_many_test.rb diff --git a/lib/active_model/serializer/adapter/json.rb b/lib/active_model/serializer/adapter/json.rb index 68dba2209..970de04b1 100644 --- a/lib/active_model/serializer/adapter/json.rb +++ b/lib/active_model/serializer/adapter/json.rb @@ -3,9 +3,16 @@ class Serializer class Adapter class Json < Adapter def serializable_hash(options = {}) - serializer.attributes.each_with_object({}) do |(attr, value), h| - h[attr] = value + @hash = serializer.attributes + + serializer.associations.each do |name, association| + if association.respond_to?(:each) + @hash[name] = association.map(&:attributes) + else + @hash[name] = association.attributes + end end + @hash end end end diff --git a/test/adapter/json/belongs_to_test.rb b/test/adapter/json/belongs_to_test.rb new file mode 100644 index 000000000..498f1d986 --- /dev/null +++ b/test/adapter/json/belongs_to_test.rb @@ -0,0 +1,25 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class Json + class BelongsToTest < Minitest::Test + def setup + @post = Post.new(id: 42, title: 'New Post', body: 'Body') + @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @post.comments = [@comment] + @comment.post = @post + + @serializer = CommentSerializer.new(@comment) + @adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer) + end + + def test_includes_post + assert_equal({id: 42, title: 'New Post', body: 'Body'}, @adapter.serializable_hash[:post]) + end + end + end + end + end +end diff --git a/test/adapter/json/has_many_test.rb b/test/adapter/json/has_many_test.rb new file mode 100644 index 000000000..d1534e6b7 --- /dev/null +++ b/test/adapter/json/has_many_test.rb @@ -0,0 +1,31 @@ +require 'test_helper' + +module ActiveModel + class Serializer + class Adapter + class Json + class HasManyTestTest < Minitest::Test + def setup + @post = Post.new(title: 'New Post', body: 'Body') + @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') + @post.comments = [@first_comment, @second_comment] + @first_comment.post = @post + @second_comment.post = @post + + @serializer = PostSerializer.new(@post) + @adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer) + end + + def test_has_many + assert_equal([ + {id: 1, body: 'ZOMG A COMMENT'}, + {id: 2, body: 'ZOMG ANOTHER COMMENT'} + ], @adapter.serializable_hash[:comments]) + end + end + end + end + end +end + diff --git a/test/adapter/json_api/has_many.rb b/test/adapter/json_api/has_many.rb index ad8c3c2f1..435079d7c 100644 --- a/test/adapter/json_api/has_many.rb +++ b/test/adapter/json_api/has_many.rb @@ -14,7 +14,7 @@ def setup @second_comment.post = @post @serializer = PostSerializer.new(@post) - @adapter = ActiveModel::Serializer::Adapter::JsonApiAdapter.new(@serializer) + @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer) end def test_includes_comment_ids diff --git a/test/adapter/json_test.rb b/test/adapter/json_test.rb index f8e753da6..1d2e35a64 100644 --- a/test/adapter/json_test.rb +++ b/test/adapter/json_test.rb @@ -3,23 +3,24 @@ module ActiveModel class Serializer class Adapter - class JsonAdapterTest < Minitest::Test + class JsonTest < Minitest::Test def setup - @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }) - @profile_serializer = ProfileSerializer.new(@profile) + @post = Post.new(title: 'New Post', body: 'Body') + @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') + @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') + @post.comments = [@first_comment, @second_comment] + @first_comment.post = @post + @second_comment.post = @post - @adapter = Json.new(@profile_serializer) + @serializer = PostSerializer.new(@post) + @adapter = ActiveModel::Serializer::Adapter::Json.new(@serializer) end - def test_serializable_hash - assert_equal({name: 'Name 1', description: 'Description 1'}, @adapter.serializable_hash) - end - - def test_simple_adapter - assert_equal('{"name":"Name 1","description":"Description 1"}', - @adapter.to_json) - -JSON + def test_has_many + assert_equal([ + {id: 1, body: 'ZOMG A COMMENT'}, + {id: 2, body: 'ZOMG ANOTHER COMMENT'} + ], @adapter.serializable_hash[:comments]) end end end From 45a47a1c4dee14734f0677ec79d29c4415dbeaa9 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov and Dmitry Myaskovskiy Date: Fri, 29 Aug 2014 19:47:29 +0400 Subject: [PATCH 24/26] safe_constantize instead of rescue --- lib/active_model/serializer.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index e21d99df4..ff0b4b1af 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -66,13 +66,8 @@ def self.serializer_for(resource) if resource.respond_to?(:to_ary) config.array_serializer else - serializer_name = "#{resource.class.name}Serializer" - - begin - serializer_name.constantize - rescue NameError - nil - end + serializer_class = "#{resource.class.name}Serializer" + serializer_class.safe_constantize end end @@ -80,11 +75,7 @@ def self.adapter adapter_class = case config.adapter when Symbol class_name = "ActiveModel::Serializer::Adapter::#{config.adapter.to_s.classify}" - begin - class_name.constantize - rescue NameError - nil - end + class_name.safe_constantize when Class config.adapter end From 258b5953e24b222d0d51f1a4c336eae16342055b Mon Sep 17 00:00:00 2001 From: Tema Bolshakov and Dmitry Myaskovskiy Date: Fri, 29 Aug 2014 19:47:46 +0400 Subject: [PATCH 25/26] clean up code --- lib/active_model/serializer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index ff0b4b1af..44954ed41 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -80,7 +80,7 @@ def self.adapter config.adapter end unless adapter_class - valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.sub('Adapter', '').downcase}" } + valid_adapters = Adapter.constants.map { |klass| ":#{klass.to_s.downcase}" } raise ArgumentError, "Unknown adapter: #{config.adapter}. Valid adapters are: #{valid_adapters}" end From 71a43a432ae064729d2debe90388647399d53ff8 Mon Sep 17 00:00:00 2001 From: Tema Bolshakov and Dmitry Myaskovskiy Date: Fri, 29 Aug 2014 20:16:11 +0400 Subject: [PATCH 26/26] Pass options to associations --- lib/active_model/serializer.rb | 10 +++++++--- lib/active_model/serializer/adapter/json.rb | 9 +++++---- lib/active_model/serializer/adapter/json_api.rb | 16 +++++++++------- test/serializers/associations_test.rb | 12 ++++++++++-- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 44954ed41..05a79900e 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -99,11 +99,15 @@ def attributes(options = {}) end end - def associations(options = {}) - self.class._associations.dup.each_with_object({}) do |(name, value), hash| + def each_association(&block) + self.class._associations.dup.each do |name, options| association = object.send(name) serializer_class = ActiveModel::Serializer.serializer_for(association) - hash[name] = serializer_class.new(association) + serializer = serializer_class.new(association) + + if block_given? + block.call(name, serializer, options[:options]) + end end end end diff --git a/lib/active_model/serializer/adapter/json.rb b/lib/active_model/serializer/adapter/json.rb index 970de04b1..f37fc8d41 100644 --- a/lib/active_model/serializer/adapter/json.rb +++ b/lib/active_model/serializer/adapter/json.rb @@ -3,13 +3,14 @@ class Serializer class Adapter class Json < Adapter def serializable_hash(options = {}) - @hash = serializer.attributes + @hash = serializer.attributes(options) - serializer.associations.each do |name, association| + serializer.each_association do |name, association, options| if association.respond_to?(:each) - @hash[name] = association.map(&:attributes) + array_serializer = association + @hash[name] = array_serializer.map { |item| item.attributes(options) } else - @hash[name] = association.attributes + @hash[name] = association.attributes(options) end end @hash diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 22b44f898..a4f516dc8 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -5,31 +5,33 @@ class JsonApi < Adapter def serializable_hash(options = {}) @hash = serializer.attributes - serializer.associations.each do |name, association| + serializer.each_association do |name, association, options| @hash[:links] ||= {} @hash[:linked] ||= {} + if association.respond_to?(:each) - add_links(name, association) + add_links(name, association, options) else - add_link(name, association) + add_link(name, association, options) end end + @hash end - def add_links(name, serializers) + def add_links(name, serializers, options) @hash[:links][name] ||= [] @hash[:linked][name] ||= [] @hash[:links][name] += serializers.map(&:id) - @hash[:linked][name] += serializers.map(&:attributes) + @hash[:linked][name] += serializers.map { |item| item.attributes(options) } end - def add_link(name, serializer) + def add_link(name, serializer, options) plural_name = name.to_s.pluralize.to_sym @hash[:linked][plural_name] ||= [] @hash[:links][name] = serializer.id - @hash[:linked][plural_name].push serializer.attributes + @hash[:linked][plural_name].push serializer.attributes(options) end end end diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 56603b2c5..6d69b563c 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -36,12 +36,20 @@ def setup def test_has_many assert_equal({comments: {type: :has_many, options: {}}}, @post_serializer.class._associations) - assert_kind_of(ActiveModel::Serializer::ArraySerializer, @post_serializer.associations[:comments]) + @post_serializer.each_association do |name, serializer, options| + assert_equal(:comments, name) + assert_equal({}, options) + assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer) + end end def test_has_one assert_equal({post: {type: :belongs_to, options: {}}}, @comment_serializer.class._associations) - assert_kind_of(PostSerializer, @comment_serializer.associations[:post]) + @comment_serializer.each_association do |name, serializer, options| + assert_equal(:post, name) + assert_equal({}, options) + assert_kind_of(PostSerializer, serializer) + end end end end