Skip to content
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

Fix #1759, Grape integration, adds serialization_context #1754

Merged

Conversation

bf4
Copy link
Member

@bf4 bf4 commented May 29, 2016

  • improves improves serialization_context to take options and not depend
    on a request object.
  • adds descriptive error on missing serialization_context.
  • Document overriding CollectionSerializer#paginated?.

Closes #1759

@@ -505,6 +505,7 @@ def links_for(serializer)
# prs:
# https://github.com/rails-api/active_model_serializers/pull/1041
def pagination_links_for(serializer)
return {} unless instance_options.key?(:serialization_context)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not put this test there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref:

        if is_collection && serializer.paginated?
          hash[:links] ||= {}
          hash[:links].update(pagination_links_for(serializer))
        end

I did at first, but then I was thinking it's really tightly coupled to the paginationlinks object and it's intent isn't as obvious in the conditional.

But really we shouldn't let an empty serialization_context get in that far. This is a quick fix, but the better fix is at the boundary, I think

@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch from 9b77f0a to 6972c22 Compare May 31, 2016 03:50
@bf4 bf4 changed the title Skip rendering JSONAPI pagination links when no serialization context Fix #1759, Grape integration, adds serialization_context May 31, 2016
@bf4
Copy link
Member Author

bf4 commented May 31, 2016

I spent too much time on this. Any blockers or anyone want to make changes?

@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch from 6972c22 to ac67827 Compare May 31, 2016 03:54
@bf4
Copy link
Member Author

bf4 commented May 31, 2016

@groyoh groyoh added the S: LGTM label May 31, 2016
@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch from ac67827 to f685c8c Compare May 31, 2016 21:32
@onomated
Copy link
Contributor

onomated commented Jun 1, 2016

@bf4 Sorry for the delay. Just seeing this, was a holiday weekend. I'll take a look and report any changes back

FIRST_PAGE = 1

attr_reader :collection, :context

def initialize(collection, adapter_options)
@collection = collection
@adapter_options = adapter_options
@context = adapter_options.fetch(:serialization_context)
@context = adapter_options.fetch(:serialization_context) do
fail MissingSerializationContextError, 'JsonApi::PaginationLinks requires a'\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-            fail MissingSerializationContextError, 'JsonApi::PaginationLinks requires a'\
+            fail MissingSerializationContextError, 'JsonApi::PaginationLinks requires a '\

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

' is use for defining the string here whereas " is used below. Not sure if typo or if I'm missing something ;)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just because I have things in the others that need double quotes. rubocop caught it. changing to a heredoc

@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch 2 times, most recently from bfa1e35 to 159c529 Compare June 1, 2016 07:45
@@ -8,6 +11,12 @@ module ActiveModelSerializers
#
# Example: To include pagination meta data: render(posts, meta: { page: posts.page, total_pages: posts.total_pages })
def render(resource, active_model_serializer_options = {})
active_model_serializer_options.fetch(:serialization_context) do
active_model_serializer_options[:serialization_context] = ::ActiveModelSerializers::SerializationContext.new(
original_url: request.url[/\A[^?]+/],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

original_url option should be request_url

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops :)

Also 👍 to making a PR to my branch and moving this code to the formatter (and adding yourself in the changelog!) #1754 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wasn't able to duplicate the failure in the grape tests, so if you could do that, that would be fantastic!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I don't use grape)

@onomated
Copy link
Contributor

onomated commented Jun 1, 2016

So the current solution works when an explicit render call is made on a resource. In generally, grape formatters should render the resulting resource without options. For example,

resource :statuses do
      desc 'Return a public timeline.'
      get :public_timeline do
        Status.limit(20)
      end
end

returns the MissingSerializationContextError error since there wasn't an explicit render call. This works if Status.limit(20) is wrapped in a render as render(Status.limit(20)).
Moving the creation of the serialization context to the formatter will fix this, and allow including other AMS options such the serialization scope. As done in the grape_active-model-serializers gem formatter.
I can take a stab at addressing this if you give me write access @bf4, or I can create a new PR on this branch

@bf4
Copy link
Member Author

bf4 commented Jun 1, 2016

@onomated if you would make a PR into my branch, that would be fantastic! I didn't check if I had all the objects I need in the formatter

@groyoh groyoh removed the S: LGTM label Jun 1, 2016
@bf4
Copy link
Member Author

bf4 commented Jun 9, 2016

@onomated I just merged in your PR and will finish this up. Great work 💯

@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch from 1a8ccef to d2b761a Compare June 9, 2016 06:30
@@ -2,14 +2,21 @@ module ActiveModelSerializers
module Adapter
class JsonApi < Base
class PaginationLinks
MissingSerializationContextError = Class.new(KeyError)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be defined within PaginationLinks? It seems like it's more general than that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to put a guard wherever it's to be used... Can't think of a better spot...

@beauby
Copy link
Contributor

beauby commented Jun 9, 2016

See my 2 remarks. LGTM otherwise.

@bf4
Copy link
Member Author

bf4 commented Jun 14, 2016

@onomated bf4#4 (comment) so is this good for you?

@onomated
Copy link
Contributor

onomated commented Jun 14, 2016

@bf4 couldn't quite resolve the comment link in the @ mention above, but on the general topic of pagination, it'll be awesome if this was configurable like so paginate: false as opposed to serialization_context: nil. I personally am in the party of not caring about pagination in the json-api rendition. I currently rely on my internal header pagination implemented a while back. With the fixes in this PR, Grape support has pagination support out the box so it just works for new projects but currently no way to turn this off if its not desired.

bf4 and others added 2 commits June 14, 2016 09:45
- improves improves serialization_context to take options and not depend
on a `request` object.
- adds descriptive error on missing serialization_context.
- Document overriding `CollectionSerializer#paginated?`.
* Fix rails-api#1759, Grape integration, adds serialization_context

- `serialization_context` is added in grape formatter so grape continues to render models without an explicit call to the `render` helper method
- Made it straightforward for subclasses to add other serializer options (such as `serialization_scope`).

* Updated Grape tests to include:
- paginated collections
- implicit Grape serializer (i.e. without explicit invocation of `render` helper method)

* Update Changelog with fixes.
I missed that the code was changing global state.
@bf4 bf4 force-pushed the handle_missing_serialization_context_when_paginating branch from d2b761a to 1a9c622 Compare June 14, 2016 14:46
@bf4
Copy link
Member Author

bf4 commented Jun 14, 2016

@onomated I just rebased this off of master. Can you confirm it works for you before merge?

@onomated
Copy link
Contributor

@bf4 sure thing. Checking out now

@onomated
Copy link
Contributor

@bf4 All good! 👍 💯

@xn
Copy link
Contributor

xn commented Jun 15, 2016

Oh snap! Thanks, this is awesome!

@bf4 bf4 merged commit 0fed486 into rails-api:master Jun 15, 2016
@bf4 bf4 deleted the handle_missing_serialization_context_when_paginating branch June 15, 2016 20:19
@bf4
Copy link
Member Author

bf4 commented Jun 15, 2016

Thanks @onomated for your work here. This was actually a blocker for us for releasing 0.10.1

@xn
Copy link
Contributor

xn commented Jun 22, 2016

Just want to leave this here in case someone gets stuck with an error like: NoMethodError: undefined method 'url' for nil:NilClass.

This formatter now depends on Grape::Middleware::Globals
You can get that going like:

module MyApi
  class ApiBase < Grape::API
    use Grape::Middleware::Globals
    require 'grape/active_model_serializers'
    include Grape::ActiveModelSerializers
    mount MyApi::V1::ApiBase

or minimally:

class API < Grape::API
  # @note Make sure this is above you're first +mount+
  use Grape::Middleware::Globals
end

@onomated
Copy link
Contributor

@xn, I didn't encounter this as I use some other middleware that inherits from grape globals. Should this be mixed in as part of include Grape::ActiveModelSerializers?

@xn
Copy link
Contributor

xn commented Jun 22, 2016

Well, if you just add it to the docs, then if someone wants/needs to monkey with Grape::Middleware::Globals or write their own for whatever reasons, they are free to do so without having to monkey with this formatter as well.

@bf4
Copy link
Member Author

bf4 commented Jun 22, 2016

PRs accepted :)

@xn
Copy link
Contributor

xn commented Jun 23, 2016

@bf4 I'm happy to roll this into a documentation PR. Though I think it is better to allow the developer to meet the dependency, it is a question that should be answered by someone who has a stake in the project's maintainance/architecture.

@bf4
Copy link
Member Author

bf4 commented Jun 23, 2016

Not sure I follow. Do you think there is a problem in AMS impl or just docs needed?

B mobile phone

On Jun 22, 2016, at 9:15 PM, Christian Trosclair notifications@github.com wrote:

@bf4 I'm happy to roll this into a documentation PR. Though I think it is better to allow the developer to meet the dependency, it is a question that should be answered by someone who has a stake in the project's maintainance/architecture.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@xn
Copy link
Contributor

xn commented Jun 23, 2016

AMS is kindly creating a grape formatter. Said formatter is depending on a grape middleware that is not enabled by default. You have a choice to automatically meet the dependency by hardcoding that dependency in the formatter itself or document the dependency to let the developer meet it on own their own terms.

If I am being too circuitous, I apologize. Let me know and I will tell you what I believe should be done.

@bf4
Copy link
Member Author

bf4 commented Jun 23, 2016

I don't use grape, so I don't know what's right for you

@xn
Copy link
Contributor

xn commented Jun 23, 2016

Ok, from basic OO principles you should let the developer meet the dependency. So, I'll create a PR for documentation to meet this in the README.

@xn
Copy link
Contributor

xn commented Jun 23, 2016

#1818

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants