From 9449ada1cdcd794598af3cdd6816bdc1b9115e0a Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Mon, 9 Mar 2015 19:48:52 +0100 Subject: [PATCH] v3: add attributes to service index --- lib/travis/api/v3/constant_resolver.rb | 5 +- lib/travis/api/v3/renderer/model_renderer.rb | 8 +- lib/travis/api/v3/service_index.rb | 11 +- spec/v3/service_index_spec.rb | 104 +++++++++++++++---- 4 files changed, 100 insertions(+), 28 deletions(-) diff --git a/lib/travis/api/v3/constant_resolver.rb b/lib/travis/api/v3/constant_resolver.rb index 5c5bb74c..0450fabe 100644 --- a/lib/travis/api/v3/constant_resolver.rb +++ b/lib/travis/api/v3/constant_resolver.rb @@ -9,9 +9,12 @@ module Travis::API::V3 attr_accessor :resolver_cache - def [](key) + def [](key, raise_unknown = true) return key unless key.is_a? Symbol resolver_cache[key] ||= const_get(key.to_s.camelize, false) + rescue NameError => e + raise e if raise_unknown + raise e unless e.message.include?(key.to_s.camelize) end def extended(base) diff --git a/lib/travis/api/v3/renderer/model_renderer.rb b/lib/travis/api/v3/renderer/model_renderer.rb index ebe3dac9..7a253178 100644 --- a/lib/travis/api/v3/renderer/model_renderer.rb +++ b/lib/travis/api/v3/renderer/model_renderer.rb @@ -14,7 +14,7 @@ module Travis::API::V3 def self.representation(name, *fields) fields.each do |field| class_eval "def #{field}; @model.#{field}; end" unless method_defined?(field) - available_fields << field.to_s + available_attributes << field.to_s end representations[name] = fields end @@ -23,8 +23,8 @@ module Travis::API::V3 @representations ||= {} end - def self.available_fields - @available_fields ||= Set.new + def self.available_attributes + @available_attributes ||= Set.new end def self.render(model, representation = :standard, **options) @@ -70,7 +70,7 @@ module Travis::API::V3 include.each do |qualified_field| raise WrongParams, 'illegal format for include parameter'.freeze unless /\A(?\w+)\.(?\w+)\Z$/ =~ qualified_field next if prefix != excepted_type - raise WrongParams, 'no field %p to include'.freeze % qualified_field unless self.class.available_fields.include?(field) + raise WrongParams, 'no field %p to include'.freeze % qualified_field unless self.class.available_attributes.include?(field) field &&= field.to_sym fields << field unless fields.include?(field) diff --git a/lib/travis/api/v3/service_index.rb b/lib/travis/api/v3/service_index.rb index de56b37e..39114408 100644 --- a/lib/travis/api/v3/service_index.rb +++ b/lib/travis/api/v3/service_index.rb @@ -25,16 +25,19 @@ module Travis::API::V3 def render_json resources = { } routes.resources.each do |resource| - resources[resource.identifier] ||= {} + data = resources[resource.identifier] ||= { :@type => :resource, :actions => {} } + if renderer = Renderer[resource.identifier, false] and renderer.respond_to? :available_attributes + data[:attributes] = renderer.available_attributes + end resource.services.each do |(request_method, sub_route), service| - list = resources[resource.identifier][service] ||= [] + list = resources[resource.identifier][:actions][service] ||= [] pattern = sub_route ? resource.route + sub_route : resource.route pattern.to_templates.each do |template| - list << { 'request_method'.freeze => request_method, 'uri_template'.freeze => prefix + template } + list << { :@type => :template, :request_method => request_method, :uri_template => prefix + template } end end end - { :@type => 'home'.freeze, :resources => resources } + { :@type => :home, :resources => resources } end def render_json_home diff --git a/spec/v3/service_index_spec.rb b/spec/v3/service_index_spec.rb index 8cb7fcfb..b4cdb3e3 100644 --- a/spec/v3/service_index_spec.rb +++ b/spec/v3/service_index_spec.rb @@ -7,25 +7,91 @@ describe Travis::API::V3::ServiceIndex do let(:response) { get(path, {}, headers) } describe "custom json entry point" do - let(:expected_resources) {{ - "repository" => { - "find" => [{"request_method"=>"GET", "uri_template"=>"#{path}repo/{repository.id}"}], - "enable" => [{"request_method"=>"POST", "uri_template"=>"#{path}repo/{repository.id}/enable"}], - "disable" => [{"request_method"=>"POST", "uri_template"=>"#{path}repo/{repository.id}/disable"}] }, - "repositories" => { - "for_current_user" => [{"request_method"=>"GET", "uri_template"=>"#{path}repos"}] }, - "branch" => { - "find" => [{"request_method"=>"GET", "uri_template"=>"#{path}repo/{repository.id}/branch/{branch.name}"}]}, - "build" => { - "find" => [{"request_method"=>"GET", "uri_template"=>"#{path}build/{build.id}"}] }, - "organizations" => { - "for_current_user" => [{"request_method"=>"GET", "uri_template"=>"#{path}orgs"}] }, - "organization" => { - "find" => [{"request_method"=>"GET", "uri_template"=>"#{path}org/{organization.id}"}] }, - "requests" => { - "find" => [{"request_method"=>"GET", "uri_template"=>"#{path}repo/{repository.id}/requests"}], - "create" => [{"request_method"=>"POST", "uri_template"=>"#{path}repo/{repository.id}/requests"}]} - }} + let(:expected_resources) { + {"requests"=> + {"@type"=>"resource", + "actions"=> + {"find"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}repo/{repository.id}/requests"}], + "create"=> + [{"@type"=>"template", + "request_method"=>"POST", + "uri_template"=>"#{path}repo/{repository.id}/requests"}]}}, + "branch"=> + {"@type"=>"resource", + "actions"=> + {"find"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}repo/{repository.id}/branch/{branch.name}"}]}, + "attributes"=>["name", "last_build", "repository"]}, + "repository"=> + {"@type"=>"resource", + "actions"=> + {"find"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}repo/{repository.id}"}], + "enable"=> + [{"@type"=>"template", + "request_method"=>"POST", + "uri_template"=>"#{path}repo/{repository.id}/enable"}], + "disable"=> + [{"@type"=>"template", + "request_method"=>"POST", + "uri_template"=>"#{path}repo/{repository.id}/disable"}]}, + "attributes"=> + ["id", + "slug", + "name", + "description", + "github_language", + "active", + "private", + "owner", + "last_build", + "default_branch"]}, + "repositories"=> + {"@type"=>"resource", + "actions"=> + {"for_current_user"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}repos"}]}}, + "build"=> + {"@type"=>"resource", + "actions"=> + {"find"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}build/{build.id}"}]}, + "attributes"=> + ["id", + "number", + "state", + "duration", + "started_at", + "finished_at", + "repository", + "branch"]}, + "organization"=> + {"@type"=>"resource", + "actions"=> + {"find"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}org/{organization.id}"}]}, + "attributes"=>["id", "login", "name", "github_id"]}, + "organizations"=> + {"@type"=>"resource", + "actions"=> + {"for_current_user"=> + [{"@type"=>"template", + "request_method"=>"GET", + "uri_template"=>"#{path}orgs"}]}}} + } describe 'with /v3 prefix' do let(:path) { '/v3/' }