versionist-1.7.0/0000755000004100000410000000000013273750405013762 5ustar www-datawww-dataversionist-1.7.0/lib/0000755000004100000410000000000013273750405014530 5ustar www-datawww-dataversionist-1.7.0/lib/generators/0000755000004100000410000000000013273750405016701 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/0000755000004100000410000000000013273750405021106 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_presenter/0000755000004100000410000000000013273750405023766 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_presenter/templates/0000755000004100000410000000000013273750405025764 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_presenter/templates/new_presenter.rb0000644000004100000410000000052713273750405031175 0ustar www-datawww-dataclass <%= module_name %>::<%= class_name%>Presenter < <%= module_name %>::BasePresenter def initialize(<%= file_name %>) @<%= file_name %> = <%= file_name %> end def as_json(options={}) # fill me in... end def to_xml(options={}, &block) xml = options[:builder] ||= Builder::XmlMarkup.new # fill me in... end end versionist-1.7.0/lib/generators/versionist/new_presenter/templates/new_presenter_spec.rb0000644000004100000410000000014513273750405032203 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::<%= class_name%>Presenter do end versionist-1.7.0/lib/generators/versionist/new_presenter/templates/new_presenter_test_rails_5.rb0000644000004100000410000000030013273750405033637 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::<%= class_name%>PresenterTest < ActiveSupport::TestCase # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_presenter/templates/new_presenter_test.rb0000644000004100000410000000027513273750405032234 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::<%= class_name%>PresenterTest < Test::Unit::TestCase # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_presenter/new_presenter_generator.rb0000644000004100000410000000320213273750405031236 0ustar www-datawww-datamodule Versionist class NewPresenterGenerator < Rails::Generators::NamedBase include InflectorFixes include RspecHelper desc "creates a new presenter for an existing API version" source_root File.expand_path('../templates', __FILE__) argument :module_name, :type => :string def new_presenter in_root do raise "API module namespace #{module_name} doesn't exist. Please run \'rails generate versionist:new_api_version\' generator first" if !File.exists?("app/presenters/#{module_name_for_path(module_name)}") template 'new_presenter.rb', File.join("app", "presenters", "#{module_name_for_path(module_name)}", "#{file_name}_presenter.rb") end end def new_presenter_test in_root do case Versionist.configuration.configured_test_framework when :test_unit if Versionist.older_than_rails_5? template 'new_presenter_test.rb', File.join("test", "presenters", "#{module_name_for_path(module_name)}", "#{file_name}_presenter_test.rb") else template 'new_presenter_test_rails_5.rb', File.join("test", "presenters", "#{module_name_for_path(module_name)}", "#{file_name}_presenter_test_rails_5.rb") end when :rspec @rspec_require_file = rspec_helper_filename template 'new_presenter_spec.rb', File.join("spec", "presenters", "#{module_name_for_path(module_name)}", "#{file_name}_presenter_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end end end versionist-1.7.0/lib/generators/versionist/new_presenter/USAGE0000644000004100000410000000054313273750405024557 0ustar www-datawww-dataDescription: Creates a new presenter class with the given name under the given version Example: rails generate versionist:new_presenter foo V2_0_0 This will create: app/presenters/v2_0_0/foo_presenter.rb In addition this will create a test for the new controller using the test_framework currently configured in your Rails app. versionist-1.7.0/lib/generators/versionist/inflector_fixes.rb0000644000004100000410000000056513273750405024624 0ustar www-datawww-datamodule Versionist # Various fixes for quirks in Rails' inflector module InflectorFixes # Transforms a module name for use in a route def module_name_for_route(module_name) module_name.gsub(/_{1}/, "__") end # Transforms a module name for use in a file path def module_name_for_path(module_name) module_name.underscore end end end versionist-1.7.0/lib/generators/versionist/copy_api_version/0000755000004100000410000000000013273750405024456 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/copy_api_version/copy_api_version_generator.rb0000644000004100000410000002556513273750405032436 0ustar www-datawww-datarequire 'yard' require 'fileutils' module Versionist class CopyApiVersionGenerator < Rails::Generators::Base include InflectorFixes desc "copies an existing API version a new API version" source_root File.expand_path('../templates', __FILE__) argument :old_version, :type => :string argument :old_module_name, :type => :string argument :new_version, :type => :string argument :new_module_name, :type => :string def copy_routes in_root do if RUBY_VERSION =~ /1.8/ || !defined?(RUBY_ENGINE) || RUBY_ENGINE != "ruby" log "ERROR: Cannot copy routes as this feature relies on the Ripper library, which is only available in MRI 1.9." return end parser = YARD::Parser::SourceParser.parse_string(File.read("config/routes.rb")) existing_routes = nil parser.enumerator.first.traverse do |node| existing_routes = node.source if node.type == :fcall && node.source =~ /api_version.*:?module\s*(=>|:)\s*("|')#{module_name_for_route(old_module_name)}("|')/ end if !existing_routes.nil? copied_routes = String.new(existing_routes) copied_routes.gsub!(/"#{module_name_for_route(old_module_name)}"/, "\"#{module_name_for_route(new_module_name)}\"") copied_routes.gsub!(/#{old_version}/, new_version) route copied_routes else say "No routes found in config/routes.rb for #{old_version}" end end end def copy_controllers in_root do if File.exists? "app/controllers/#{module_name_for_path(old_module_name)}" log "Copying all files from app/controllers/#{module_name_for_path(old_module_name)} to app/controllers/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "app/controllers/#{module_name_for_path(old_module_name)}", "app/controllers/#{module_name_for_path(new_module_name)}" Dir.glob("app/controllers/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No controllers found in app/controllers for #{old_version}" end end end # due to the inflector quirks we can't use hook_for :test_framework def copy_controller_tests in_root do case Versionist.configuration.configured_test_framework when :test_unit if File.exists? "#{Versionist.test_path}/#{module_name_for_path(old_module_name)}" log "Copying all files from #{Versionist.test_path}/#{module_name_for_path(old_module_name)} to #{Versionist.test_path}/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "#{Versionist.test_path}/#{module_name_for_path(old_module_name)}", "#{Versionist.test_path}/#{module_name_for_path(new_module_name)}" Dir.glob("#{Versionist.test_path}/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No tests found in #{Versionist.test_path} for #{old_version}" end if Versionist.older_than_rails_5? if File.exists? "test/integration/#{module_name_for_path(old_module_name)}" log "Copying all files from test/integration/#{module_name_for_path(old_module_name)} to test/integration/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "test/integration/#{module_name_for_path(old_module_name)}", "test/integration/#{module_name_for_path(new_module_name)}" Dir.glob("test/integration/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No integration tests found in test/integration for #{old_version}" end end when :rspec if File.exists? "spec/controllers/#{module_name_for_path(old_module_name)}" log "Copying all files from spec/controllers/#{module_name_for_path(old_module_name)} to spec/controllers/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "spec/controllers/#{module_name_for_path(old_module_name)}", "spec/controllers/#{module_name_for_path(new_module_name)}" Dir.glob("spec/controllers/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No controller specs found in spec/controllers for #{old_version}" end if File.exists? "spec/requests/#{module_name_for_path(old_module_name)}" log "Copying all files from spec/requests/#{module_name_for_path(old_module_name)} to spec/requests/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "spec/requests/#{module_name_for_path(old_module_name)}", "spec/requests/#{module_name_for_path(new_module_name)}" Dir.glob("spec/requests/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No request specs found in spec/requests for #{old_version}" end else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def copy_presenters in_root do if File.exists? "app/presenters/#{module_name_for_path(old_module_name)}" log "Copying all files from app/presenters/#{module_name_for_path(old_module_name)} to app/presenters/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "app/presenters/#{module_name_for_path(old_module_name)}", "app/presenters/#{module_name_for_path(new_module_name)}" Dir.glob("app/presenters/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No presenters found in app/presenters for #{old_version}" end end end def copy_presenter_tests in_root do case Versionist.configuration.configured_test_framework when :test_unit if File.exists? "test/presenters/#{module_name_for_path(old_module_name)}" log "Copying all files from test/presenters/#{module_name_for_path(old_module_name)} to test/presenters/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "test/presenters/#{module_name_for_path(old_module_name)}", "test/presenters/#{module_name_for_path(new_module_name)}" Dir.glob("test/presenters/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No presenter tests found in test/presenters for #{old_version}" end when :rspec if File.exists? "spec/presenters/#{module_name_for_path(old_module_name)}" log "Copying all files from spec/presenters/#{module_name_for_path(old_module_name)} to spec/presenters/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "spec/presenters/#{module_name_for_path(old_module_name)}", "spec/presenters/#{module_name_for_path(new_module_name)}" Dir.glob("spec/presenters/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No presenter specs found in spec/presenters for #{old_version}" end else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def copy_helpers in_root do if File.exists? "app/helpers/#{module_name_for_path(old_module_name)}" log "Copying all files from app/helpers/#{module_name_for_path(old_module_name)} to app/helpers/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "app/helpers/#{module_name_for_path(old_module_name)}", "app/helpers/#{module_name_for_path(new_module_name)}" Dir.glob("app/helpers/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No helpers found in app/helpers for #{old_version}" end end end def copy_helper_tests in_root do case Versionist.configuration.configured_test_framework when :test_unit if File.exists? "test/helpers/#{module_name_for_path(old_module_name)}" log "Copying all files from test/helpers/#{module_name_for_path(old_module_name)} to test/helpers/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "test/helpers/#{module_name_for_path(old_module_name)}", "test/helpers/#{module_name_for_path(new_module_name)}" Dir.glob("test/helpers/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No helper tests found in test/helpers for #{old_version}" end when :rspec if File.exists? "spec/helpers/#{module_name_for_path(old_module_name)}" log "Copying all files from spec/helpers/#{module_name_for_path(old_module_name)} to spec/helpers/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "spec/helpers/#{module_name_for_path(old_module_name)}", "spec/helpers/#{module_name_for_path(new_module_name)}" Dir.glob("spec/helpers/#{module_name_for_path(new_module_name)}/*.rb").each do |f| text = File.read(f) File.open(f, 'w') {|f| f << text.gsub(/#{old_module_name}/, new_module_name)} end else say "No helper specs found in spec/helpers for #{old_version}" end else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def copy_documentation in_root do if File.exists? "public/docs/#{old_version}" log "Copying all files from public/docs/#{old_version} to public/docs/#{new_version}" FileUtils.cp_r "public/docs/#{old_version}/.", "public/docs/#{new_version}" else say "No documentation found in public/docs for #{old_version}" end end end end end versionist-1.7.0/lib/generators/versionist/copy_api_version/USAGE0000644000004100000410000000170213273750405025245 0ustar www-datawww-dataDescription: Copies an existing API version to a new API version. Example: rails generate versionist:copy_api_version v2.0.0 V2_0_0 v3.0.0 V3_0_0 This will do the following: route api_version(:module => "V3__0__0", :header=>"Accept", :value=>"application/vnd.mycompany.com-v3.0.0") do end Copying all files from app/controllers/v2_0_0 to app/controllers/v3_0_0 Copying all files from spec/controllers/v2_0_0 to spec/controllers/v3_0_0 Copying all files from app/presenters/v2_0_0 to app/presenters/v3_0_0 Copying all files from spec/presenters/v2_0_0 to spec/presenters/v3_0_0 Copying all files from public/docs/v2.0.0 to public/docs/v3.0.0 Note: routes can only be copied with MRI Ruby 1.9 and above, as this feature relies on Ripper which is only available in stdlib in MRI Ruby 1.9 and above. Outside of routes copying, the other copy steps will work just fine in Ruby 1.8 and other non-MRI Ruby implementations. versionist-1.7.0/lib/generators/versionist/new_api_version/0000755000004100000410000000000013273750405024275 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_api_version/templates/0000755000004100000410000000000013273750405026273 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_presenter_test.rb0000644000004100000410000000026113273750405032657 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::BasePresenterTest < Test::Unit::TestCase # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller.rb0000644000004100000410000000010513273750405031771 0ustar www-datawww-dataclass <%= module_name %>::BaseController < ApplicationController end ././@LongLink0000644000000000000000000000015100000000000011600 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_integration_test.rbversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_integration_tes0000644000004100000410000000027513273750405034655 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::BaseControllerTest < ActionDispatch::IntegrationTest # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_api_version/templates/docs_style.rb0000644000004100000410000000037713273750405030777 0ustar www-datawww-databody {margin: 0; background-color: #fff; color: #000; font-family: Arial,sans-serif;} content {margin-left: 200px;} content h1 {text-align: center;} operations {float: left; width: 200px; border-right: 1px solid #ccc;} operations h3 {text-align: center;} versionist-1.7.0/lib/generators/versionist/new_api_version/templates/docs_index.rb0000644000004100000410000000064313273750405030742 0ustar www-datawww-data Documentation for <%= version%>

API Operations

Documentation for <%= version%>

versionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_presenter.rb0000644000004100000410000000005413273750405031620 0ustar www-datawww-dataclass <%= module_name %>::BasePresenter end versionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_presenter_spec.rb0000644000004100000410000000013113273750405032626 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::BasePresenter do end ././@LongLink0000644000000000000000000000015000000000000011577 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test.rbversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test0000644000004100000410000000027013273750405034653 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::BaseControllerTest < ActionController::TestCase # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_spec.rb0000644000004100000410000000013213273750405033003 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::BaseController do end versionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_presenter_test_rails_5.rb0000644000004100000410000000026413273750405034300 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::BasePresenterTest < ActiveSupport::TestCase # Replace this with your real tests. test "the truth" do assert true end end ././@LongLink0000644000000000000000000000016000000000000011600 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test_rails_5.rbversionist-1.7.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test0000644000004100000410000000027513273750405034660 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::BaseControllerTest < ActionDispatch::IntegrationTest # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_api_version/new_api_version_generator.rb0000644000004100000410000001524113273750405032062 0ustar www-datawww-datamodule Versionist class NewApiVersionGenerator < Rails::Generators::Base include InflectorFixes include RspecHelper desc "creates the infrastructure for a new API version" source_root File.expand_path('../templates', __FILE__) argument :version, :type => :string argument :module_name, :type => :string class_option :default, :type => :boolean class_option :header, :type => :hash, :group => :header class_option :parameter, :type => :hash, :group => :parameter class_option :path, :type => :hash, :group => :path class_option :defaults, :type => :hash, :group => :defaults def verify_options raise "Must specify at least one versioning strategy option" if !['header', 'parameter', 'path'].any? {|strategy| options.has_key?(strategy)} if options.has_key?("header") raise "Must specify name and value for header versioning strategy" if !options["header"].has_key?("name") || !options["header"].has_key?("value") end if options.has_key?("parameter") raise "Must specify name and value for parameter versioning strategy" if !options["parameter"].has_key?("name") || !options["parameter"].has_key?("value") end if options.has_key?("path") raise "Must specify value for path versioning strategy" if !options["path"].has_key?("value") end end def add_routes in_root do api_version_block = /api_version.*:module\s*(=>|:)\s*("|')#{module_name_for_route(module_name)}("|')/ matching_version_blocks = File.readlines("config/routes.rb").grep(api_version_block) raise "API version already exists in config/routes.rb" if !matching_version_blocks.empty? route_string = "api_version(:module => \"#{module_name_for_route(module_name)}\"" ['header', 'parameter', 'path'].each do |versioning_strategy| if options.has_key?(versioning_strategy) options[versioning_strategy].symbolize_keys! route_string << ", :#{versioning_strategy} => {#{options[versioning_strategy].to_s.gsub(/[\{\}]/, '').gsub('=>', ' => ')}}" end end if options.has_key?('defaults') options['defaults'].symbolize_keys! route_string << ", :defaults => {#{options['defaults'].to_s.gsub(/[\{\}]/, '').gsub('=>', ' => ')}}" end if options.has_key?('default') route_string << ", :default => true" end route_string << ") do\n end" route route_string end end def add_controller_base in_root do empty_directory "app/controllers/#{module_name_for_path(module_name)}" template 'base_controller.rb', File.join("app", "controllers", "#{module_name_for_path(module_name)}", "base_controller.rb") end end # due to the inflector quirks we can't use hook_for :test_framework def add_controller_base_tests in_root do case Versionist.configuration.configured_test_framework when :test_unit empty_directory "test/#{Versionist.test_path}/#{module_name_for_path(module_name)}" empty_directory "test/integration/#{module_name_for_path(module_name)}" if Versionist.older_than_rails_5? template 'base_controller_integration_test.rb', File.join("test", "integration", "#{module_name_for_path(module_name)}", "base_controller_test.rb") template 'base_controller_functional_test.rb', File.join("test", "#{Versionist.test_path}", "#{module_name_for_path(module_name)}", "base_controller_test.rb") else template 'base_controller_functional_test_rails_5.rb', File.join("test", "#{Versionist.test_path}", "#{module_name_for_path(module_name)}", "base_controller_test_rails_5.rb") end when :rspec @rspec_require_file = rspec_helper_filename empty_directory "spec/controllers/#{module_name_for_path(module_name)}" template 'base_controller_spec.rb', File.join("spec", "controllers", "#{module_name_for_path(module_name)}", "base_controller_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } empty_directory "spec/requests/#{module_name_for_path(module_name)}" template 'base_controller_spec.rb', File.join("spec", "requests", "#{module_name_for_path(module_name)}", "base_controller_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def add_presenters_base in_root do empty_directory "app/presenters/#{module_name_for_path(module_name)}" template 'base_presenter.rb', File.join("app", "presenters", "#{module_name_for_path(module_name)}", "base_presenter.rb") end end def add_presenter_test in_root do case Versionist.configuration.configured_test_framework when :test_unit empty_directory "test/presenters/#{module_name_for_path(module_name)}" if Versionist.older_than_rails_5? template 'base_presenter_test.rb', File.join("test", "presenters", "#{module_name_for_path(module_name)}", "base_presenter_test.rb") else template 'base_presenter_test_rails_5.rb', File.join("test", "presenters", "#{module_name_for_path(module_name)}", "base_presenter_test_rails_5.rb") end when :rspec @rspec_require_file = rspec_helper_filename empty_directory "spec/presenters/#{module_name_for_path(module_name)}" template 'base_presenter_spec.rb', File.join("spec", "presenters", "#{module_name_for_path(module_name)}", "base_presenter_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def add_helpers_dir in_root do empty_directory "app/helpers/#{module_name_for_path(module_name)}" end end def add_helpers_test_dir in_root do case Versionist.configuration.configured_test_framework when :test_unit empty_directory "test/helpers/#{module_name_for_path(module_name)}" when :rspec empty_directory "spec/helpers/#{module_name_for_path(module_name)}" else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end def add_documentation_base in_root do empty_directory "public/docs/#{version}" template 'docs_index.rb', File.join("public", "docs", "#{version}", "index.html") template 'docs_style.rb', File.join("public", "docs", "#{version}", "style.css") end end end end versionist-1.7.0/lib/generators/versionist/new_api_version/USAGE0000644000004100000410000000145013273750405025064 0ustar www-datawww-dataDescription: Creates the infrastructure for a new API version. Example: rails generate versionist:new_api_version v2.0.0 V2_0_0 header:Accept value:application/vnd.mycompany.com-v2.0.0 This will create: route api_version(:module => "V2__0__0", :header=>"Accept", :value=>"application/vnd.mycompany.com-v2.0.0") do end create app/controllers/v2_0_0 create app/controllers/v2_0_0/base_controller.rb create app/presenters/v2_0_0 create app/presenters/v2_0_0/base_presenter.rb create public/docs/v2.0.0 create public/docs/v2.0.0/index.html create public/docs/v2.0.0/style.css In addition this will create tests for base_controller.rb and base_presenter.rb using the test_framework currently configured in your Rails app. versionist-1.7.0/lib/generators/versionist/new_controller/0000755000004100000410000000000013273750405024142 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_controller/new_controller_generator.rb0000644000004100000410000000554413273750405031601 0ustar www-datawww-datamodule Versionist class NewControllerGenerator < Rails::Generators::NamedBase include InflectorFixes include RspecHelper desc "creates a new controller for an existing API version" source_root File.expand_path('../templates', __FILE__) argument :module_name, :type => :string def new_controller in_root do raise "API module namespace #{module_name} doesn't exist. Please run \'rails generate versionist:new_api_version\' generator first" if !File.exists?("app/controllers/#{module_name_for_path(module_name)}") template 'new_controller.rb', File.join("app", "controllers", "#{module_name_for_path(module_name)}", "#{file_name}_controller.rb") api_version_block = /api_version.*:?module\s*(=>|:)\s*("|')#{module_name_for_route(module_name)}("|')/ new_route = " resources :#{file_name}\n" matching_version_blocks = File.readlines("config/routes.rb").grep(api_version_block) if matching_version_blocks.empty? raise "API version doesn't exist in config/routes.rb. Please run \'rails generate versionist:new_api_version\' generator first" elsif matching_version_blocks.size > 1 raise "API version is duplicated in config/routes.rb" else version_block = matching_version_blocks.first inject_into_file "config/routes.rb", "#{new_route}", {:after => version_block, :verbose => false} end end end # due to the inflector quirks we can't use hook_for :test_framework def new_controller_tests in_root do case Versionist.configuration.configured_test_framework when :test_unit if Versionist.older_than_rails_5? template 'new_controller_integration_test.rb', File.join("test", "integration", "#{module_name_for_path(module_name)}", "#{file_name}_controller_test.rb") template 'new_controller_functional_test.rb', File.join("test", "#{Versionist.test_path}", "#{module_name_for_path(module_name)}", "#{file_name}_controller_test.rb") else template 'new_controller_functional_test_rails_5.rb', File.join("test", "#{Versionist.test_path}", "#{module_name_for_path(module_name)}", "#{file_name}_controller_test_rails_5.rb") end when :rspec @rspec_require_file = rspec_helper_filename template 'new_controller_spec.rb', File.join("spec", "controllers", "#{module_name_for_path(module_name)}", "#{file_name}_controller_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } template 'new_controller_spec.rb', File.join("spec", "requests", "#{module_name_for_path(module_name)}", "#{file_name}_controller_spec.rb"), :assigns => { :rspec_require_file => @rspec_require_file } else say "Unsupported test_framework: #{Versionist.configuration.configured_test_framework}" end end end end end versionist-1.7.0/lib/generators/versionist/new_controller/templates/0000755000004100000410000000000013273750405026140 5ustar www-datawww-dataversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_spec.rb0000644000004100000410000000014613273750405032534 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::<%= class_name%>Controller do end ././@LongLink0000644000000000000000000000014700000000000011605 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_integration_test.rbversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_integration_test.0000644000004100000410000000031213273750405034633 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::<%= class_name%>ControllerTest < ActionDispatch::IntegrationTest # Replace this with your real tests. test "the truth" do assert true end end ././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test.rbversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test.r0000644000004100000410000000030513273750405034636 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::<%= class_name%>ControllerTest < ActionController::TestCase # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller.rb0000644000004100000410000000013613273750405031521 0ustar www-datawww-dataclass <%= module_name %>::<%= class_name%>Controller < <%= module_name %>::BaseController end ././@LongLink0000644000000000000000000000015600000000000011605 Lustar rootrootversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test_rails_5.rbversionist-1.7.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test_r0000644000004100000410000000031213273750405034715 0ustar www-datawww-datarequire 'test_helper' class <%= module_name %>::<%= class_name%>ControllerTest < ActionDispatch::IntegrationTest # Replace this with your real tests. test "the truth" do assert true end end versionist-1.7.0/lib/generators/versionist/new_controller/USAGE0000644000004100000410000000056213273750405024734 0ustar www-datawww-dataDescription: Creates a new controller class with the given name under the given module namespace Example: rails generate versionist:new_controller test V2_0_0 This will create: app/controllers/V2_0_0/test_controller.rb In addition this will create a test for the new controller using the test_framework currently configured in your Rails app. versionist-1.7.0/lib/generators/versionist/rspec_helper.rb0000644000004100000410000000047213273750405024111 0ustar www-datawww-datamodule Versionist module RspecHelper # Gets the name of the helper file to require in spec files # Accounting for rspec-rails 2 vs rspec-rails 3 def rspec_helper_filename if File.exists? "spec/rails_helper.rb" "rails_helper" else "spec_helper" end end end end versionist-1.7.0/lib/versionist.rb0000644000004100000410000000213013273750405017256 0ustar www-datawww-datarequire 'active_support/dependencies/autoload' module Versionist extend ActiveSupport::Autoload autoload :Configuration autoload :InflectorFixes, "generators/versionist/inflector_fixes" autoload :RspecHelper, "generators/versionist/rspec_helper" autoload :CopyApiVersionGenerator, "generators/versionist/copy_api_version/copy_api_version_generator" autoload :NewApiVersionGenerator, "generators/versionist/new_api_version/new_api_version_generator" autoload :NewControllerGenerator, "generators/versionist/new_controller/new_controller_generator" autoload :NewPresenterGenerator, "generators/versionist/new_presenter/new_presenter_generator" autoload :VersioningStrategy, "versionist/versioning_strategy" autoload :Middleware autoload :Routing def self.configuration @@configuration ||= Configuration.new end def self.older_than_rails_5? defined?(Rails) && Rails.version.to_i < 5 end def self.test_path return "test/functional" if older_than_rails_5? "test/controllers" end end require 'versionist/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3 versionist-1.7.0/lib/versionist/0000755000004100000410000000000013273750405016735 5ustar www-datawww-dataversionist-1.7.0/lib/versionist/version.rb0000644000004100000410000000005213273750405020744 0ustar www-datawww-datamodule Versionist VERSION = '1.7.0' end versionist-1.7.0/lib/versionist/railtie.rb0000644000004100000410000000107213273750405020713 0ustar www-datawww-datarequire 'rails/railtie' module Versionist class Railtie < Rails::Railtie config.versionist = ActiveSupport::OrderedOptions.new initializer 'versionist.configure' do |app| ActionDispatch::Routing::Mapper.send :include, Versionist::Routing end config.app_middleware.use Versionist::Middleware config.after_initialize do generators = config.respond_to?(:app_generators) ? config.app_generators : config.generators Versionist.configuration.configured_test_framework = generators.options[:rails][:test_framework] end end end versionist-1.7.0/lib/versionist/routing.rb0000644000004100000410000000767513273750405020770 0ustar www-datawww-datarequire 'active_support/core_ext/hash/keys' module Versionist module Routing # Allows you to constrain routes to specific versions of your api using versioning strategies. # Supported formats: # # HTTP Header # api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}}) # # Path # api_version(:module => "V1", :path => {:value => "v1"}}) # # Request Parameter # api_version(:module => "V1", :parameter => {:name => "version", :value => "1"}}) # # Specifying default version: # api_version(:module => "V1", :default => true, :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}}) # # Multiple Strategies per version # api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}, :path => {:value => "v1"}) def api_version(config, &block) raise ArgumentError, "you must pass a configuration Hash to api_version" if config.nil? || !config.is_a?(Hash) config.symbolize_keys! raise ArgumentError, "you must specify :header, :path, or :parameter in configuration Hash passed to api_version" if !config.has_key?(:header) && !config.has_key?(:path) && !config.has_key?(:parameter) [:header, :path, :parameter].each do |s| raise ArgumentError, "#{s} key in configuration Hash passed to api_version must point to a Hash" if config.has_key?(s) && !config[s].is_a?(Hash) end raise ArgumentError, "you must specify :module in configuration Hash passed to api_version" if !config.has_key?(:module) raise ArgumentError, ":defaults must be a Hash" if config.has_key?(:defaults) && !config[:defaults].is_a?(Hash) rails_quirks(config, &block) configure_header(config, &block) if config.has_key?(:header) configure_path(config, &block) if config.has_key?(:path) configure_parameter(config, &block) if config.has_key?(:parameter) configure_default(config, &block) if config.has_key?(:default) && config[:default] end private def configure_header(config, &block) header = Versionist::VersioningStrategy::Header.new(config) route_hash = {:module => config[:module], :constraints => header} route_hash.merge!({:defaults => config[:defaults]}) if config.has_key?(:defaults) scope(route_hash, &block) end def configure_path(config, &block) config[:path][:value].slice!(0) if config[:path][:value] =~ /^\// path = Versionist::VersioningStrategy::Path.new(config) # Use the :as option and strip out non-word characters from the path to avoid this: # https://github.com/rails/rails/issues/3224 route_hash = {:module => config[:module], :as => config[:path][:value].gsub(/\W/, '_')} route_hash.merge!({:defaults => config[:defaults]}) if config.has_key?(:defaults) namespace(config[:path][:value], route_hash, &block) end def configure_parameter(config, &block) parameter = Versionist::VersioningStrategy::Parameter.new(config) route_hash = {:module => config[:module], :constraints => parameter} route_hash.merge!({:defaults => config[:defaults]}) if config.has_key?(:defaults) scope(route_hash, &block) end def configure_default(config, &block) default = Versionist::VersioningStrategy::Default.new(config) route_hash = {:module => config[:module], :constraints => default, :as => 'default'} route_hash.merge!({:defaults => config[:defaults]}) if config.has_key?(:defaults) scope(route_hash, &block) end # deals with quirks in routing among the various Rails versions def rails_quirks(config, &block) # Rails 4 no longer allows constant syntax in routing. # https://github.com/bploetz/versionist/issues/39 # call underscore on the module so it adheres to this convention config[:module] = config[:module].underscore if Rails::VERSION::MAJOR >= 4 end end end versionist-1.7.0/lib/versionist/configuration.rb0000644000004100000410000000117413273750405022134 0ustar www-datawww-datamodule Versionist class Configuration attr_accessor :versioning_strategies attr_accessor :default_version attr_accessor :header_versions attr_accessor :parameter_versions attr_accessor :path_versions attr_accessor :configured_test_framework def initialize @versioning_strategies ||= Array.new @header_versions ||= Array.new @parameter_versions ||= Array.new @path_versions ||= Array.new end def clear! @versioning_strategies.clear @default_version = nil @header_versions.clear @parameter_versions.clear @path_versions.clear end end end versionist-1.7.0/lib/versionist/versioning_strategy/0000755000004100000410000000000013273750405023042 5ustar www-datawww-dataversionist-1.7.0/lib/versionist/versioning_strategy/default.rb0000644000004100000410000000223413273750405025014 0ustar www-datawww-datamodule Versionist module VersioningStrategy # Implements the default version handling strategy. class Default < Base attr_accessor :strategies attr_accessor :module def initialize(config) super @module = config[:module] raise ArgumentError, "[VERSIONIST] attempt to set more than one default api version" if !Versionist.configuration.default_version.nil? && Versionist.configuration.default_version != self Versionist.configuration.default_version = self end def matches?(request) !header_matches?(request) && !parameter_matches?(request) end def ==(other) super return false if !other.is_a?(Versionist::VersioningStrategy::Default) return self.module == other.module end private def header_matches?(request) Versionist.configuration.header_versions && Versionist.configuration.header_versions.any? {|v| v.matches?(request)} end def parameter_matches?(request) Versionist.configuration.parameter_versions && Versionist.configuration.parameter_versions.any? {|v| v.matches?(request)} end end end end versionist-1.7.0/lib/versionist/versioning_strategy/header.rb0000644000004100000410000000343613273750405024625 0ustar www-datawww-datamodule Versionist module VersioningStrategy # Implements the header versioning strategy. class Header < Base # Creates a new Header VersioningStrategy object. config must contain the following keys: # - :header the header hash to inspect def initialize(config) super raise ArgumentError, "you must specify :name in the :header configuration Hash" if !config[:header].has_key?(:name) raise ArgumentError, "you must specify :value in the :header configuration Hash" if !config[:header].has_key?(:value) Versionist.configuration.header_versions << self if !Versionist.configuration.header_versions.include?(self) end def matches?(request) header_string = request.headers[config[:header][:name]].to_s if !header_string.blank? potential_matches = Versionist.configuration.header_versions.select {|hv| header_string.include?(hv.config[:header][:value])} if !potential_matches.empty? if potential_matches.include?(self) if potential_matches.size == 1 return true else # when finding multiple potential matches, the match with the longest value wins # (i.e. v2.1 trumps v2), as one is a subset of the other longest = potential_matches.max {|a,b| a.config[:header][:value].length <=> b.config[:header][:value].length} return longest == self end end end end false end def ==(other) super return false if !other.is_a?(Versionist::VersioningStrategy::Header) return config[:header][:name] == other.config[:header][:name] && self.config[:header][:value] == other.config[:header][:value] end end end end versionist-1.7.0/lib/versionist/versioning_strategy/base.rb0000644000004100000410000000120613273750405024300 0ustar www-datawww-datarequire 'active_support/core_ext/hash/keys' module Versionist module VersioningStrategy class Base attr_reader :config def initialize(config={}) raise ArgumentError, "you must pass a configuration Hash" if config.nil? || !config.is_a?(Hash) @config = config @config.symbolize_keys! Versionist.configuration.versioning_strategies << self if !Versionist.configuration.versioning_strategies.include?(self) end def ==(other) return false if other.nil? || !other.is_a?(Versionist::VersioningStrategy::Base) return self.config == other.config end end end end versionist-1.7.0/lib/versionist/versioning_strategy/parameter.rb0000644000004100000410000000226713273750405025356 0ustar www-datawww-datamodule Versionist module VersioningStrategy # Implements the parameter versioning strategy. class Parameter < Base # Creates a new Parameter VersioningStrategy object. config must contain the following keys: # - :parameter the parameter hash to inspect def initialize(config) super raise ArgumentError, "you must specify :name in the :parameter configuration Hash" if !config[:parameter].has_key?(:name) raise ArgumentError, "you must specify :value in the :parameter configuration Hash" if !config[:parameter].has_key?(:value) Versionist.configuration.parameter_versions << self if !Versionist.configuration.parameter_versions.include?(self) end def matches?(request) parameter_string = request.params[config[:parameter][:name]].to_s return !parameter_string.blank? && parameter_string == config[:parameter][:value] end def ==(other) super return false if !other.is_a?(Versionist::VersioningStrategy::Parameter) return config[:parameter][:name] == other.config[:parameter][:name] && self.config[:parameter][:value] == other.config[:parameter][:value] end end end end versionist-1.7.0/lib/versionist/versioning_strategy/path.rb0000644000004100000410000000146613273750405024332 0ustar www-datawww-datamodule Versionist module VersioningStrategy # Implements the path versioning strategy. It expects the following path format: # GET //... class Path < Base # Creates a new Path VersioningStrategy object. config must contain the following keys: # - :path the path prefix containing the version def initialize(config) super raise ArgumentError, "you must specify :value in the :path configuration Hash" if !config[:path].has_key?(:value) Versionist.configuration.path_versions << self if !Versionist.configuration.path_versions.include?(self) end def ==(other) super return false if !other.is_a?(Versionist::VersioningStrategy::Path) return config[:path][:value] == other.config[:path][:value] end end end end versionist-1.7.0/lib/versionist/versioning_strategy.rb0000644000004100000410000000062213273750405023367 0ustar www-datawww-datamodule Versionist module VersioningStrategy extend ActiveSupport::Autoload autoload :Base, 'versionist/versioning_strategy/base' autoload :Header, 'versionist/versioning_strategy/header' autoload :Path, 'versionist/versioning_strategy/path' autoload :Parameter, 'versionist/versioning_strategy/parameter' autoload :Default, 'versionist/versioning_strategy/default' end end versionist-1.7.0/lib/versionist/middleware.rb0000644000004100000410000000312513273750405021400 0ustar www-datawww-datamodule Versionist # When your routes don't include an explicit format in the URL (i.e. `match 'foos.(:format)' => foos#index`), # Rails inspects the `Accept` header to determine the requested format. Since an `Accept` header can have multiple values, # Rails uses the first one present to determine the format. If your custom version header happens to be the first value # in the `Accept` header, it would incorrectly be interpretted as the format. This middleware moves your custom version header # (if found) to the end of the `Accept` header so as to not interfere with this format logic in Rails. class Middleware ACCEPT = "Accept" HTTP_ACCEPT = "HTTP_ACCEPT" def initialize(app) @app = app end def call(env) dup._call(env) end def _call(env) request = ::Rack::Request.new(env) potential_matches = Versionist.configuration.header_versions.select {|hv| hv.config[:header][:name] == ACCEPT && env[HTTP_ACCEPT].try(:include?, hv.config[:header][:value])} if !potential_matches.empty? strategy = potential_matches.max {|a,b| a.config[:header][:value].length <=> b.config[:header][:value].length} end if !strategy.nil? entries = env[HTTP_ACCEPT].split(',') index = -1 entries.each_with_index do |e, i| e.strip! index = i if e == strategy.config[:header][:value] end if (index != -1) version = entries.delete_at(index) entries << version end env[HTTP_ACCEPT] = entries.join(", ") end @app.call(env) end end end versionist-1.7.0/versionist.gemspec0000644000004100000410000001062113273750405017534 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: versionist 1.7.0 ruby lib Gem::Specification.new do |s| s.name = "versionist".freeze s.version = "1.7.0" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Brian Ploetz".freeze] s.date = "2017-12-21" s.description = "A plugin for versioning Rails based RESTful APIs.".freeze s.files = ["lib/generators/versionist/copy_api_version/USAGE".freeze, "lib/generators/versionist/copy_api_version/copy_api_version_generator.rb".freeze, "lib/generators/versionist/inflector_fixes.rb".freeze, "lib/generators/versionist/new_api_version/USAGE".freeze, "lib/generators/versionist/new_api_version/new_api_version_generator.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_functional_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_functional_test_rails_5.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_integration_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_controller_spec.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_spec.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_test.rb".freeze, "lib/generators/versionist/new_api_version/templates/base_presenter_test_rails_5.rb".freeze, "lib/generators/versionist/new_api_version/templates/docs_index.rb".freeze, "lib/generators/versionist/new_api_version/templates/docs_style.rb".freeze, "lib/generators/versionist/new_controller/USAGE".freeze, "lib/generators/versionist/new_controller/new_controller_generator.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_functional_test.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_functional_test_rails_5.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_integration_test.rb".freeze, "lib/generators/versionist/new_controller/templates/new_controller_spec.rb".freeze, "lib/generators/versionist/new_presenter/USAGE".freeze, "lib/generators/versionist/new_presenter/new_presenter_generator.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_spec.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_test.rb".freeze, "lib/generators/versionist/new_presenter/templates/new_presenter_test_rails_5.rb".freeze, "lib/generators/versionist/rspec_helper.rb".freeze, "lib/versionist.rb".freeze, "lib/versionist/configuration.rb".freeze, "lib/versionist/middleware.rb".freeze, "lib/versionist/railtie.rb".freeze, "lib/versionist/routing.rb".freeze, "lib/versionist/version.rb".freeze, "lib/versionist/versioning_strategy.rb".freeze, "lib/versionist/versioning_strategy/base.rb".freeze, "lib/versionist/versioning_strategy/default.rb".freeze, "lib/versionist/versioning_strategy/header.rb".freeze, "lib/versionist/versioning_strategy/parameter.rb".freeze, "lib/versionist/versioning_strategy/path.rb".freeze] s.homepage = "https://github.com/bploetz/versionist".freeze s.licenses = ["MIT".freeze] s.rdoc_options = ["--charset=UTF-8".freeze] s.rubygems_version = "2.5.2.1".freeze s.summary = "versionist-1.7.0".freeze if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, [">= 3"]) s.add_runtime_dependency(%q.freeze, [">= 3"]) s.add_runtime_dependency(%q.freeze, ["~> 0.9.11"]) else s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, ["~> 0.9.11"]) end else s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, [">= 3"]) s.add_dependency(%q.freeze, ["~> 0.9.11"]) end end