-
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
Only use subclasses of ActiveModel::Serializer during lookup. #1294
Only use subclasses of ActiveModel::Serializer during lookup. #1294
Conversation
I don't think this would fully address the problem. For example, if you're migrating from nothing to AMS and have a I think basically you need an option to switch off automatic lookup: https://github.com/rails-api/active_model_serializers/compare/master...trek:config-autolookup?expand=1 |
The whole purpose of this PR is to avoid what you just described. Have a look at the provided test to convince yourself. Or maybe I misunderstood something? |
@@ -202,7 +202,7 @@ def self.serializer_lookup_chain_for(klass) | |||
def self.get_serializer_for(klass) | |||
serializers_cache.fetch_or_store(klass) do | |||
# NOTE(beauby): When we drop 1.9.3 support we can lazify the map for perfs. | |||
serializer_class = serializer_lookup_chain_for(klass).map(&:safe_constantize).find { |x| x } | |||
serializer_class = serializer_lookup_chain_for(klass).map(&:safe_constantize).find { |x| x && x < ActiveModel::Serializer } | |||
|
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.
kill ducks!
LGTM. |
Only use subclasses of ActiveModel::Serializer during lookup.
Wait, why was this merged? OP said it wouldn't solve the problem and limiting serializers to subclasses doesn't make sense |
cc @rails-api/ams re considering reverting this. OP said it wouldn't help #1294 (comment) and made his own PR #1295 |
@bf4 The reasons OP stated are not valid, unless I didn't understand. |
I just think that if OP @trek says this doesn't look like the fix he needs it shouldn't be merged until he says it works or it just seems like a good thing for the library to have
two reasons
Also, looping three times instead of one just seems unnecessary. (And yes, I understand that lazy evaluation wouldn't loop three times, but we're not using lazy evaluation). |
For 2) we already agreed on dropping support for 1.9.3, and lazy evaluation will come right when we do. As for the alleged 'esotericness', I suggested replacing |
Moreover, 2) is still possible by explicitly providing the serializer. |
Sorry about that, I thought it was good to go, and something beneficial :-/ |
How are they not valid? This PR did fix a problematic situation ("I have serializers but they are not AMS") but doesn't address what I suspect will be the larger problem for existing applications: You were not using Serializers (of any flavor) in existing controllers but want to use them for new controllers. AMS will lookup serializers and change render output when introduced: Here's an example of where this would cause breaking changes into an existing API: Imagine an application like this # models/tweet.rb
class Tweet < ActiveRecord::Base
end # controllers/v1/tweets_controller.rb
class V1::TweetsController < ApplicationController
def show
render json: Tweet.find(params[:id])
end
end
For v2, the developers decide to adopt JSON API via AMS: # models/tweet.rb
class Tweet < ActiveRecord::Base
end + # serializers/tweet_serializer.rb
+ TweetSerializer < ActiveModel::Serializer
+ attribute :body
+ end # controllers/v1/tweets_controller.rb
class V1::TweetsController < ApplicationController
def show
render json: Tweet.find(params[:id])
end
end + # controllers/v2/tweets_controller.rb
+ class V2::TweetsController < ApplicationController
+ def show
+ render json: Tweet.find(params[:id])
+ end
+ end Now, the newly introduced V2 controller is OK. The augmentation to There are two solutions to this:
Option 1 makes it easy to opt out locally (nicer for smaller or greefield apps), Option 2 makes it easy to opt in locally (nicer for larger legacy apps). In this small example, each option feels like roughly the same amount of work. But in real world examples there will be – initially – many hundreds of Over time, this balance will shift to the other side: all non-AMS controllers will end up removed from the application as those versions of the API are discontinued. Controllers that manually opted into AMS will continue to function, new controllers can begin using the automatic lookup behavior: # use default behavior
- ActiveModel::Serializer.config.automatic_lookup = false
- # V2, deprecated and removed
- def show
- render json: Tweet.find(params[:id])
- end
# V8, manually opted into AMS
def show
render json: Tweet.find(params[:id]), serializer: TweetSerializer
end
+ # V9 using automatic lookuop
+ def show
+ render json: Tweet.find(params[:id])
+ end |
Fixes #1293.