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

Always include self, first, last pagination links #2149

Merged

Conversation

mecampbellsoup
Copy link

@mecampbellsoup mecampbellsoup commented Jun 5, 2017

Found a bug in jsonapi adapter. Basically, when there’s one page, all links are omitted. The specs says

Keys MUST either be omitted or have a null value to indicate that a particular link is unavailable.

It doesn’t say “remove pagination entirely”. A book with one page still has a first/current/last page. It doesn’t contain next or prev.

@mecampbellsoup mecampbellsoup force-pushed the more-pagination-links-by-default branch from 1316d69 to 7387266 Compare June 5, 2017 21:26
@mecampbellsoup mecampbellsoup changed the base branch from master to 0-10-stable June 5, 2017 21:28
@kurko
Copy link
Member

kurko commented Jun 5, 2017

No CI showing up here, except for appveyor (which stands as #1 Continuous Delivery service for Windows?).

@mecampbellsoup
Copy link
Author

@kurko Travis showing up now.

@kurko
Copy link
Member

kurko commented Jun 6, 2017

So, this looks good to me and I intend to merge it because it makes sense. The spec doesn't really say we should hide all links when there's only one page, but only the ones that are unavailable.

pages[:next] = collection.current_page + FIRST_PAGE
end
else
pages[:last] = FIRST_PAGE
end
end
Copy link
Member

Choose a reason for hiding this comment

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

sure, though it might be nice to refactor to something like

  def as_json
      {
        "self": location_url,
        "first": first_page_url,
        "prev": prev_page_url,
        "next": next_page_url,
        "last": last_page_url
      }
    end

    def location_url
      url_for_page(collection.current_page)
    end

    def first_page_url
      url_for_page(1)
    end

    def prev_page_url
      return nil if collection.first_page?
      url_for_page(collection.prev_page)
    end

    def next_page_url
      return nil if collection.last_page? || collection.out_of_range?
      url_for_page(collection.next_page)
    end

    def last_page_url
      url_for_page(collection.total_pages)
    end

    def url_for_page(number)
      params = query_parameters.dup
      params[:page] = { page: per_page, number: number }
      context.url_for(action: :index, params: params)
    end

    def per_page
       @per_page ||= collection.try(:per_page) || collection.try(:limit_value) || collection.size
    end

Copy link
Member

Choose a reason for hiding this comment

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

It's not really a refactor here because there's change in behavior, (we are omitting next prev when it's not available vs just returning null), but I agree that we can improve this a bit.

Copy link
Member

Choose a reason for hiding this comment

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

ah

Keys MUST either be omitted or have a null value to indicate that a particular link is unavailable.

I like the 'always be there' ¯\_(ツ)_/¯

Copy link
Author

Choose a reason for hiding this comment

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

Seems like a matter of preference since missing key vs. present key with null value should produce same behavior for clients. We do need to pick one or the other, though... 😦

Copy link
Member

Choose a reason for hiding this comment

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

either one is fine

Copy link
Author

@mecampbellsoup mecampbellsoup Jun 8, 2017

Choose a reason for hiding this comment

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

@bf4 in your code snippet, why do you think context responds to url_for?

context.url_for(action: :index, params: params)
[11] pry(#<ActiveModelSerializers::Adapter::JsonApi::PaginationLinks>)> context.url_for(action: :index, params: params)      
NoMethodError: undefined method `url_for' for #<ActiveModelSerializers::SerializationContext:0x007ff3af0e2338>
from (pry):11:in `url_for_page'

I did notice that url_helpers seem to be available as an instance variable, however:

[7] pry(#<ActiveModelSerializers::Adapter::JsonApi::PaginationLinks>)> context.url_helpers
NoMethodError: undefined method `url_helpers' for #<ActiveModelSerializers::SerializationContext:0x007ff3af0e2338>
from (pry):7:in `url_for_page'
[8] pry(#<ActiveModelSerializers::Adapter::JsonApi::PaginationLinks>)> context.instance_variable_get :@url_helpers
=> #<Module:0x007ff3aedee488>
[9] pry(#<ActiveModelSerializers::Adapter::JsonApi::PaginationLinks>)> _.lm
=> [:url_options, :url_for, :_routes, :optimize_routes_generation?, :included, :append_features, :class_methods]

@mecampbellsoup
Copy link
Author

@kurko I've refactored the code now per @bf4 suggestion. Ready for review.

"prev": prev_page_url,
"next": next_page_url,
"last": last_page_url
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this looks much nicer :) probably should be self: vs. "self":.. not sure why I used quotes... not asking for a change.. just thinking aloud

Copy link
Member

Choose a reason for hiding this comment

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

actually, looks like this is causing failures... I hadn't check CI yet.

Copy link
Member

@bf4 bf4 left a comment

Choose a reason for hiding this comment

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

👍 Looks good

@bf4
Copy link
Member

bf4 commented Jun 14, 2017

warnings via CI

/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:85: warning: mismatched indentations at 'end' with 'def' at 22
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:24: warning: assigned but unused variable - location_url
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:25: warning: assigned but unused variable - first_page_url
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:26: warning: assigned but unused variable - prev_page_url
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:27: warning: assigned but unused variable - next_page_url
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:86: warning: mismatched indentations at 'end' with 'class' at 4
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:87: warning: mismatched indentations at 'end' with 'class' at 3
/home/travis/build/rails-api/active_model_serializers/lib/active_model_serializers/adapter/json_api/pagination_links.rb:88: warning: mismatched indentations at 'end' with 'module' at 2

@mecampbellsoup
Copy link
Author

@kurko @bf4 Travis 👍 but Appveyor 👎 ...

@kurko kurko merged commit 1e4d117 into rails-api:0-10-stable Jun 14, 2017
@mecampbellsoup mecampbellsoup deleted the more-pagination-links-by-default branch May 2, 2018 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants