diff --git a/.gitignore b/.gitignore index 22fe389..43e1500 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ spec/dummy/db/*.sqlite3 spec/dummy/log/*.log spec/dummy/tmp/ spec/dummy/.sass-cache +*.swp +*.un~ +tags diff --git a/.travis.yml b/.travis.yml index 222078e..4c9dc22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: ruby rvm: - 1.9.3 - - 2.0.0 + - 2.1.2 diff --git a/README.md b/README.md index faa255f..9932319 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # ApiTaster [![endorse](http://api.coderwall.com/fredwu/endorsecount.png)](http://coderwall.com/fredwu) [![Build Status](https://secure.travis-ci.org/fredwu/api_taster.png?branch=master)](http://travis-ci.org/fredwu/api_taster) [![Dependency Status](https://gemnasium.com/fredwu/api_taster.png)](https://gemnasium.com/fredwu/api_taster) +### NOTE +> If you want to use this gem with Rails 3x/4.0 please specify version 0.7.0 in +your Gemfile. + +> Version 0.8 of this gem is compatible only with Rails 4.1. + A quick and easy way to visually test your Rails application's API. ![](http://i.imgur.com/8Dnto.png) @@ -29,7 +35,7 @@ Rails.application.routes.draw do end ``` -In `routes.rb`, define parameters for each API endpoint after the normal routes definition block. For example: +In `lib/api_tasters/routes.rb`, define parameters for each API endpoint after the normal routes definition block. For example: ```ruby if Rails.env.development? @@ -60,10 +66,31 @@ if Rails.env.development? end ``` +You can change the default `lib/api_tasters/routes.rb` path by creating `config/initializers/api_taster.rb` with the content below: +```ruby +ApiTaster.route_path = Rails.root.to_s + "/app/api_tasters" # just an example +``` + ### Share Params with Test Factories If you use a test factory such as [FactoryGirl](https://github.com/thoughtbot/factory_girl), you can require your test factories and share the params. For example in FactoryGirl you can use the `attributes_for(:name_of_factory)` method. +### Custom Headers + +If there are certain headers (such as auth token) that need to be present to +consume an API endpoint, you may set then in `APITaster.global_headers` before +`APITaster.routes`: + +```ruby +ApiTaster.global_headers = { + 'Authorization' => 'Token token=teGpfbVitpnUwm7qStf9' +} + +ApiTaster.routes do + # your route definitions +end +``` + ### Global Params If there are certain params (such as API version and auth token) that need to be present in every API endpoint, you may set them in `ApiTaster.global_params` before `ApiTaster.routes`: diff --git a/api_taster.gemspec b/api_taster.gemspec index 6f5666b..514c4a6 100644 --- a/api_taster.gemspec +++ b/api_taster.gemspec @@ -14,10 +14,10 @@ Gem::Specification.new do |s| s.files = `git ls-files`.split($\) s.test_files = Dir["spec/**/*"] - s.add_dependency 'rails', '~> 4.0.0' + s.add_dependency 'rails', '~> 4.1.0' s.add_dependency 'jquery-rails' - s.add_dependency 'sass-rails' - s.add_dependency 'bootstrap-sass', '~> 2.1' + s.add_dependency 'sass-rails', '~> 4.0.3' + s.add_dependency 'bootstrap-sass', '~> 3.1.0.0' s.add_dependency 'redcarpet' s.add_dependency 'remotipart', '~> 1.0' diff --git a/app/assets/javascripts/api_taster/app.js b/app/assets/javascripts/api_taster/app.js index 1abd534..292309f 100644 --- a/app/assets/javascripts/api_taster/app.js +++ b/app/assets/javascripts/api_taster/app.js @@ -18,11 +18,11 @@ var ApiTaster = { detectContentType: function(response) { var contentType = response.getResponseHeader("Content-Type"); - var detectedContentType = null + var detectedContentType = null; if (contentType.match(/application\/json/)) { detectedContentType = 'json'; - } + }; return detectedContentType; }, @@ -55,7 +55,13 @@ var ApiTaster = { } return baseUrl; - } + }, + + setHeaders: function(headers) { + this.headers = headers; + }, + + headers: [] }; @@ -117,6 +123,12 @@ jQuery(function($) { ApiTaster.disableUrlParams(); window.ajax = $.ajax({ + beforeSend: function(xhr) { + var headers = ApiTaster.headers; + for(var l = headers.length, i = 0; i < l; i ++) { + xhr.setRequestHeader(headers[i].key, headers[i].value); + } + }, url: ApiTaster.getSubmitUrl($form), type: $form.attr('method'), data: $form.serialize() diff --git a/app/controllers/api_taster/routes_controller.rb b/app/controllers/api_taster/routes_controller.rb index e5d8678..bd6b40a 100644 --- a/app/controllers/api_taster/routes_controller.rb +++ b/app/controllers/api_taster/routes_controller.rb @@ -1,6 +1,7 @@ module ApiTaster class RoutesController < ApiTaster::ApplicationController before_filter :map_routes + layout false, except: :index def index @routes = Route.grouped_routes diff --git a/app/helpers/api_taster/application_helper.rb b/app/helpers/api_taster/application_helper.rb index 194c161..b85118f 100644 --- a/app/helpers/api_taster/application_helper.rb +++ b/app/helpers/api_taster/application_helper.rb @@ -6,5 +6,9 @@ def markdown(text) markdown_renderer ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML) markdown_renderer.render(text).html_safe end + + def headers_js_callback + render partial: "api_taster/routes/headers.js", locals: {headers: ApiTaster.global_headers} + end end end diff --git a/app/views/api_taster/routes/_headers.js b/app/views/api_taster/routes/_headers.js new file mode 100644 index 0000000..e657073 --- /dev/null +++ b/app/views/api_taster/routes/_headers.js @@ -0,0 +1,10 @@ +(function() { + if(typeof ApiTaster !== 'undefined') { + ApiTaster.setHeaders( + <%= JSON(headers.collect {|header, value| + {key: header, value: value} + }).html_safe + %> + ); + } +}).apply({}); diff --git a/app/views/api_taster/routes/show.html.erb b/app/views/api_taster/routes/show.html.erb index 2825259..24550e7 100644 --- a/app/views/api_taster/routes/show.html.erb +++ b/app/views/api_taster/routes/show.html.erb @@ -5,6 +5,10 @@ :label_type => 'important' %> + + <% if @params.is_a?(Hash) && @params.has_key?(:undefined) %> <%= render 'undefined_route', :route => @params[:undefined] %> <% else %> @@ -16,7 +20,7 @@ <% end %> <% @params.each do |param| %> - <%= form_tag @route[:path], :method => @route[:verb], :class => 'well form-horizontal', :remote => true do %> + <%= form_tag @route[:full_path], :method => @route[:verb], :class => 'well form-horizontal', :remote => true do %> <% if param[:url_params].empty? && param[:post_params].empty? %>
diff --git a/lib/api_taster.rb b/lib/api_taster.rb index 81d1168..25e7895 100644 --- a/lib/api_taster.rb +++ b/lib/api_taster.rb @@ -15,6 +15,9 @@ module ApiTaster mattr_accessor :route_path self.route_path = "#{Rails.root}/lib/api_tasters" + mattr_accessor :global_headers + self.global_headers = {} + def self.routes(&block) ApiTaster::RouteCollector.routes << block end diff --git a/lib/api_taster/form_builder.rb b/lib/api_taster/form_builder.rb index 10c8f19..c623c99 100644 --- a/lib/api_taster/form_builder.rb +++ b/lib/api_taster/form_builder.rb @@ -1,6 +1,7 @@ module ApiTaster class FormBuilder < AbstractController::Base include AbstractController::Rendering + include ActionView::Layouts include ActionView::Context include ActionView::Helpers::CaptureHelper @@ -48,7 +49,7 @@ def add_to_buffer(params, parent_labels = []) def add_element_to_buffer(parent_labels, label, value) @_buffer += render( - :partial => 'api_taster/routes/param_form_element', + :template => 'api_taster/routes/_param_form_element', :locals => { :label => "#{print_labels(parent_labels)}#{label}", :label_text => label, @@ -59,7 +60,7 @@ def add_element_to_buffer(parent_labels, label, value) def add_legend_to_buffer(parent_labels, label) @_buffer += render( - :partial => 'api_taster/routes/param_form_legend', + :template => 'api_taster/routes/_param_form_legend', :locals => { :label => print_labels(parent_labels.clone << label) } ) end diff --git a/lib/api_taster/route.rb b/lib/api_taster/route.rb index e36c0ab..e0acfbf 100644 --- a/lib/api_taster/route.rb +++ b/lib/api_taster/route.rb @@ -116,12 +116,14 @@ def discover_rack_app(app) def normalise_route(route, path_prefix = nil) route.verb.source.split('|').map do |verb| + path = path_prefix.to_s + route.path.spec.to_s.sub('(.:format)', '') { - :id => @_route_counter+=1, - :name => route.name, - :verb => verb.gsub(/[$^]/, ''), - :path => path_prefix.to_s + route.path.spec.to_s.sub('(.:format)', ''), - :reqs => route.requirements + :id => @_route_counter+=1, + :name => route.name, + :verb => verb.gsub(/[$^]/, ''), + :path => path, + :full_path => rails_url_root + path, + :reqs => route.requirements } end end @@ -143,6 +145,10 @@ def hash_diff(h1, h2) h2[k] == v end.merge!(h2.dup.delete_if { |k, v| h1.has_key?(k) }) end + + def rails_url_root + ActionController::Base.relative_url_root.to_s.chomp('/') + end end end end diff --git a/lib/api_taster/version.rb b/lib/api_taster/version.rb index c02dea4..ec73bd3 100644 --- a/lib/api_taster/version.rb +++ b/lib/api_taster/version.rb @@ -1,3 +1,3 @@ module ApiTaster - VERSION = "0.7.0" + VERSION = "0.8.1" end diff --git a/spec/route_spec.rb b/spec/route_spec.rb index d376568..ff93817 100644 --- a/spec/route_spec.rb +++ b/spec/route_spec.rb @@ -15,9 +15,10 @@ module ApiTaster :name => 'home', :verb => 'GET', :path => '/home', + :full_path => '/home', :reqs => { - :controller => 'application', - :action => 'home' + :action => 'home', + :controller => 'application' } } end