v3: add ability to sort branches
This commit is contained in:
parent
0249140dc8
commit
33d31131c1
|
@ -1,7 +1,10 @@
|
|||
module Travis::API::V3
|
||||
class Queries::Branches < Query
|
||||
sortable_by :name, last_build: "builds.started_at".freeze
|
||||
default_sort "last_build:desc"
|
||||
|
||||
def find(repository)
|
||||
repository.branches
|
||||
sort repository.branches
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ module Travis::API::V3
|
|||
def query(type, main_type: self.main_type, params: self.params)
|
||||
main_type = type if main_type == :owner
|
||||
params = params.merge("#{type}.login" => params["owner.login".freeze]) if params["owner.login".freeze]
|
||||
Queries[type].new(params, main_type)
|
||||
Queries[type].new(params, main_type, service: @service)
|
||||
end
|
||||
|
||||
def find!(type)
|
||||
|
|
|
@ -20,8 +20,11 @@ module Travis::API::V3
|
|||
end
|
||||
RUBY
|
||||
|
||||
def self.type
|
||||
name[/[^:]+$/].underscore
|
||||
end
|
||||
|
||||
def self.params(*list, prefix: nil, method_name: nil)
|
||||
type = name[/[^:]+$/].underscore
|
||||
prefix ||= type.to_s
|
||||
check_type = method_name.nil? and type != prefix
|
||||
list.each do |entry|
|
||||
|
@ -35,12 +38,48 @@ module Travis::API::V3
|
|||
end
|
||||
end
|
||||
|
||||
def self.prefix(input)
|
||||
return input if input.is_a? String
|
||||
"#{type}.#{input}"
|
||||
end
|
||||
|
||||
def self.sortable_by(*params, **mapping)
|
||||
params.each { |param| sort_by[param.to_s] = prefix(param) }
|
||||
mapping.each { |key, value| sort_by[key.to_s] = prefix(value) }
|
||||
end
|
||||
|
||||
def self.sortable?
|
||||
!sort_by.empty?
|
||||
end
|
||||
|
||||
@sort_by = {}
|
||||
def self.sort_by
|
||||
@sort_by ||= superclass.sort_by.dup
|
||||
end
|
||||
|
||||
@default_sort = ""
|
||||
def self.default_sort(value = nil)
|
||||
@default_sort = value.to_s if value
|
||||
@default_sort ||= superclass.default_sort
|
||||
end
|
||||
|
||||
attr_reader :params, :main_type
|
||||
|
||||
def initialize(params, main_type, includes: nil)
|
||||
def initialize(params, main_type, includes: nil, service: nil)
|
||||
@params = params
|
||||
@main_type = main_type.to_s
|
||||
@includes = includes
|
||||
@service = service
|
||||
end
|
||||
|
||||
def warn(*args)
|
||||
return unless @service
|
||||
@service.warn(*args)
|
||||
end
|
||||
|
||||
def ignored_value(param, value, reason: nil, **info)
|
||||
message = reason ? "query value #{value} for #{param} #{reason}, ignored" : "query value #{value} for #{param} ignored"
|
||||
warn(message, warning_type: :ignored_value, parameter: param, value: value, **info)
|
||||
end
|
||||
|
||||
def perform_async(identifier, *args)
|
||||
|
@ -72,6 +111,45 @@ module Travis::API::V3
|
|||
value.split(?,.freeze)
|
||||
end
|
||||
|
||||
def sort(collection)
|
||||
return collection unless sort_by = params["sort_by".freeze] || self.class.default_sort and not sort_by.empty?
|
||||
first = true
|
||||
list(sort_by).each do |field_with_order|
|
||||
field, order = field_with_order.split(?:.freeze, 2)
|
||||
order ||= "asc".freeze
|
||||
if sort_by? field, order
|
||||
collection = sort_by(collection, field, order: order, first: first)
|
||||
first = false
|
||||
else
|
||||
ignored_value("sort_by".freeze, field_with_order, reason: "not a valid sort mode".freeze)
|
||||
end
|
||||
end
|
||||
collection
|
||||
end
|
||||
|
||||
def sort_by?(field, order)
|
||||
return false unless order == "asc".freeze or order == "desc".freeze
|
||||
self.class.sort_by.include?(field)
|
||||
end
|
||||
|
||||
def sort_by(collection, field, order: nil, first: false)
|
||||
raise ArgumentError, 'cannot sort by that' unless sort_by?(field, order)
|
||||
actual = self.class.sort_by.fetch(field)
|
||||
line = "#{actual} #{order.upcase}"
|
||||
|
||||
if sort_join?(collection, actual)
|
||||
collection = collection.joins(actual.to_sym)
|
||||
elsif actual != field and sort_join?(collection, field)
|
||||
collection = collection.joins(field.to_sym)
|
||||
end
|
||||
|
||||
first ? collection.reorder(line) : collection.order(line)
|
||||
end
|
||||
|
||||
def sort_join?(collection, field)
|
||||
!collection.reflect_on_association(field.to_sym).nil?
|
||||
end
|
||||
|
||||
def user_condition(value)
|
||||
case value
|
||||
when String then { login: value }
|
||||
|
|
|
@ -26,6 +26,7 @@ module Travis::API::V3
|
|||
|
||||
def self.paginate(**options)
|
||||
params("limit".freeze, "offset".freeze)
|
||||
params("sort_by".freeze) if query_factory.sortable?
|
||||
@paginator = Paginator.new(**options)
|
||||
end
|
||||
|
||||
|
@ -37,6 +38,10 @@ module Travis::API::V3
|
|||
!!@paginator if defined? @paginator
|
||||
end
|
||||
|
||||
def self.query_factory
|
||||
Queries[result_type]
|
||||
end
|
||||
|
||||
attr_accessor :access_control, :params
|
||||
|
||||
def initialize(access_control, params)
|
||||
|
@ -47,7 +52,7 @@ module Travis::API::V3
|
|||
end
|
||||
|
||||
def query(type = result_type)
|
||||
@queries[type] ||= Queries[type].new(params, result_type)
|
||||
@queries[type] ||= Queries[type].new(params, result_type, service: self)
|
||||
end
|
||||
|
||||
def github(user = nil)
|
||||
|
@ -81,7 +86,21 @@ module Travis::API::V3
|
|||
def run
|
||||
not_found unless result = run!
|
||||
result = result(result_type, result) unless result.is_a? Result
|
||||
self.class.paginate? ? paginate(result) : result
|
||||
result = paginate(result) if self.class.paginate?
|
||||
apply_warnings(result)
|
||||
result
|
||||
end
|
||||
|
||||
def warnings
|
||||
@warnings ||= []
|
||||
end
|
||||
|
||||
def warn(*args)
|
||||
warnings << args
|
||||
end
|
||||
|
||||
def apply_warnings(result)
|
||||
warnings.each { |args| result.warn(*args) }
|
||||
end
|
||||
|
||||
def paginate(result)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Travis::API::V3
|
||||
class Services::Branches::Find < Service
|
||||
paginate
|
||||
|
||||
def run!
|
||||
query.find(find(:repository))
|
||||
end
|
||||
|
|
|
@ -171,4 +171,60 @@ describe Travis::API::V3::Services::Branches::Find do
|
|||
"exists_on_github" => true }]}
|
||||
}
|
||||
end
|
||||
|
||||
describe "sorting by name" do
|
||||
before { get("/v3/repo/#{repo.id}/branches?sort_by=name&limit=1") }
|
||||
example { expect(last_response).to be_ok }
|
||||
example { expect(parsed_body["@pagination"]).to be == {
|
||||
"limit" => 1,
|
||||
"offset" => 0,
|
||||
"count" => 1,
|
||||
"is_first" => true,
|
||||
"is_last" => true,
|
||||
"next" => nil,
|
||||
"prev" => nil,
|
||||
"first" => {
|
||||
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=name&limit=1",
|
||||
"offset" => 0,
|
||||
"limit" => 1 },
|
||||
"last" => {
|
||||
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=name&limit=1",
|
||||
"offset" => 0,
|
||||
"limit" => 1 }}
|
||||
}
|
||||
end
|
||||
|
||||
describe "sorting by name:desc" do
|
||||
before { get("/v3/repo/#{repo.id}/branches?sort_by=name%3Adesc&limit=1") }
|
||||
example { expect(last_response).to be_ok }
|
||||
example { expect(parsed_body["@pagination"]).to be == {
|
||||
"limit" => 1,
|
||||
"offset" => 0,
|
||||
"count" => 1,
|
||||
"is_first" => true,
|
||||
"is_last" => true,
|
||||
"next" => nil,
|
||||
"prev" => nil,
|
||||
"first" => {
|
||||
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=name%3Adesc&limit=1",
|
||||
"offset" => 0,
|
||||
"limit" => 1 },
|
||||
"last" => {
|
||||
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=name%3Adesc&limit=1",
|
||||
"offset" => 0,
|
||||
"limit" => 1 }}
|
||||
}
|
||||
end
|
||||
|
||||
describe "sorting by unknown sort field" do
|
||||
before { get("/v3/repo/#{repo.id}/branches?sort_by=name:desc,foo&limit=1") }
|
||||
example { expect(last_response).to be_ok }
|
||||
example { expect(parsed_body["@warnings"]).to be == [{
|
||||
"@type" => "warning",
|
||||
"message" => "query value foo for sort_by not a valid sort mode, ignored",
|
||||
"warning_type"=> "ignored_value",
|
||||
"parameter" => "sort_by",
|
||||
"value" => "foo"
|
||||
}]}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue
Block a user