Merge pull request #203 from travis-ci/rkh-branches-filtering-and-sorting

better branches filtering and sorting
This commit is contained in:
Konstantin Haase 2015-10-13 13:18:12 +02:00
commit aa222ad6b2
4 changed files with 104 additions and 7 deletions

View File

@ -1,10 +1,33 @@
module Travis::API::V3
class Queries::Branches < Query
sortable_by :name, last_build: "builds.started_at".freeze
default_sort "last_build:desc"
params :exists_on_github, prefix: :branch
sortable_by :name,
last_build: "builds.started_at".freeze,
exists_on_github: sort_condition(:exists_on_github),
default_branch: sort_condition(name: "repositories.default_branch")
default_sort "default_branch,exists_on_github,last_build:desc"
def find(repository)
sort repository.branches
sort(filter(repository.branches), repository: repository)
end
def sort_by(collection, field, repository: nil, **options)
return super unless field == "default_branch".freeze
if repository
options[:sql] = sort_condition(name: quote(repository.default_branch_name))
else
collection = collection.joins(:repository)
end
super(collection, field, **options)
end
def filter(list)
list = list.where(exists_on_github: bool(exists_on_github)) unless exists_on_github.nil?
list
end
end
end

View File

@ -48,6 +48,13 @@ module Travis::API::V3
mapping.each { |key, value| sort_by[key.to_s] = prefix(value) }
end
def self.sort_condition(condition)
if condition.is_a? Hash
condition = condition.map { |e| e.map { |v| prefix(v) }.join(" = ".freeze) }.join(" and ".freeze)
end
"(case when #{prefix(condition)} then 1 else 2 end)"
end
def self.sortable?
!sort_by.empty?
end
@ -111,14 +118,14 @@ module Travis::API::V3
value.split(?,.freeze)
end
def sort(collection)
def sort(collection, **options)
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)
collection = sort_by(collection, field, order: order, first: first, **options)
first = false
else
ignored_value("sort_by".freeze, field_with_order, reason: "not a valid sort mode".freeze)
@ -132,9 +139,9 @@ module Travis::API::V3
self.class.sort_by.include?(field)
end
def sort_by(collection, field, order: nil, first: false)
def sort_by(collection, field, order: nil, first: false, sql: nil, **)
raise ArgumentError, 'cannot sort by that' unless sort_by?(field, order)
actual = self.class.sort_by.fetch(field)
actual = sql || self.class.sort_by.fetch(field)
line = "#{actual} #{order.upcase}"
if sort_join?(collection, actual)
@ -150,6 +157,14 @@ module Travis::API::V3
!collection.reflect_on_association(field.to_sym).nil?
end
def sort_condition(*args)
self.class.sort_condition(*args)
end
def quote(value)
ActiveRecord::Base.connection.quote(value)
end
def user_condition(value)
case value
when String then { login: value }

View File

@ -1,5 +1,6 @@
module Travis::API::V3
class Services::Branches::Find < Service
params :exists_on_github, prefix: :branch
paginate
def run!

View File

@ -172,6 +172,20 @@ describe Travis::API::V3::Services::Branches::Find do
}
end
describe "filtering by exists_on_github" do
describe "false" do
before { get("/v3/repo/#{repo.id}/branches?branch.exists_on_github=false") }
example { expect(last_response).to be_ok }
example { expect(parsed_body["branches"]).to be_empty }
end
describe "true" do
before { get("/v3/repo/#{repo.id}/branches?branch.exists_on_github=true") }
example { expect(last_response).to be_ok }
example { expect(parsed_body["branches"]).not_to be_empty }
end
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 }
@ -216,6 +230,50 @@ describe Travis::API::V3::Services::Branches::Find do
}
end
describe "sorting by exists_on_github" do
before { get("/v3/repo/#{repo.id}/branches?sort_by=exists_on_github&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=exists_on_github&limit=1",
"offset" => 0,
"limit" => 1 },
"last" => {
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=exists_on_github&limit=1",
"offset" => 0,
"limit" => 1 }}
}
end
describe "sorting by default_branch" do
before { get("/v3/repo/#{repo.id}/branches?sort_by=default_branch&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=default_branch&limit=1",
"offset" => 0,
"limit" => 1 },
"last" => {
"@href" => "/v3/repo/#{repo.id}/branches?sort_by=default_branch&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 }