-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restrict serializable_hash to accepted options #1647
Conversation
@@ -8,7 +8,7 @@ def initialize(serializer, options = {}) | |||
end | |||
|
|||
def serializable_hash(options = nil) | |||
options ||= {} | |||
options = super |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figure this pattern with the base class is a little nicer and less error prone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually find this pattern quite weird 😄 I mean, when I read super
I would expect it to return a Hash
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I think it's weird and intuitive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super does return a hash. We need to make sure options is always set. This is how it is in Rails. See links in #1643. If someone passes in 'nil', it sets options to '{}'. Rather than make sure the signature is always 'options = nil' and the first line in the method 'options ||= {}', we just delegate that guard to the base class. Alternatively, we use a different abstract method that serializable_hash calls.
@bf4 I'll have a look at it later today. |
691a596
to
ec824c9
Compare
@@ -2,7 +2,7 @@ | |||
|
|||
module ActiveModelSerializers | |||
class SerializableResource | |||
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links]) | |||
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links, :serialization_context]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@remear this is where I added serialization context to the adapter options.
Now pagination links call from jsonapi adapter is PaginationLinks.new(serializer.object, instance_options).as_json
and PaginationLinks calls @context = adapter_options.fetch(:serialization_context)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add :key_transform
here and your failing test will pass 😉
aa602d5
to
c3dfee7
Compare
Looks good to me but could probably use a bit more docs |
c3dfee7
to
001ecb9
Compare
ActiveModelSerializers::SerializableResource.new(paginated_collection, options) | ||
def load_adapter(paginated_collection, mock_request = nil) | ||
render_options = { adapter: :json_api } | ||
render_options[:serialization_context] = mock_request if mock_request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this! 👍
What is your main objective when restricting the options of |
def serializable_hash(_options = nil) | ||
fail NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' | ||
def serializable_hash(options = nil) | ||
(options ||= {}).slice(*ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS) # rubocop:disable Lint/UselessAssignment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the centerpiece of the pr
@bf4 yeah sorry, my question was not really clear. Since you wan to restrict the options passed to |
Good question, I agree it should probably be as_json but we have so many
|
@groyoh This is how AMS fits into rendering and why I'm thinking this way render json: record, options
# |-> https://github.com/rails/rails/blob/v5.0.0.beta3/actionpack/lib/action_controller/metal/renderers.rb#L151-L152
_render_with_renderer_json(record, options)
+ # |-> https://github.com/rails-api/active_model_serializers/blob/d30aa4c44fe004821be49d3427b56973f95c4984/lib/action_controller/serialization.rb#L46-L52
+ record = ActiveModel::Serializable_resource.new(record, options)
# |-> https://github.com/rails/rails/blob/v5.0.0.beta3/actionpack/lib/action_controller/metal/renderers.rb#L159
record.to_json(options) unless record.is_a?(String)
# |-> https://github.com/rails/rails/blob/v5.0.0.beta3/activemodel/lib/active_model/serializers/json.rb#L88-L92
record.as_json(options)
# |-> https://github.com/rails/rails/blob/v5.0.0.beta3/activemodel/lib/active_model/serialization.rb#L124-L137
record.serializable_hash(options) where |
001ecb9
to
826c927
Compare
@@ -41,6 +43,10 @@ def cache_check(serializer) | |||
|
|||
private | |||
|
|||
def serialization_options(options) | |||
(options ||= {}).slice(*ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS) # rubocop:disable Lint/UselessAssignment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you have this assignment here?
why not just:
(options || {}).slice(*ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess in the current implementation it doesn't matter. Good eyes. previously, when it was inline, we, of course wanted to set the value of options when nil.
@bf4, I'm good with this. After squashing, I'd be happy to merge. (Or we can try out the new github feature where it forces squashing) :-) |
2e66676
to
4d89ec8
Compare
@@ -102,8 +102,8 @@ def test_success_document_transform_global_config | |||
mock_request | |||
result = with_config(key_transform: :camel_lower) do | |||
serializer = PostSerializer.new(@post) | |||
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer) | |||
adapter.serializable_hash(@options) | |||
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer, @options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is failing when run as part of the suite, but not alone.. minitest-bisect anyone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I added gem 'minitest-bisect'
to my Gemfile.local and ran
RUBYOPT=-Ilib:test MTB_VERBOSE=2 be minitest_bisect --seed 48816 $(find test -type f -name \*_test.rb)
and minitest-bisect tells me
Final reproduction:
Run options: --seed 48816 -n "/^(?:ActiveModel::Serializer::OptionsTest#(?:test_no_option_is_passed_in)|ActionController::Serialization::JsonApi::KeyTransformTest#(?:test_render_resource_with_transform))$/"
# Running:
.F
Finished in 0.039316s, 50.8697 runs/s, 50.8697 assertions/s.
1) Failure:
ActionController::Serialization::JsonApi::KeyTransformTest#test_render_resource_with_transform [/Users/benjamin/files/dev/repos/active_model_serializers/test/action_controller/json_api/transform_test.rb:105]:
--- expected
+++ actual
@@ -1 +1 @@
-{"Data"=>{"Id"=>"1337", "Type"=>"Posts", "Attributes"=>{"Title"=>"Title 1", "Body"=>"Body 1", "PublishAt"=>"2020-03-16T03:55:25.291Z"}, "Relationships"=>{"Author"=>{"Data"=>{"Id"=>"1", "Type"=>"Authors"}}, "TopComments"=>{"Data"=>[{"Id"=>"7", "Type"=>"TopComments"}, {"Id"=>"12", "Type"=>"TopComments"}]}}, "Links"=>{"PostAuthors"=>"https://example.com/post_authors"}, "Meta"=>{"Rating"=>5, "FavoriteCount"=>10}}}
+{"data"=>{"id"=>"1337", "type"=>"posts", "attributes"=>{"title"=>"Title 1", "body"=>"Body 1", "publish-at"=>"2020-03-16T03:55:25.291Z"}, "relationships"=>{"author"=>{"data"=>{"id"=>"1", "type"=>"authors"}}, "top-comments"=>{"data"=>[{"id"=>"7", "type"=>"top-comments"}, {"id"=>"12", "type"=>"top-comments"}]}}, "links"=>{"post-authors"=>"https://example.com/post_authors"}, "meta"=>{"rating"=>5, "favorite-count"=>10}}}
but that's wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented that out and it still failed. It appears to go away when I rm-rf test/action_controller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently it's in test/action_controller/json_api/transform_test.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and, omg, I can't read, that's where it's been all along. no test pollution, just test/adapter/json_api/transform_test.rb
looks a lot like test/action_controller/json_api/transform_test.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:-( I believe in you!! :-)
@bf4 I pushed two commits that should fix the failing test plus two rubocop complaints 😉 |
@@ -2,7 +2,7 @@ | |||
|
|||
module ActiveModelSerializers | |||
class SerializableResource | |||
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links]) | |||
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links, :serialization_context, :key_transform]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@groyoh thanks for catching :key_transform
, d'oh
See #1643 for rationale behind these changes.
Some of these failures are addressed in other PRs such as
#1572