Draft
Conversation
0ba7104 to
4c211b0
Compare
Contributor
Author
|
While this is passing, it expands the surface area of the dependencies. The favorable part of that trade-off is that the package gains more sophisticated query string parsing when it's available through Rack). However, I wonder if the goals of the use case described in the PR could be achieved by expanding I'll explore that in a separate PR. |
9b07df4 to
76e38b4
Compare
The problem
---
When a resource queries an "index"-like endpoint and receives a response
payload that relies on URL-based pagination, it can be tedious to
deconstruct the next page's URL and transform it into a subsequent
`.where` call.
For example, consider a `Post` payload like:
```json
{
"posts": { … },
"next_page": "https://api.blog.com/posts?page=2"
}
```
In order to query the URL in the `next_page` property, the collection
parser must extract a `{ "page" => "2" }` Hash and forward it to a
`resource_class.where` call:
```ruby
def initialize(parsed = {})
@elements = parsed["posts"]
@next_page_uri = URI.parse(parsed["next_page"])
end
def next_page_params
query_string = @next_page_uri.query
URI.decode_www_form(query_string).to_h
end
def next_page
resource_class.where(next_page_params)
end
collection.next_page_params # => { "page" => "2" }
collection.next_page # => GET https://api.blog.com/posts?page=2
```
The process becomes complicated when there are other parameters
(including "array"-like keys):
```json
{
"posts": { … },
"next_page": "https://api.blog.com/posts?tags[]=Ruby&tags[]=Rails&page=2"
}
```
In this scenario, the Array created by [URI.decode_www_form][] will only
retain both `tags[]`-keyed values, but the [Array#to_h][] call will
flatten that Array into a Hash that only contains the last key. In this
case, `tags[]=Ruby` will be omitted, and the resulting Hash would be `{
"tags[]" => "Rails", "page" => "2" }`.
The proposal
---
Active Record's `.where` method supports both [String][] and [Array][]
arguments. In the context of Active Record, `String` and `Array`
arguments are in support of the underlying SQL queries to be executed.
In the context of Active Resource, the underlying format for a "query"
is an HTTP-compliant query that's encoded as an
[application/x-www-form-urlencoded][] string.
This commit proposes adding support to `Base.where` to accept String
arguments.
This support would simplify the scenario above:
```ruby
def initialize(parsed = {})
@elements = parsed["posts"]
@next_page_uri = URI.parse(parsed["next_page"])
end
def next_page
resource_class.where(@next_page_uri.query)
end
collection.next_page # => GET https://api.blog.com/posts?page=2
```
When Active Resource is loaded alongside a Rails or Rack application,
rely on [Rack::Utils.parse_nested_query][] to decode key-value pairs.
Otherwise, rely on [URI.decode_www_form][] and [Array#to_h][].
[URI.decode_www_form]: https://docs.ruby-lang.org/en/master/URI.html#method-c-decode_www_form
[String]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-where-label-String
[Array]: https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-where-label-Array
[application/x-www-form-urlencoded]: https://url.spec.whatwg.org/#application/x-www-form-urlencoded
[Rack::Utils.parse_nested_query]: https://www.rubydoc.info/gems/rack/Rack/Utils#parse_nested_query-class_method
[Array#to_h]: https://docs.ruby-lang.org/en/master/Array.html#method-i-to_h
76e38b4 to
d9fa989
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
When a resource queries an "index"-like endpoint and receives a response
payload that relies on URL-based pagination, it can be tedious to
deconstruct the next page's URL and transform it into a subsequent
.wherecall.For example, consider a
Postpayload like:{ "posts": { … }, "next_page": "https://api.blog.com/posts?page=2" }In order to query the URL in the
next_pageproperty, the collectionparser must extract a
{ "page" => "2" }Hash and forward it to aresource_class.wherecall:The process becomes complicated when there are other parameters
(including "array"-like keys):
{ "posts": { … }, "next_page": "https://api.blog.com/posts?tags[]=Ruby&tags[]=Rails&page=2" }In this scenario, the Array created by URI.decode_www_form will only
retain both
tags[]-keyed values, but the Array#to_h call willflatten that Array into a Hash that only contains the last key. In this
case,
tags[]=Rubywill be omitted, and the resulting Hash would be{ "tags[]" => "Rails", "page" => "2" }.The proposal
Active Record's
.wheremethod supports both String and Arrayarguments. In the context of Active Record,
StringandArrayarguments are in support of the underlying SQL queries to be executed.
In the context of Active Resource, the underlying format for a "query"
is an HTTP-compliant query that's encoded as an
application/x-www-form-urlencoded string.
This commit proposes adding support to
Base.whereto accept Stringarguments.
This support would simplify the scenario above:
When Active Resource is loaded alongside a Rails or Rack application,
rely on Rack::Utils.parse_nested_query to decode key-value pairs.
Otherwise, rely on URI.decode_www_form and Array#to_h.