versionist-1.6.0/0000755000004100000410000000000013147533336013763 5ustar www-datawww-dataversionist-1.6.0/lib/0000755000004100000410000000000013147533336014531 5ustar www-datawww-dataversionist-1.6.0/lib/versionist/0000755000004100000410000000000013147533336016736 5ustar www-datawww-dataversionist-1.6.0/lib/versionist/configuration.rb0000644000004100000410000000117413147533336022135 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.6.0/lib/versionist/versioning_strategy.rb0000644000004100000410000000062213147533336023370 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.6.0/lib/versionist/version.rb0000644000004100000410000000005213147533336020745 0ustar www-datawww-datamodule Versionist VERSION = '1.6.0' end versionist-1.6.0/lib/versionist/middleware.rb0000644000004100000410000000312513147533336021401 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.6.0/lib/versionist/routing.rb0000644000004100000410000000767513147533336020771 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.6.0/lib/versionist/versioning_strategy/0000755000004100000410000000000013147533336023043 5ustar www-datawww-dataversionist-1.6.0/lib/versionist/versioning_strategy/default.rb0000644000004100000410000000223413147533336025015 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.6.0/lib/versionist/versioning_strategy/path.rb0000644000004100000410000000146613147533336024333 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.6.0/lib/versionist/versioning_strategy/header.rb0000644000004100000410000000343613147533336024626 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.6.0/lib/versionist/versioning_strategy/parameter.rb0000644000004100000410000000226713147533336025357 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.6.0/lib/versionist/versioning_strategy/base.rb0000644000004100000410000000120613147533336024301 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.6.0/lib/versionist/railtie.rb0000644000004100000410000000107213147533336020714 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.6.0/lib/versionist.rb0000644000004100000410000000213013147533336017257 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.6.0/lib/generators/0000755000004100000410000000000013147533336016702 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/0000755000004100000410000000000013147533336021107 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/rspec_helper.rb0000644000004100000410000000047213147533336024112 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.6.0/lib/generators/versionist/new_api_version/0000755000004100000410000000000013147533336024276 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/new_api_version/templates/0000755000004100000410000000000013147533336026274 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_presenter_test.rb0000644000004100000410000000026113147533336032660 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.6.0/lib/generators/versionist/new_api_version/templates/base_presenter_spec.rb0000644000004100000410000000013113147533336032627 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::BasePresenter do end versionist-1.6.0/lib/generators/versionist/new_api_version/templates/docs_style.rb0000644000004100000410000000037713147533336031000 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;} ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_integration_test.rbversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_integration_tes0000644000004100000410000000027513147533336034656 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 ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test_rails_5.rbversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test0000644000004100000410000000027513147533336034661 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 ././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test.rbversionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_functional_test0000644000004100000410000000027013147533336034654 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.6.0/lib/generators/versionist/new_api_version/templates/base_presenter_test_rails_5.rb0000644000004100000410000000026413147533336034301 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 versionist-1.6.0/lib/generators/versionist/new_api_version/templates/docs_index.rb0000644000004100000410000000064313147533336030743 0ustar www-datawww-data Documentation for <%= version%>

API Operations

Documentation for <%= version%>

versionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller.rb0000644000004100000410000000010513147533336031772 0ustar www-datawww-dataclass <%= module_name %>::BaseController < ApplicationController end versionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_controller_spec.rb0000644000004100000410000000013213147533336033004 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::BaseController do end versionist-1.6.0/lib/generators/versionist/new_api_version/templates/base_presenter.rb0000644000004100000410000000005413147533336031621 0ustar www-datawww-dataclass <%= module_name %>::BasePresenter end versionist-1.6.0/lib/generators/versionist/new_api_version/USAGE0000644000004100000410000000145013147533336025065 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.6.0/lib/generators/versionist/new_api_version/new_api_version_generator.rb0000644000004100000410000001515213147533336032064 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/#{test_path}/#{module_name_for_path(module_name)}" empty_directory "test/integration/#{module_name_for_path(module_name)}" if 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", "#{test_path}", "#{module_name_for_path(module_name)}", "base_controller_test.rb") else template 'base_controller_functional_test_rails_5.rb', File.join("test", "#{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 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.6.0/lib/generators/versionist/new_controller/0000755000004100000410000000000013147533336024143 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/new_controller/templates/0000755000004100000410000000000013147533336026141 5ustar www-datawww-data././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test.rbversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test.r0000644000004100000410000000030513147533336034637 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.6.0/lib/generators/versionist/new_controller/templates/new_controller.rb0000644000004100000410000000013613147533336031522 0ustar www-datawww-dataclass <%= module_name %>::<%= class_name%>Controller < <%= module_name %>::BaseController end versionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_spec.rb0000644000004100000410000000014613147533336032535 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::<%= class_name%>Controller do end ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_integration_test.rbversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_integration_test.0000644000004100000410000000031213147533336034634 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 ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test_rails_5.rbversionist-1.6.0/lib/generators/versionist/new_controller/templates/new_controller_functional_test_r0000644000004100000410000000031213147533336034716 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.6.0/lib/generators/versionist/new_controller/USAGE0000644000004100000410000000056213147533336024735 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.6.0/lib/generators/versionist/new_controller/new_controller_generator.rb0000644000004100000410000000550313147533336031575 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 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", "#{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", "#{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.6.0/lib/generators/versionist/new_presenter/0000755000004100000410000000000013147533336023767 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/new_presenter/new_presenter_generator.rb0000644000004100000410000000316713147533336031251 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 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.6.0/lib/generators/versionist/new_presenter/templates/0000755000004100000410000000000013147533336025765 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/new_presenter/templates/new_presenter_test.rb0000644000004100000410000000027513147533336032235 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.6.0/lib/generators/versionist/new_presenter/templates/new_presenter.rb0000644000004100000410000000052713147533336031176 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.6.0/lib/generators/versionist/new_presenter/templates/new_presenter_spec.rb0000644000004100000410000000014513147533336032204 0ustar www-datawww-datarequire '<%= @rspec_require_file %>' describe <%= module_name %>::<%= class_name%>Presenter do end versionist-1.6.0/lib/generators/versionist/new_presenter/templates/new_presenter_test_rails_5.rb0000644000004100000410000000030013147533336033640 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.6.0/lib/generators/versionist/new_presenter/USAGE0000644000004100000410000000054313147533336024560 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.6.0/lib/generators/versionist/inflector_fixes.rb0000644000004100000410000000056513147533336024625 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.6.0/lib/generators/versionist/copy_api_version/0000755000004100000410000000000013147533336024457 5ustar www-datawww-dataversionist-1.6.0/lib/generators/versionist/copy_api_version/USAGE0000644000004100000410000000170213147533336025246 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.6.0/lib/generators/versionist/copy_api_version/copy_api_version_generator.rb0000644000004100000410000002543513147533336032433 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? "#{test_path}/#{module_name_for_path(old_module_name)}" log "Copying all files from #{test_path}/#{module_name_for_path(old_module_name)} to #{test_path}/#{module_name_for_path(new_module_name)}" FileUtils.cp_r "#{test_path}/#{module_name_for_path(old_module_name)}", "#{test_path}/#{module_name_for_path(new_module_name)}" Dir.glob("#{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 #{test_path} for #{old_version}" end if 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.6.0/versionist.gemspec0000644000004100000410000000767213147533336017551 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "versionist" s.version = "1.6.0" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version= s.authors = ["Brian Ploetz"] s.date = "2017-08-10" s.description = "A plugin for versioning Rails based RESTful APIs." s.files = ["lib/generators/versionist/copy_api_version/USAGE", "lib/generators/versionist/copy_api_version/copy_api_version_generator.rb", "lib/generators/versionist/inflector_fixes.rb", "lib/generators/versionist/new_api_version/USAGE", "lib/generators/versionist/new_api_version/new_api_version_generator.rb", "lib/generators/versionist/new_api_version/templates/base_controller.rb", "lib/generators/versionist/new_api_version/templates/base_controller_functional_test.rb", "lib/generators/versionist/new_api_version/templates/base_controller_functional_test_rails_5.rb", "lib/generators/versionist/new_api_version/templates/base_controller_integration_test.rb", "lib/generators/versionist/new_api_version/templates/base_controller_spec.rb", "lib/generators/versionist/new_api_version/templates/base_presenter.rb", "lib/generators/versionist/new_api_version/templates/base_presenter_spec.rb", "lib/generators/versionist/new_api_version/templates/base_presenter_test.rb", "lib/generators/versionist/new_api_version/templates/base_presenter_test_rails_5.rb", "lib/generators/versionist/new_api_version/templates/docs_index.rb", "lib/generators/versionist/new_api_version/templates/docs_style.rb", "lib/generators/versionist/new_controller/USAGE", "lib/generators/versionist/new_controller/new_controller_generator.rb", "lib/generators/versionist/new_controller/templates/new_controller.rb", "lib/generators/versionist/new_controller/templates/new_controller_functional_test.rb", "lib/generators/versionist/new_controller/templates/new_controller_functional_test_rails_5.rb", "lib/generators/versionist/new_controller/templates/new_controller_integration_test.rb", "lib/generators/versionist/new_controller/templates/new_controller_spec.rb", "lib/generators/versionist/new_presenter/USAGE", "lib/generators/versionist/new_presenter/new_presenter_generator.rb", "lib/generators/versionist/new_presenter/templates/new_presenter.rb", "lib/generators/versionist/new_presenter/templates/new_presenter_spec.rb", "lib/generators/versionist/new_presenter/templates/new_presenter_test.rb", "lib/generators/versionist/new_presenter/templates/new_presenter_test_rails_5.rb", "lib/generators/versionist/rspec_helper.rb", "lib/versionist.rb", "lib/versionist/configuration.rb", "lib/versionist/middleware.rb", "lib/versionist/railtie.rb", "lib/versionist/routing.rb", "lib/versionist/version.rb", "lib/versionist/versioning_strategy.rb", "lib/versionist/versioning_strategy/base.rb", "lib/versionist/versioning_strategy/default.rb", "lib/versionist/versioning_strategy/header.rb", "lib/versionist/versioning_strategy/parameter.rb", "lib/versionist/versioning_strategy/path.rb"] s.homepage = "https://github.com/bploetz/versionist" s.licenses = ["MIT"] s.rdoc_options = ["--charset=UTF-8"] s.require_paths = ["lib"] s.rubygems_version = "1.8.23" s.summary = "versionist-1.6.0" 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, [">= 3"]) s.add_runtime_dependency(%q, [">= 3"]) s.add_runtime_dependency(%q, ["~> 0.7"]) else s.add_dependency(%q, [">= 3"]) s.add_dependency(%q, [">= 3"]) s.add_dependency(%q, ["~> 0.7"]) end else s.add_dependency(%q, [">= 3"]) s.add_dependency(%q, [">= 3"]) s.add_dependency(%q, ["~> 0.7"]) end end