Skip to content

Commit

Permalink
refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
bodrovis committed Sep 6, 2024
1 parent 877aab1 commit 4681ad5
Show file tree
Hide file tree
Showing 17 changed files with 224 additions and 155 deletions.
6 changes: 3 additions & 3 deletions docs/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ source 'https://rubygems.org'
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem 'jekyll', '~> 3.9.0'
gem 'jekyll', '~> 3.10.0'

# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem 'minima', '~> 2.0'

# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem 'github-pages', '~> 231', group: :jekyll_plugins
gem 'github-pages', '~> 232', group: :jekyll_plugins

# If you have any plugins, put them here!
group :jekyll_plugins do
Expand All @@ -32,7 +32,7 @@ install_if -> { RUBY_PLATFORM =~ /mingw|mswin|java/ } do
end

# Performance-booster for watching directories on Windows
gem 'wdm', '~> 0.1.0', install_if: Gem.win_platform?
gem 'wdm', '~> 0.2.0', install_if: Gem.win_platform?

# kramdown v2 ships without the gfm parser by default. If you're using
# kramdown v1, comment out this line.
Expand Down
34 changes: 14 additions & 20 deletions lib/ruby_lokalise_api/collections/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,39 +32,23 @@ def initialize(response)
def next_page
return nil if last_page?

override_params = { page: current_page + 1 }

self.class.new(
reinit_endpoint(
override_req_params: override_params
).do_get
)
fetch_page(current_page + 1)
end

# Tries to fetch the next cursor for paginated collection
# Returns a new collection or nil if the next cursor is not available
def load_next_cursor
return nil unless next_cursor?

override_params = { cursor: next_cursor }

self.class.new(
reinit_endpoint(
override_req_params: override_params
).do_get
)
fetch_cursor(next_cursor)
end

# Tries to fetch the previous page for paginated collection
# Returns a new collection or nil if the previous page is not available
def prev_page
return nil if first_page?

self.class.new(
reinit_endpoint(
override_req_params: { page: current_page - 1 }
).do_get
)
fetch_page(current_page - 1)
end

# Checks whether the next page is available
Expand Down Expand Up @@ -131,7 +115,7 @@ def produce_collection_from(response)
data_key_plural = collection_key_for klass: self.class.base_name

resources_data = content[data_key_plural]
other_data = content.reject { |key, _| key == data_key_plural }
other_data = content.except(data_key_plural)

@collection = build_collection resources_data, other_data
end
Expand Down Expand Up @@ -165,6 +149,16 @@ def resource_endpoint

klass.const_defined?(:RESOURCES_ENDPOINT) ? klass.const_get(:RESOURCES_ENDPOINT) : klass.const_get(:ENDPOINT)
end

# Helper method to fetch a page for paginated collections
def fetch_page(page)
self.class.new(reinit_endpoint(override_req_params: { page: page }).do_get)
end

# Helper method to fetch the next cursor
def fetch_cursor(cursor)
self.class.new(reinit_endpoint(override_req_params: { cursor: cursor }).do_get)
end
end
end
end
32 changes: 25 additions & 7 deletions lib/ruby_lokalise_api/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ module RubyLokaliseApi
# Module to setup connection using Faraday
module Connection
# Creates a new Faraday object with specified params
#
# @param endpoint [Object] the API endpoint
# @param params [Hash] additional connection parameters
# @return [Faraday::Connection] the Faraday connection object
def connection(endpoint, params = {})
Faraday.new(options(endpoint, params), request_params_for(endpoint.client)) do |faraday|
faraday.adapter Faraday.default_adapter
faraday.request(:gzip)
faraday.request :gzip
end
end

Expand All @@ -17,19 +21,33 @@ def options(endpoint, params)
req_params = __base_options(endpoint)
client = endpoint.client

if client.respond_to?(:token) && client.respond_to?(:token_header)
req_params[:headers][client.token_header] = client.token
end
add_token_header(req_params, client) if client_responds_to_token?(client)

# Sending content-type is needed only when the body is actually present
# Trying to send this header in other cases seems to result in error 500
req_params[:headers]['Content-type'] = 'application/json' if !params[:get_request] && endpoint.req_params
# Set Content-Type if required (skip for GET requests)
add_content_type_header(req_params, params, endpoint)

req_params[:headers][:accept_encoding] = 'gzip,deflate,br'

req_params
end

# Adds the token header to the request parameters if token is present
def add_token_header(req_params, client)
req_params[:headers][client.token_header] = client.token
end

# Checks if the client can respond to token and token header methods
def client_responds_to_token?(client)
client.respond_to?(:token) && client.respond_to?(:token_header)
end

# Conditionally adds the Content-Type header
def add_content_type_header(req_params, params, endpoint)
return unless !params[:get_request] && endpoint.req_params

req_params[:headers]['Content-Type'] = 'application/json'
end

def __base_options(endpoint)
{
headers: {
Expand Down
6 changes: 3 additions & 3 deletions lib/ruby_lokalise_api/endpoints/base_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ def reinitialize(query_params: nil, req_params: {})
end

def base_url
self.class.const_get(:BASE_URL)
self.class::BASE_URL
end

def full_uri
base_url + uri
base_url + uri.to_s
end

# Creates methods like `do_post`, `do_get` that proxy calls to the
Expand All @@ -52,7 +52,7 @@ def partial_uri(*_args)
end

def partial_uri_template
self.class.const_get(:PARTIAL_URI_TEMPLATE)
self.class::PARTIAL_URI_TEMPLATE
end
end
end
Expand Down
14 changes: 12 additions & 2 deletions lib/ruby_lokalise_api/endpoints/oauth2/oauth2_endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,30 @@ class OAuth2Endpoint < BaseEndpoint
def initialize(client, params = {})
super

@uri = partial_uri(base_query(*@query_params), params.fetch(:get, []))
@uri = build_uri(params.fetch(:get, []))
end

private

# Builds the complete URI for the OAuth2 endpoint
def build_uri(query)
partial_uri(base_query(*@query_params), query)
end

def partial_uri(segments, query)
template = super

template.expand(
segments: segments.to_a.flatten,
query: query.filter { |_k, v| !v.nil? }
query: filter_query_params(query)
).to_s
end

# Filters out nil values from query parameters
def filter_query_params(query)
query.compact
end

def base_query(segment = nil)
[segment]
end
Expand Down
57 changes: 29 additions & 28 deletions lib/ruby_lokalise_api/oauth2/auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,49 +29,50 @@ def oauth2_endpoint
def auth(scope:, redirect_uri: nil, state: nil)
get_params = {
client_id: client_id,
scope: (scope.is_a?(Array) ? scope.join(' ') : scope),
scope: scope_to_string(scope),
state: state,
redirect_uri: redirect_uri
}

oauth2_endpoint.new(self, query: 'auth', get: get_params).full_uri
end

# Requests OAuth2 access token. Requires OAuth2 code obtained
# using the `.auth` method
# @return [RubyLokaliseApi::Resources::OAuth2Token]
# @param code [String]
# Requests an OAuth2 access token using a code
# @param code [String] The authorization code
# @return [RubyLokaliseApi::Resources::OAuth2Token] The OAuth2 token resource
def token(code)
endpoint = oauth2_endpoint.new(
self,
query: :token,
req: common_params.merge(
grant_type: 'authorization_code',
code: code
)
)

RubyLokaliseApi::Resources::OAuth2Token.new endpoint.do_post
request_token(grant_type: 'authorization_code', code: code)
end

# Refreshes expired OAuth2 access token.
# @return [RubyLokaliseApi::Resources::OAuth2RefreshedToken]
# @param refresh_token [String]
# Refreshes an expired OAuth2 token
# @param refresh_token [String] The refresh token
# @return [RubyLokaliseApi::Resources::OAuth2RefreshedToken] The refreshed token resource
def refresh(refresh_token)
endpoint = oauth2_endpoint.new(
self,
query: :token,
req: common_params.merge(
grant_type: 'refresh_token',
refresh_token: refresh_token
)
)

RubyLokaliseApi::Resources::OAuth2RefreshedToken.new endpoint.do_post
request_token(grant_type: 'refresh_token', refresh_token: refresh_token)
end

private

# Generalized method for requesting a token
# @param params [Hash] Request parameters including grant type
# @return [RubyLokaliseApi::Resources::OAuth2Token, RubyLokaliseApi::Resources::OAuth2RefreshedToken]
def request_token(params)
endpoint = oauth2_endpoint.new(self, query: :token, req: common_params.merge(params))
resource_class = if params[:grant_type] == 'authorization_code'
RubyLokaliseApi::Resources::OAuth2Token
else
RubyLokaliseApi::Resources::OAuth2RefreshedToken
end
resource_class.new(endpoint.do_post)
end

# Converts scope to a space-separated string if it's an array
# @param scope [Array, String] The scope or scopes
# @return [String] The scope as a string
def scope_to_string(scope)
scope.is_a?(Array) ? scope.join(' ') : scope
end

def common_params
{
client_id: @client_id,
Expand Down
12 changes: 7 additions & 5 deletions lib/ruby_lokalise_api/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,19 @@ def raise_on_error!(response, body)
end

def respond_with(response, endpoint)
begin
body = custom_load response.body
rescue JSON::ParserError
respond_with_error(response.status, response.body)
end
body = parse_response_body(response)

raise_on_error! response, body

RubyLokaliseApi::Response.new(body, endpoint, response.headers)
end

def parse_response_body(response)
custom_load(response.body)
rescue JSON::ParserError
respond_with_error(response.status, response.body)
end

def respond_with_error(code, body)
raise(RubyLokaliseApi::Error, body['error'] || body) unless RubyLokaliseApi::Error::ERRORS.key? code

Expand Down
26 changes: 17 additions & 9 deletions lib/ruby_lokalise_api/resources/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,28 @@ def reinit_endpoint(req_params = {})
@self_endpoint.reinitialize(query_params: read_main_params, req_params: req_params)
end

# Populates attributes from the response content
def populate_attrs_from(content)
return unless content

data_key = data_key_for klass: self.class.base_name
data_key = data_key_for(klass: self.class.base_name)
supported_attrs.each { |attrib| set_instance_variable(attrib, content, data_key) }
end

supported_attrs.each do |attrib|
value = if content.key?(data_key) && content[data_key].is_a?(Hash) && content[data_key].key?(attrib)
content[data_key][attrib]
else
content[attrib]
end
# Sets the instance variable for a given attribute
def set_instance_variable(attrib, content, data_key)
value = if content_key_exists?(content, data_key, attrib)
content[data_key][attrib]
else
content[attrib]
end

instance_variable_set :"@#{attrib}", value
end
instance_variable_set(:"@#{attrib}", value)
end

# Checks if the content contains the specified key
def content_key_exists?(content, data_key, attrib)
content.key?(data_key) && content[data_key].is_a?(Hash) && content[data_key].key?(attrib)
end
end
end
Expand Down
10 changes: 1 addition & 9 deletions lib/ruby_lokalise_api/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,11 @@ def patch_endpoint_with(new_endpoint)
@endpoint = new_endpoint
end

# Returns an array of pagination headers
def pagination_headers
self.class.const_get(:PAGINATION_HEADERS)
end

private

# Keep only pagination headers
def extract_headers_from(raw_headers)
raw_headers.
to_h.
keep_if { |header, _value| pagination_headers.include?(header) }.
transform_keys(&:to_sym)
raw_headers.to_h.slice(*PAGINATION_HEADERS).transform_keys(&:to_sym)
end
end
end
Loading

0 comments on commit 4681ad5

Please sign in to comment.