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

Updating 4.x client to expect query string params as ['params'] #619

Merged
merged 1 commit into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 9 additions & 7 deletions GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,19 @@ plans.each_page.each_with_index do |data, page_num|
end
```

Pagination endpoints take a number of options to sort and filter the results. They can be passed in as keyword arguments.
Pagination endpoints take a number of options to sort and filter the results. They can be passed in as a hash provided by the `:params` keyword argument.
The names, types, and descriptions of these arguments are listed in the rubydocs for each method:

```ruby
options = {
limit: 200, # number of items per page
state: :active, # only active plans
sort: :updated_at,
order: :asc,
begin_time: DateTime.new(2017,1,1), # January 1st 2017,
end_time: DateTime.now
params: {
limit: 200, # number of items per page
state: :active, # only active plans
sort: :updated_at,
order: :asc,
begin_time: DateTime.new(2017,1,1), # January 1st 2017,
end_time: DateTime.now
}
}

plans = client.list_plans(**options)
Expand Down
36 changes: 34 additions & 2 deletions lib/recurly/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ class Client
MAX_RETRIES = 3
LOG_LEVELS = %i(debug info warn error fatal).freeze
BASE36_ALPHABET = (("0".."9").to_a + ("a".."z").to_a).freeze
REQUEST_OPTIONS = [:headers].freeze
ALLOWED_OPTIONS = [
:site_id,
:open_timeout,
:read_timeout,
:body,
:params,
:headers,
].freeze

# Initialize a client. It requires an API key.
#
Expand Down Expand Up @@ -90,20 +97,23 @@ def pager(path, **options)
end

def head(path, **options)
validate_options!(options)
request = Net::HTTP::Head.new build_url(path, options)
set_headers(request, options[:headers])
http_response = run_request(request, options)
handle_response! request, http_response
end

def get(path, **options)
validate_options!(options)
request = Net::HTTP::Get.new build_url(path, options)
set_headers(request, options[:headers])
http_response = run_request(request, options)
handle_response! request, http_response
end

def post(path, request_data, request_class, **options)
validate_options!(options)
request_class.new(request_data).validate!
request = Net::HTTP::Post.new build_url(path, options)
request.set_content_type(JSON_CONTENT_TYPE)
Expand All @@ -114,6 +124,7 @@ def post(path, request_data, request_class, **options)
end

def put(path, request_data = nil, request_class = nil, **options)
validate_options!(options)
request = Net::HTTP::Put.new build_url(path, options)
request.set_content_type(JSON_CONTENT_TYPE)
set_headers(request, options[:headers])
Expand All @@ -127,6 +138,7 @@ def put(path, request_data = nil, request_class = nil, **options)
end

def delete(path, **options)
validate_options!(options)
request = Net::HTTP::Delete.new build_url(path, options)
set_headers(request, options[:headers])
http_response = run_request(request, options)
Expand Down Expand Up @@ -274,6 +286,17 @@ def read_headers(response)
response
end

def validate_options!(**options)
invalid_options = options.keys.reject do |k|
ALLOWED_OPTIONS.include?(k)
end
if invalid_options.any?
joinedKeys = invalid_options.join(", ")
joinedOptions = ALLOWED_OPTIONS.join(", ")
raise ArgumentError, "Invalid options: '#{joinedKeys}'. Allowed options: '#{joinedOptions}'"
end
end

def validate_path_parameters!(**options)
# Check to see that we are passing the correct data types
# This prevents a confusing error if the user passes in a non-primitive by mistake
Expand Down Expand Up @@ -317,14 +340,23 @@ def set_api_key(api_key)

def build_url(path, options)
path = scope_by_site(path, options)
query_params = options.reject { |k, _| REQUEST_OPTIONS.include?(k.to_sym) }
query_params = map_array_params(options.fetch(:params, {}))
if query_params.any?
"#{path}?#{URI.encode_www_form(query_params)}"
else
path
end
end

# Converts array parameters to CSV strings to maintain consistency with
# how the server expects the request to be formatted while providing the
# developer with an array type to maintain developer happiness!
def map_array_params(params)
params.map do |key, param|
[key, param.is_a?(Array) ? param.join(",") : param]
end.to_h
end

def scope_by_site(path, **options)
if site = site_id || options[:site_id]
# Ensure that we are only including the site_id once because the Pager operations
Expand Down