otr-activerecord-1.4.1/0000755000175000017500000000000013616267747014740 5ustar utkarshutkarshotr-activerecord-1.4.1/README.md0000644000175000017500000000522713616267747016225 0ustar utkarshutkarsh# otr-activerecord An easy way to use ActiveRecord "off the rails." Works with Grape, Sinatra, plain old Rack, or even in a boring little script!. The defaults are all very Railsy (`config/database.yml`, `db/seeds.rb`, `db/migrate`, etc.), but you can easily change them. (Formerly known as `grape-activerecord`.) Supports: * ActiveRecord 4 * ActiveRecord 5 * ActiveRecord 6 ## How to use #### 1. Add it to your Gemfile gem "otr-activerecord" #### 2. Configure your database connection After loading your gems, tell `OTR::ActiveRecord` about your database config using one of the following examples: OTR::ActiveRecord.configure_from_file! "config/database.yml" OTR::ActiveRecord.configure_from_url! ENV['DATABASE_URL'] # e.g. postgres://user:pass@host/db OTR::ActiveRecord.configure_from_hash!(adapter: "postgresql", host: "localhost", database: "db", username: "user", password: "pass", encoding: "utf8", pool: 10, timeout: 5000) **Important note**: `configure_from_file!` won't work as expected if you have already `DATABASE_URL` set as part of your environment variables. This is because in ActiveRecord when that env variable is set it will merge its properties into the current connection configuration. #### 3. Enable middleware for Rack apps Add these middlewares in `config.ru`: # Clean up database connections after every request (required) use OTR::ActiveRecord::ConnectionManagement # Enable ActiveRecord's QueryCache for every request (optional) use OTR::ActiveRecord::QueryCache #### 4. Import ActiveRecord tasks into your Rakefile This will give you most of the standard `db:` tasks you get in Rails. Add it to your `Rakefile`. require "bundler/setup" load "tasks/otr-activerecord.rake" namespace :db do # Some db tasks require your app code to be loaded; they'll expect to find it here task :environment do require_relative "app" end end Unlike in Rails, creating a new migration is also a rake task. Run `bundle exec rake -T` to get a full list of tasks. bundle exec rake db:create_migration[create_widgets] ## Examples Look under [/examples](https://github.com/jhollinger/otr-activerecord/tree/master/examples) for some example apps. ## Advanced options The defaults for db-related files like migrations, seeds, and fixtures are the same as Rails. If you want to override them, use the following options in your `Rakefile`: OTR::ActiveRecord.db_dir = 'db' OTR::ActiveRecord.migrations_paths = ['db/migrate'] OTR::ActiveRecord.fixtures_path = 'test/fixtures' OTR::ActiveRecord.seed_file = 'seeds.rb' ## License Licensed under the MIT License Copyright 2016 Jordan Hollinger otr-activerecord-1.4.1/otr-activerecord.gemspec0000644000175000017500000000425713616267747021571 0ustar utkarshutkarsh######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: otr-activerecord 1.4.1 ruby lib Gem::Specification.new do |s| s.name = "otr-activerecord".freeze s.version = "1.4.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Jordan Hollinger".freeze] s.date = "2019-06-18" s.description = "Off The Rails ActiveRecord: Use ActiveRecord with Grape, Sinatra, Rack, or anything else! Formerly known as 'grape-activerecord'.".freeze s.email = "jordan.hollinger@gmail.com".freeze s.files = ["LICENSE".freeze, "README.md".freeze, "lib/otr-activerecord.rb".freeze, "lib/otr-activerecord/activerecord.rb".freeze, "lib/otr-activerecord/compatibility_4.rb".freeze, "lib/otr-activerecord/compatibility_5.rb".freeze, "lib/otr-activerecord/compatibility_6.rb".freeze, "lib/otr-activerecord/defaults.rb".freeze, "lib/otr-activerecord/middleware/connection_management.rb".freeze, "lib/otr-activerecord/middleware/query_cache.rb".freeze, "lib/otr-activerecord/version.rb".freeze, "lib/tasks/otr-activerecord.rake".freeze] s.homepage = "https://github.com/jhollinger/otr-activerecord".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.1.0".freeze) s.rubygems_version = "2.7.6.2".freeze s.summary = "Off The Rails: Use ActiveRecord with Grape, Sinatra, Rack, or anything else!".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, ["< 6.1", ">= 4.0"]) s.add_runtime_dependency(%q.freeze, ["~> 0.1"]) else s.add_dependency(%q.freeze, ["< 6.1", ">= 4.0"]) s.add_dependency(%q.freeze, ["~> 0.1"]) end else s.add_dependency(%q.freeze, ["< 6.1", ">= 4.0"]) s.add_dependency(%q.freeze, ["~> 0.1"]) end end otr-activerecord-1.4.1/LICENSE0000644000175000017500000000204413616267747015745 0ustar utkarshutkarshCopyright (c) 2016 Jordan Hollinger Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. otr-activerecord-1.4.1/lib/0000755000175000017500000000000013616267747015506 5ustar utkarshutkarshotr-activerecord-1.4.1/lib/tasks/0000755000175000017500000000000013616267747016633 5ustar utkarshutkarshotr-activerecord-1.4.1/lib/tasks/otr-activerecord.rake0000644000175000017500000000503113616267747022752 0ustar utkarshutkarshrequire 'pathname' require 'fileutils' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/inflections' require 'otr-activerecord' load 'active_record/railties/databases.rake' # # Configure and override the default activerecord db rake tasks # Rake::Task.define_task('db:_load_config') do ::ActiveRecord::Base.logger = nil ::ActiveRecord::Tasks::DatabaseTasks.tap do |config| config.root = Rake.application.original_dir config.env = OTR::ActiveRecord.rack_env.to_s config.db_dir = OTR::ActiveRecord.db_dir config.migrations_paths = Array(OTR::ActiveRecord.migrations_paths) config.fixtures_path = OTR::ActiveRecord.fixtures_path config.database_configuration = ::ActiveRecord::Base.configurations config.seed_loader = Object.new config.seed_loader.instance_eval do def load_seed load "#{OTR::ActiveRecord.db_dir}/#{OTR::ActiveRecord.seed_file}" end end end end Rake::Task['db:load_config'].clear Rake::Task.define_task('db:load_config') do # Run the user's db:environment task first, so they have an opportunity to set a custom db config location Rake::Task['db:environment'].invoke end Rake::Task.define_task('db:environment') do # defined by user end # Load db config at the end of user-defined db:environment Rake::Task['db:environment'].enhance do Rake::Task['db:_load_config'].invoke end Rake::Task['db:test:deprecated'].clear if Rake::Task.task_defined?('db:test:deprecated') # # Define otr-activerecord helper tasks # namespace :db do namespace :test do task :environment do ENV['RACK_ENV'] = 'test' end end if OTR::ActiveRecord._normalizer.force_db_test_env? desc "Create a migration" task :create_migration, [:name] do |_, args| name, version = args[:name], Time.now.utc.strftime("%Y%m%d%H%M%S") OTR::ActiveRecord._normalizer.migrations_paths.each do |directory| next unless File.exists?(directory) migration_files = Pathname(directory).children if duplicate = migration_files.find { |path| path.basename.to_s.include?(name) } abort "Another migration is already named \"#{name}\": #{duplicate}." end end filename = "#{version}_#{name}.rb" dirname = OTR::ActiveRecord._normalizer.migrations_path path = File.join(dirname, filename) FileUtils.mkdir_p(dirname) File.write path, <<-MIGRATION.strip_heredoc class #{name.camelize} < #{OTR::ActiveRecord._normalizer.migration_base_class_name} def change end end MIGRATION puts path end end otr-activerecord-1.4.1/lib/otr-activerecord.rb0000644000175000017500000000043313616267747021307 0ustar utkarshutkarshrequire 'active_record' require 'hashie-forbidden_attributes' require 'otr-activerecord/version' require 'otr-activerecord/activerecord' require 'otr-activerecord/middleware/connection_management' require 'otr-activerecord/middleware/query_cache' require 'otr-activerecord/defaults' otr-activerecord-1.4.1/lib/otr-activerecord/0000755000175000017500000000000013616267747020762 5ustar utkarshutkarshotr-activerecord-1.4.1/lib/otr-activerecord/version.rb0000644000175000017500000000012313616267747022770 0ustar utkarshutkarshmodule OTR module ActiveRecord # Gem version VERSION = '1.4.1' end end otr-activerecord-1.4.1/lib/otr-activerecord/compatibility_6.rb0000644000175000017500000000165013616267747024407 0ustar utkarshutkarshmodule OTR module ActiveRecord # Compatibility layer for ActiveRecord 6 class Compatibility6 attr_reader :major_version # Compatibility layer for ActiveRecord 6 def initialize @major_version = 6 ::ActiveRecord::Base.default_timezone = :utc ::ActiveRecord::Base.logger = Logger.new(STDOUT) end # All db migration dir paths def migrations_paths OTR::ActiveRecord.migrations_paths end # The dir in which to put new migrations def migrations_path OTR::ActiveRecord.migrations_paths[0] end # Basename of migration classes def migration_base_class_name version = "6.#{::ActiveRecord::VERSION::MINOR}" "ActiveRecord::Migration[#{version}]" end # Force RACK_ENV/RAILS_ENV to be 'test' when running any db:test:* tasks def force_db_test_env? false end end end end otr-activerecord-1.4.1/lib/otr-activerecord/activerecord.rb0000644000175000017500000000431013616267747023757 0ustar utkarshutkarshrequire 'erb' # "Off the Rails" ActiveRecord configuration/integration for Grape, Sinatra, Rack, and any other kind of app module OTR # ActiveRecord configuration module module ActiveRecord autoload :Compatibility4, 'otr-activerecord/compatibility_4' autoload :Compatibility5, 'otr-activerecord/compatibility_5' autoload :Compatibility6, 'otr-activerecord/compatibility_6' class << self # Relative path to the "db" dir attr_accessor :db_dir # Relative path(s) to the migrations directory attr_accessor :migrations_paths # Relative path to the fixtures directory attr_accessor :fixtures_path # Name of the seeds file in db_dir attr_accessor :seed_file # Internal compatibility layer across different major versions of AR attr_accessor :_normalizer end # Connect to database with a Hash. Example: # {adapter: 'postgresql', host: 'localhost', database: 'db', username: 'user', password: 'pass', encoding: 'utf8', pool: 10, timeout: 5000} def self.configure_from_hash!(spec) config = spec.stringify_keys.merge("migrations_paths" => ::OTR::ActiveRecord.migrations_paths) ::ActiveRecord::Base.configurations = {rack_env.to_s => config} ::ActiveRecord::Base.establish_connection(rack_env) end # Connect to database with a DB URL. Example: "postgres://user:pass@localhost/db" def self.configure_from_url!(url) configure_from_hash! ::ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(url).to_hash end # Connect to database with a yml file. Example: "config/database.yml" def self.configure_from_file!(path) raise "#{path} does not exist!" unless File.file? path ::ActiveRecord::Base.configurations = (YAML.load(ERB.new(File.read(path)).result) || {}). reduce({}) { |a, (env, config)| a[env] = {"migrations_paths" => ::OTR::ActiveRecord.migrations_paths}.merge config a } ::ActiveRecord::Base.establish_connection(rack_env) end # The current Rack environment def self.rack_env (ENV['RACK_ENV'] || ENV['RAILS_ENV'] || ENV['APP_ENV'] || ENV['OTR_ENV'] || 'development').to_sym end end end otr-activerecord-1.4.1/lib/otr-activerecord/defaults.rb0000644000175000017500000000110313616267747023111 0ustar utkarshutkarshENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] ||= "true" OTR::ActiveRecord.db_dir = 'db' OTR::ActiveRecord.migrations_paths = %w(db/migrate) OTR::ActiveRecord.fixtures_path = 'test/fixtures' OTR::ActiveRecord.seed_file = 'seeds.rb' OTR::ActiveRecord._normalizer = case ::ActiveRecord::VERSION::MAJOR when 4 then OTR::ActiveRecord::Compatibility4.new when 5 then OTR::ActiveRecord::Compatibility5.new when 6 then OTR::ActiveRecord::Compatibility6.new end otr-activerecord-1.4.1/lib/otr-activerecord/compatibility_5.rb0000644000175000017500000000165013616267747024406 0ustar utkarshutkarshmodule OTR module ActiveRecord # Compatibility layer for ActiveRecord 5 class Compatibility5 attr_reader :major_version # Compatibility layer for ActiveRecord 5 def initialize @major_version = 5 ::ActiveRecord::Base.default_timezone = :utc ::ActiveRecord::Base.logger = Logger.new(STDOUT) end # All db migration dir paths def migrations_paths OTR::ActiveRecord.migrations_paths end # The dir in which to put new migrations def migrations_path OTR::ActiveRecord.migrations_paths[0] end # Basename of migration classes def migration_base_class_name version = "5.#{::ActiveRecord::VERSION::MINOR}" "ActiveRecord::Migration[#{version}]" end # Force RACK_ENV/RAILS_ENV to be 'test' when running any db:test:* tasks def force_db_test_env? false end end end end otr-activerecord-1.4.1/lib/otr-activerecord/compatibility_4.rb0000644000175000017500000000154313616267747024406 0ustar utkarshutkarshmodule OTR module ActiveRecord # Compatibility layer for ActiveRecord 4 class Compatibility4 attr_reader :major_version # Compatibility layer for ActiveRecord 4 def initialize @major_version = 4 ::ActiveRecord::Base.default_timezone = :utc ::ActiveRecord::Base.logger = Logger.new(STDOUT) end # All db migration dir paths def migrations_paths OTR::ActiveRecord.migrations_paths end # The dir in which to put new migrations def migrations_path OTR::ActiveRecord.migrations_paths[0] end # Basename of migration classes def migration_base_class_name 'ActiveRecord::Migration' end # Force RACK_ENV/RAILS_ENV to be 'test' when running any db:test:* tasks def force_db_test_env? true end end end end otr-activerecord-1.4.1/lib/otr-activerecord/middleware/0000755000175000017500000000000013616267747023077 5ustar utkarshutkarshotr-activerecord-1.4.1/lib/otr-activerecord/middleware/query_cache.rb0000644000175000017500000000141313616267747025713 0ustar utkarshutkarshmodule OTR module ActiveRecord # # Rack middleware to enable ActiveRecord's query cache for each request. # class QueryCache def initialize(app) @handler = case ::ActiveRecord::VERSION::MAJOR when 4 then ::ActiveRecord::QueryCache.new(app) when 5, 6 then ActionDispatchHandler.new(app) end end def call(env) @handler.call(env) end class ActionDispatchHandler def initialize(app) @app = app end def call(env) state = nil state = ::ActiveRecord::QueryCache.run @app.call(env) ensure ::ActiveRecord::QueryCache.complete(state) if state end end end end end otr-activerecord-1.4.1/lib/otr-activerecord/middleware/connection_management.rb0000644000175000017500000000115013616267747027754 0ustar utkarshutkarshmodule OTR module ActiveRecord # # Rack middleware that returns active db connections to the connection pool after a request completes. # class ConnectionManagement def initialize(app) @app = app end def call(env) testing = env['rack.test'] == true resp = @app.call env resp[2] = ::Rack::BodyProxy.new resp[2] do ::ActiveRecord::Base.clear_active_connections! unless testing end resp rescue Exception ::ActiveRecord::Base.clear_active_connections! unless testing raise end end end end