v3: add @href to payloads

This commit is contained in:
Konstantin Haase 2015-02-17 15:43:38 +01:00
parent 89f96c98ec
commit 32c2d9b0b9
14 changed files with 71 additions and 22 deletions

View File

@ -14,6 +14,12 @@ module Travis
[status, headers, [payload] ]
end
def location(env)
location = env['SCRIPT_NAME'.freeze].to_s + env['PATH_INFO'.freeze].to_s
location << ??.freeze << env['QUERY_STRING'.freeze] if env['QUERY_STRING'.freeze] and not env['QUERY_STRING'.freeze].empty?
location
end
extend self
load_dir("#{__dir__}/v3")

View File

@ -1,5 +1,8 @@
module Travis::API::V3
module Renderer
EXPANDER_CACHE = Tool::ThreadLocal.new
private_constant :EXPANDER_CACHE
extend ConstantResolver
extend self
@ -15,5 +18,31 @@ module Travis::API::V3
value = object.public_send(attribute)
value.nil? ? defaults[attribute] : value
end
def clear(**args)
args.select { |key, value| !value.nil? }
end
def href(type, script_name: nil, **args)
expander = EXPANDER_CACHE[[type, script_name, args.keys]] ||= begin
resource = Routes.resources.detect { |r| r.identifier == type }
unprefixed = args.keys.reject { |a| a.to_s.include? ?..freeze }
route = resource.route
route &&= Mustermann.new(script_name, type: :identity) + route if script_name and not script_name.empty?
generate_expander(route, type, unprefixed)
end
expander.call(args)
end
private
def generate_expander(route, prefix, unprefixed)
return proc { |**| } unless route.respond_to? :expand
proc do |**args|
unprefixed.each { |key| args[:"#{prefix}.#{key}"] = args.delete(key) }
route.expand(**args)
end
end
end
end

View File

@ -2,7 +2,7 @@ module Travis::API::V3
module Renderer::Error
extend self
def render(type)
def render(type, **)
{
:@type => 'pending'.freeze,
:resource_type => type

View File

@ -2,9 +2,9 @@ module Travis::API::V3
module Renderer::Collection
extend self
def render(collection_type, entry_type, entries, **additional)
entries &&= entries.map { |entry| Renderer[entry_type].render(entry) }
{ :@type => collection_type, collection_type => entries, **additional }
def render(collection_type, entry_type, entries, href: nil, script_name: nil, **additional)
entries &&= entries.map { |entry| Renderer[entry_type].render(entry, script_name: script_name) }
Renderer.clear(:@type => collection_type, :@href => href).merge(collection_type => entries, **additional)
end
end
end

View File

@ -2,7 +2,7 @@ module Travis::API::V3
module Renderer::Error
extend self
def render(error)
def render(error, **)
{
:@type => 'error'.freeze,
:error_type => error.type,

View File

@ -3,7 +3,7 @@ module Travis::API::V3
DIRECT_ATTRIBUTES = %i[id login name github_id]
extend self
def render(organization)
def render(organization, **)
{ :@type => 'organization'.freeze, **direct_attributes(organization) }
end

View File

@ -2,8 +2,8 @@ module Travis::API::V3
module Renderer::Organizations
extend self
def render(repositories)
Renderer[:collection].render(:organizations, :organization, repositories)
def render(repositories, **options)
Renderer[:collection].render(:organizations, :organization, repositories, **options)
end
end
end

View File

@ -2,8 +2,8 @@ module Travis::API::V3
module Renderer::Repositories
extend self
def render(repositories)
Renderer[:collection].render(:repositories, :repository, repositories)
def render(repositories, **options)
Renderer[:collection].render(:repositories, :repository, repositories, **options)
end
end
end

View File

@ -4,8 +4,12 @@ module Travis::API::V3
DEFAULTS = { active: false, default_branch: 'master' }
extend self
def render(repository)
{ :@type => 'repository'.freeze, **Renderer.get_attributes(repository, *DIRECT_ATTRIBUTES, **DEFAULTS), **nested_resources(repository) }
def render(repository, script_name: nil, **)
{
:@type => 'repository'.freeze,
:@href => Renderer.href(:repository, id: repository.id, script_name: script_name),
**Renderer.get_attributes(repository, *DIRECT_ATTRIBUTES, **DEFAULTS), **nested_resources(repository)
}
end
def nested_resources(repository)

View File

@ -1,6 +1,6 @@
module Travis::API::V3
class Result
attr_accessor :type, :resource, :status
attr_accessor :type, :resource, :status, :href
def initialize(type, resource = [], status: 200)
@type, @resource, @status = type, resource, status
@ -15,8 +15,10 @@ module Travis::API::V3
self
end
def render
Renderer[type].render(resource)
def render(params, env)
href = self.href
href = V3.location(env) if href.nil? and env['REQUEST_METHOD'.freeze] == 'GET'.freeze
Renderer[type].render(resource, href: href, script_name: env['SCRIPT_NAME'.freeze])
end
def method_missing(method, *args)

View File

@ -19,15 +19,15 @@ module Travis::API::V3
service = factory.new(access_control, env_params.merge(params))
result = service.run
render(result, env_params)
render(result, env_params, env)
rescue Error => error
result = Result.new(:error, error)
headers = error.status == 404 ? CASCADE : {}
V3.response(result.render, headers, status: error.status)
V3.response(result.render(env_params, env), headers, status: error.status)
end
def render(result, env_params)
V3.response(result.render, status: result.status)
def render(result, env_params, env)
V3.response(result.render(env_params, env), status: result.status)
end
def service_index(env)

View File

@ -19,6 +19,7 @@ describe Travis::API::V3::Services::Organizations::ForCurrentUser do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "organizations",
"@href" => "/v3/orgs",
"organizations" => [{
"@type" => "organization",
"id" => org.id,

View File

@ -14,8 +14,10 @@ describe Travis::API::V3::Services::Repositories::ForCurrentUser do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "repositories",
"@href" => "/v3/repos",
"repositories" => [{
"@type" => "repository",
"@href" => "/v3/repo/#{repo.id}",
"id" => repo.id,
"name" => "minimal",
"slug" => "svenfuchs/minimal",
@ -40,9 +42,10 @@ describe Travis::API::V3::Services::Repositories::ForCurrentUser do
end
describe "filter: private=false" do
before { get("/v3/repos", {"repository.private" => "false"}, headers) }
example { expect(last_response) .to be_ok }
example { expect(JSON.load(body)['repositories']) .to be == [] }
before { get("/v3/repos", {"repository.private" => "false"}, headers) }
example { expect(last_response) .to be_ok }
example { expect(JSON.load(body)['repositories']) .to be == [] }
example { expect(JSON.load(body)['@href']) .to be == "/v3/repos?repository.private=false" }
end
describe "filter: active=false" do

View File

@ -8,6 +8,7 @@ describe Travis::API::V3::Services::Repository::Find do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "repository",
"@href" => "/v3/repo/#{repo.id}",
"id" => repo.id,
"name" => "minimal",
"slug" => "svenfuchs/minimal",
@ -78,6 +79,7 @@ describe Travis::API::V3::Services::Repository::Find do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "repository",
"@href" => "/v3/repo/#{repo.id}",
"id" => repo.id,
"name" => "minimal",
"slug" => "svenfuchs/minimal",
@ -133,6 +135,7 @@ describe Travis::API::V3::Services::Repository::Find do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "repository",
"@href" => "/v3/repo/#{repo.id}",
"id" => repo.id,
"name" => "minimal",
"slug" => "svenfuchs/minimal",
@ -194,6 +197,7 @@ describe Travis::API::V3::Services::Repository::Find do
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "repository",
"@href" => "/v3/repo/#{repo.id}",
"id" => repo.id,
"name" => "minimal",
"slug" => "svenfuchs/minimal",