pax_global_header00006660000000000000000000000064147273326040014522gustar00rootroot0000000000000052 comment=d76b23e886c79a7d6b3c2c0f4654c84b391fe418 otr-activerecord-2.5.0/000077500000000000000000000000001472733260400150025ustar00rootroot00000000000000otr-activerecord-2.5.0/.gitignore000066400000000000000000000000671472733260400167750ustar00rootroot00000000000000/*.gem /Gemfile.lock /examples/**/*.sqlite3* .DS_Store otr-activerecord-2.5.0/Appraisals000066400000000000000000000006621472733260400170300ustar00rootroot00000000000000appraise "ar-8.0" do gem "activerecord", "~> 8.0.0" gem "sqlite3", "~> 2.4.1" end appraise "ar-7.2" do gem "activerecord", "~> 7.2.1" gem "sqlite3", "~> 1.7.3" end appraise "ar-7.1" do gem "activerecord", "~> 7.1.1" gem "sqlite3", "~> 1.7.3" end appraise "ar-7.0" do gem "activerecord", "~> 7.0.1" gem "sqlite3", "~> 1.4.2" end appraise "ar-6.1" do gem "activerecord", "~> 6.1.4" gem "sqlite3", "~> 1.4.2" end otr-activerecord-2.5.0/CHANGELOG.md000066400000000000000000000043041472733260400166140ustar00rootroot00000000000000### 2.5.0 (2024-12-13) * Support for ActiveRecord 8.0 ### 2.4.0 (2024-08-30) * Support for ActiveRecord 7.2 ### 2.3.0 (2024-07-25) * Support for multi-db config in `OTR::ActiveRecord.configure_from_hash!` * Removal of support for ActiveRecord 4.x-6.0 ### 2.2.0 (2023-10-19) * Support for ActiveRecord 7.1 ### 2.1.2 (2023-01-25) * Use File.exist? instead of File.exists? ### 2.1.1 (2022-01-30) * Fix `OTR::ActiveRecord::QueryCache` for ActiveRecord 7. ### 2.1.0 (2022-01-30) * Don't set logger - allows apps to do that - [PR #28](https://github.com/jhollinger/otr-activerecord/pull/28) - [anakinj](https://github.com/anakinj) ### 2.0.4 (2022-01-20) * Fix YAML loading on Ruby 3.1 - [PR #39](https://github.com/jhollinger/otr-activerecord/pull/39) - [scudelletti](https://github.com/scudelletti) ### 2.0.3 (2021-10-22) * Preliminary support for ActiveRecord 7 (tested against 7.0.0.alpha2) ### 2.0.2 (2021-09-14) * Fix `configure_from_file!` for flat files (Brynbayliss87) ### 2.0.1 (2021-06-24) * Fix configure_from_url! for AR 6.1 ### 2.0.0 (2021-05-06) * Parse three-tier database.yml * Require manually calling OTR::ActiveRecord::establish_connection! ### 1.4.2 (2021-04-03) * Allow AR 6.1 ### 1.4.0 (2019-06-05) * Add `OTR::ActiveRecord::QueryCache` middleware. ### 1.3.0 * Active Record 6.0 support ### 1.2.7 (2019-01-11) * A less hacky way of fixing the bug fixed in 1.2.6. `ENV["RACK_ENV"]`/`ENV["RAILS_ENV"]` will no longer be forced into `development` when blank. ### 1.2.6 (2018-12-11) * Bugfix to default env in development mode w/AR 5.2 ### 1.2.5 (2018-04-23) * Support ActiveRecord 5.2 ### 1.2.4 (2017-08-23) * Bugfix to db:create_migration ### 1.2.3 (2017-08-17) * Bugfix to OTR::ActiveRecord.configure_from_hash! for ActiveRecord 5.1 * Look for APP_ENV if RAILS_ENV and RACK_ENV aren't set ### 1.2.2 (2017-08-17) * Support ActiveRecord 5.1 ### 1.2.1 (2017-02-11) * Bugfix to db:test: Rake tasks for Rails 5 ### 1.2.0 (2016-08-24) * Bugfix to AR 5.0.X version restriction - [PR #2](https://github.com/jhollinger/otr-activerecord/pull/2) - [vidok](https://github.com/vidok) ### 1.0.0-rc1 (2016-07-31) * Port from grape-activerecord * Tweak `db:create_migration` to take a real rake arg rather than an env var otr-activerecord-2.5.0/Gemfile000066400000000000000000000002101472733260400162660ustar00rootroot00000000000000source 'https://rubygems.org' gemspec gem 'rake' gem 'appraisal', '~> 2.5' group :test do gem 'minitest' end gem "rack", "~> 3.1" otr-activerecord-2.5.0/LICENSE000066400000000000000000000020441472733260400160070ustar00rootroot00000000000000Copyright (c) 2024 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-2.5.0/README.md000066400000000000000000000072221472733260400162640ustar00rootroot00000000000000# 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 8.0 * ActiveRecord 7.2 * ActiveRecord 7.1 * ActiveRecord 7.0 * ActiveRecord 6.1 * See older versions of this library for older versions of ActiveRecord ## How to use #### 1. Add it to your Gemfile ```ruby 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: ```ruby 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. Connect to your database(s) If you have a single database (most apps), use this helper: ```ruby OTR::ActiveRecord.establish_connection! ``` If you're using multiple databases, call your base class(es) instead: ```ruby MyBase.establish_connection :primary MyBase.establish_connection :primary_replica ... ``` #### 4. Enable middleware for Rack apps Add these middlewares in `config.ru`: ```ruby # Clean up database connections after every request (required) use OTR::ActiveRecord::ConnectionManagement # Enable ActiveRecord's QueryCache for every request (optional) use OTR::ActiveRecord::QueryCache ``` #### 5. 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`. ```ruby 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. ```bash bundle exec rake db:create_migration[create_widgets] ``` ## 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`: ```ruby OTR::ActiveRecord.db_dir = 'db' OTR::ActiveRecord.migrations_paths = ['db/migrate'] OTR::ActiveRecord.fixtures_path = 'test/fixtures' OTR::ActiveRecord.seed_file = 'seeds.rb' ``` ## Testing Testing is fully scripted under the `bin/` directory. Appraisal is used to test against various ActiveRecord versions, and Docker or Podman is used to test against various Ruby versions. The combinations to test are defined in [test/matrix](https://github.com/jhollinger/otr-activerecord/blob/main/test/matrix). ```bash # Run all tests bin/testall # Filter tests bin/testall ruby-3.3 bin/testall ar-7.1 bin/testall ruby-3.3 ar-7.1 # Run one specific line from test/matrix bin/test ruby-3.3 ar-7.1 sqlite3 # Run a specific file bin/test ruby-3.3 ar-7.1 sqlite3 test/configure_test.rb # Run a specific test bin/test ruby-3.3 ar-7.1 sqlite3 N=test_configure_from_file # Use podman PODMAN=1 bin/testall ``` ## License Licensed under the MIT License Copyright 2024 Jordan Hollinger otr-activerecord-2.5.0/Rakefile000066400000000000000000000006451472733260400164540ustar00rootroot00000000000000require 'bundler/setup' require 'minitest/test_task' Bundler::GemHelper.install_tasks # Accepts files, dirs, N=test_name_or/pattern/, X=test_name_or/pattern/ Minitest::TestTask.create(:test) do |t| globs = ARGV[1..].map { |a| if Dir.exist? a "#{a}/**/*_test.rb" elsif File.exist? a a end }.compact t.libs << "test" << "lib" t.test_globs = globs.any? ? globs : ["test/**/*_test.rb"] end otr-activerecord-2.5.0/bin/000077500000000000000000000000001472733260400155525ustar00rootroot00000000000000otr-activerecord-2.5.0/bin/appraise000077500000000000000000000010701472733260400173020ustar00rootroot00000000000000#!/usr/bin/env bash if [[ $# -lt 3 ]]; then echo "Use: bin/appraise ruby-X ar-X [args]" exit 1 fi set -euo pipefail cd $(dirname $0)/../ ruby_version=$1 ar_version=$2 shift 2 args="$@" exec env bin/run ${ruby_version} bash -c ' BVER=$(tail -n 1 Gemfile.lock | sed "s/ //g") if ! gem list bundler --exact | grep $BVER > /dev/null; then gem install bundler -v $BVER fi bundle install && \ bundle exec appraisal '${ar_version}' bundle install && \ TEST_DATABASE_URL="'${TEST_DATABASE_URL-}'" bundle exec appraisal '${ar_version}" ${args[@]}" otr-activerecord-2.5.0/bin/lib.sh000066400000000000000000000025411472733260400166560ustar00rootroot00000000000000function podpose { if [[ -n "${PODMAN-}" ]]; then podman-compose "$@" else docker compose "$@" fi } function array_in_array { args=("$@") term_size=${args[0]} terms=("${args[@]:1:$term_size}") array=("${args[@]:$(($term_size+1))}") for x in ${terms[@]}; do if ! in_array $x ${array[@]}; then return 1 fi done return 0 } function in_array { term=$1 shift 1 for x in $@; do [[ $term == $x ]] && return 0; done return 1 } function announce { box="#############################################################" printf "\n%s\n %s\n%s\n" $box "$@" $box } function nyancat { red='\e[31m' green='\e[32m' yellow='\e[33m' blue='\e[34m' bold='\033[1m' normal='\e[0m' lines=( "" "+ o + o" " + o + +" "o +" " o + + +" "+ o o + o" "${red}-_-_-_-_-_-_-_${normal},------, o " "${yellow}_-_-_-_-_-_-_-${normal}| /\\_/\\ " "${green}-_-_-_-_-_-_-${normal}~|__( ^ .^) + + " "${blue}_-_-_-_-_-_-_-${normal}\"\" \"\" " " + o o + o" " + +" "o o o o +" " o +" "+ + o o + " "" ) for line in "${lines[@]}"; do printf "${line}\n" done } otr-activerecord-2.5.0/bin/run000077500000000000000000000003421472733260400163030ustar00rootroot00000000000000#!/usr/bin/env bash # # Use: bin/run service cmd [arg1...] # set -euo pipefail cd $(dirname $0)/../ source bin/lib.sh service=$1 shift podpose build $service podpose up --no-start $service podpose run --rm $service "$@" otr-activerecord-2.5.0/bin/test000077500000000000000000000011421472733260400164550ustar00rootroot00000000000000#!/usr/bin/env bash if [[ $# -lt 3 ]]; then echo "Use: bin/test ruby-X ar-X sqlite3|postgres-*|mysql-8 [args]" exit 1 fi set -euo pipefail cd $(dirname $0)/../ ruby_version=$1 ar_version=$2 db=$3 shift 3 if [[ $db == sqlite* ]]; then db_url="" elif [[ $db == postgres-* ]]; then db_url="postgresql://postgres@${db}:5432/postgres" elif [[ $db == mysql-* ]]; then db_url="mysql2://root:@${db}:3306/mysql" else echo "Unknown database '${db}'. Options are: sqlite, postgres-*, mysql-*" exit 1 fi export TEST_DATABASE_URL="$db_url" exec bin/appraise ${ruby_version} ${ar_version} rake test "$@" otr-activerecord-2.5.0/bin/testall000077500000000000000000000012511472733260400171470ustar00rootroot00000000000000#!/usr/bin/env bash # # Run every combination: # bin/testall # # Run just the matching combinations: # bin/testall ruby-3.0 # set -euo pipefail cd $(dirname $0)/../ source bin/lib.sh [[ $# -gt 0 ]] && filter=("$@") || filter=() # flatten matrix matrix=() while read ruby ar dbs; do for db in $dbs; do matrix+=("$ruby $ar $db") done done < <(awk '/^ *[^#]/' test/matrix) # run each row in the matrix for row in "${matrix[@]}"; do read ruby ar db <<< "$row" if [[ ${#filter[@]} -eq 0 ]] || array_in_array ${#filter[@]} ${filter[@]} $ruby $ar $db; then cmd="bin/test $ruby $ar $db" announce "$cmd" sleep 1 $cmd fi done podpose stop nyancat otr-activerecord-2.5.0/bin/uninstall000077500000000000000000000002151472733260400175070ustar00rootroot00000000000000#!/usr/bin/env bash set -euo pipefail cd $(dirname $0)/../ source bin/lib.sh podpose stop podpose down podpose down --rmi=local --volumes otr-activerecord-2.5.0/compose/000077500000000000000000000000001472733260400164475ustar00rootroot00000000000000otr-activerecord-2.5.0/compose/Dockerfile.ruby-3.0000066400000000000000000000005031472733260400217150ustar00rootroot00000000000000FROM ruby:3.0-slim-bullseye WORKDIR /srv ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_APP_CONFIG="$GEM_HOME" RUN \ apt-get update -qq && \ apt-get install -y --no-install-recommends \ build-essential \ libsqlite3-dev \ git \ && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* otr-activerecord-2.5.0/compose/Dockerfile.ruby-3.1000066400000000000000000000005031472733260400217160ustar00rootroot00000000000000FROM ruby:3.1-slim-bookworm WORKDIR /srv ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_APP_CONFIG="$GEM_HOME" RUN \ apt-get update -qq && \ apt-get install -y --no-install-recommends \ build-essential \ libsqlite3-dev \ git \ && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* otr-activerecord-2.5.0/compose/Dockerfile.ruby-3.2000066400000000000000000000005031472733260400217170ustar00rootroot00000000000000FROM ruby:3.2-slim-bookworm WORKDIR /srv ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_APP_CONFIG="$GEM_HOME" RUN \ apt-get update -qq && \ apt-get install -y --no-install-recommends \ build-essential \ libsqlite3-dev \ git \ && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* otr-activerecord-2.5.0/compose/Dockerfile.ruby-3.3000066400000000000000000000005031472733260400217200ustar00rootroot00000000000000FROM ruby:3.3-slim-bookworm WORKDIR /srv ENV GEM_HOME /usr/local/bundle ENV BUNDLE_PATH="$GEM_HOME" \ BUNDLE_APP_CONFIG="$GEM_HOME" RUN \ apt-get update -qq && \ apt-get install -y --no-install-recommends \ build-essential \ libsqlite3-dev \ git \ && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* otr-activerecord-2.5.0/docker-compose.yml000066400000000000000000000013271472733260400204420ustar00rootroot00000000000000--- services: ruby-3.3: build: context: ./ dockerfile: ./compose/Dockerfile.ruby-3.3 volumes: - ./:/srv - ruby-3.3-gems:/usr/local/bundle ruby-3.2: build: context: ./ dockerfile: ./compose/Dockerfile.ruby-3.2 volumes: - ./:/srv - ruby-3.2-gems:/usr/local/bundle ruby-3.1: build: context: ./ dockerfile: ./compose/Dockerfile.ruby-3.1 volumes: - ./:/srv - ruby-3.1-gems:/usr/local/bundle ruby-3.0: build: context: ./ dockerfile: ./compose/Dockerfile.ruby-3.0 volumes: - ./:/srv - ruby-3.0-gems:/usr/local/bundle volumes: ruby-3.3-gems: ruby-3.2-gems: ruby-3.1-gems: ruby-3.0-gems: otr-activerecord-2.5.0/examples/000077500000000000000000000000001472733260400166205ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rack-activerecord7.1/000077500000000000000000000000001472733260400224365ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rack-activerecord7.1/Gemfile000066400000000000000000000003521472733260400237310ustar00rootroot00000000000000source 'https://rubygems.org' gem 'rack', '~> 2.2' gem 'puma', '~> 5.6' gem 'activerecord', '7.1.1', require: 'active_record' gem 'otr-activerecord', path: '../../' gem 'sqlite3' gem 'rake' group :development do gem 'shotgun' end otr-activerecord-2.5.0/examples/rack-activerecord7.1/Gemfile.lock000066400000000000000000000025601472733260400246630ustar00rootroot00000000000000PATH remote: ../.. specs: otr-activerecord (2.1.2) activerecord (>= 4.0, < 7.2) hashie-forbidden_attributes (~> 0.1) GEM remote: https://rubygems.org/ specs: activemodel (7.1.1) activesupport (= 7.1.1) activerecord (7.1.1) activemodel (= 7.1.1) activesupport (= 7.1.1) timeout (>= 0.4.0) activesupport (7.1.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) minitest (>= 5.1) mutex_m tzinfo (~> 2.0) base64 (0.1.1) bigdecimal (3.1.4) concurrent-ruby (1.2.2) connection_pool (2.4.1) drb (2.1.1) ruby2_keywords hashie (5.0.0) hashie-forbidden_attributes (0.1.1) hashie (>= 3.0) i18n (1.14.1) concurrent-ruby (~> 1.0) mini_portile2 (2.8.4) minitest (5.20.0) mutex_m (0.1.2) nio4r (2.5.9) puma (5.6.7) nio4r (~> 2.0) rack (2.2.8) rake (13.0.6) ruby2_keywords (0.0.5) shotgun (0.9.2) rack (>= 1.0) sqlite3 (1.6.6) mini_portile2 (~> 2.8.0) sqlite3 (1.6.6-arm64-darwin) timeout (0.4.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) PLATFORMS arm64-darwin-22 ruby DEPENDENCIES activerecord (= 7.1.1) otr-activerecord! puma (~> 5.6) rack (~> 2.2) rake shotgun sqlite3 BUNDLED WITH 2.4.1 otr-activerecord-2.5.0/examples/rack-activerecord7.1/Rakefile000066400000000000000000000002211472733260400240760ustar00rootroot00000000000000require 'bundler/setup' load 'tasks/otr-activerecord.rake' namespace :db do task :environment do require_relative 'environment' end end otr-activerecord-2.5.0/examples/rack-activerecord7.1/config.ru000066400000000000000000000005171472733260400242560ustar00rootroot00000000000000require_relative 'environment' use OTR::ActiveRecord::ConnectionManagement use OTR::ActiveRecord::QueryCache map '/' do run ->(env) { body = Widget.all .map { |w| {id: w.id, name: w.name} } .to_json [200, {'Content-Type' => 'application/json', 'Content-Length' => body.size.to_s}, [body]] } end otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/000077500000000000000000000000001472733260400230235ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/config.yml000066400000000000000000000005221472733260400250120ustar00rootroot00000000000000development: adapter: sqlite3 encoding: utf8 database: db/otr_example_dev.sqlite3 pool: 5 timeout: 5000 test: adapter: sqlite3 encoding: utf8 database: db/otr_example_test.sqlite3 pool: 5 timeout: 5000 production: adapter: sqlite3 encoding: utf8 database: db/otr_example_prod.sqlite3 pool: 5 timeout: 5000 otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/migrate/000077500000000000000000000000001472733260400244535ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/migrate/.keep000066400000000000000000000000001472733260400253660ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/schema.rb000066400000000000000000000024241472733260400246120ustar00rootroot00000000000000# This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # This file is the source Rails uses to define your schema when running `bin/rails # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to # be faster and is potentially less error prone than running all of your # migrations from scratch. Old migrations may fail to apply correctly if those # migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 2021_10_23_013351) do create_table "bars", force: :cascade do |t| t.string "name", null: false end create_table "foos", force: :cascade do |t| t.string "name", null: false end create_table "splines", force: :cascade do |t| t.string "name", null: false t.index ["name"], name: "index_splines_on_name", unique: true end create_table "widgets", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end otr-activerecord-2.5.0/examples/rack-activerecord7.1/db/seeds.rb000066400000000000000000000001131472733260400244460ustar00rootroot00000000000000Widget.create! name: 'A' Widget.create! name: 'B' Widget.create! name: 'C' otr-activerecord-2.5.0/examples/rack-activerecord7.1/environment.rb000066400000000000000000000004311472733260400253250ustar00rootroot00000000000000require 'json' require 'bundler' Bundler.require(:default, ENV['OTR_ENV'] ? ENV['OTR_ENV'].to_sym : :development) OTR::ActiveRecord.configure_from_file! './db/config.yml' OTR::ActiveRecord.establish_connection! class Widget < ActiveRecord::Base validates_presence_of :name end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/000077500000000000000000000000001472733260400233005ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/.gitignore000066400000000000000000000000311472733260400252620ustar00rootroot00000000000000/.bundle /data/*.sqlite3 otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/Gemfile000066400000000000000000000002251472733260400245720ustar00rootroot00000000000000source 'https://rubygems.org' gem 'activerecord', '8.0.1', require: 'active_record' gem 'otr-activerecord', path: '../../' gem 'sqlite3' gem 'rake' otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/Gemfile.lock000066400000000000000000000031261472733260400255240ustar00rootroot00000000000000PATH remote: ../.. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (8.0.1) activesupport (= 8.0.1) activerecord (8.0.1) activemodel (= 8.0.1) activesupport (= 8.0.1) timeout (>= 0.4.0) activesupport (8.0.1) base64 benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) base64 (0.2.0) benchmark (0.4.0) bigdecimal (3.1.8) concurrent-ruby (1.3.4) connection_pool (2.4.1) drb (2.2.1) i18n (1.14.6) concurrent-ruby (~> 1.0) logger (1.6.3) minitest (5.25.4) rake (13.2.1) securerandom (0.4.0) sqlite3 (2.4.1-aarch64-linux-gnu) sqlite3 (2.4.1-aarch64-linux-musl) sqlite3 (2.4.1-arm-linux-gnu) sqlite3 (2.4.1-arm-linux-musl) sqlite3 (2.4.1-arm64-darwin) sqlite3 (2.4.1-x86-linux-gnu) sqlite3 (2.4.1-x86-linux-musl) sqlite3 (2.4.1-x86_64-darwin) sqlite3 (2.4.1-x86_64-linux-gnu) sqlite3 (2.4.1-x86_64-linux-musl) timeout (0.4.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uri (1.0.2) PLATFORMS aarch64-linux-gnu aarch64-linux-musl arm-linux-gnu arm-linux-musl arm64-darwin x86-linux-gnu x86-linux-musl x86_64-darwin x86_64-linux-gnu x86_64-linux-musl DEPENDENCIES activerecord (= 8.0.1) otr-activerecord! rake sqlite3 BUNDLED WITH 2.5.18 otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/Rakefile000066400000000000000000000023211472733260400247430ustar00rootroot00000000000000require 'bundler/setup' load 'tasks/otr-activerecord.rake' OTR::ActiveRecord.db_dir = 'data' OTR::ActiveRecord.migrations_paths = ['data/migrate'] OTR::ActiveRecord.seed_file = 'seeds.rb' namespace :db do task :environment do require_relative 'environment' end end namespace :widgets do desc "Query all widgets" task :query => 'db:environment' do widgets = Widget.order('name').to_a puts widgets.map(&:as_json).to_json end desc "Fetch a single widget" task :fetch, [:id] => 'db:environment' do |_, args| widget = Widget.find(args[:id]) puts widget.to_json end desc "Create a new widget" task :create, [:name] => 'db:environment' do |_, args| widget = Widget.new(name: args[:name]) if widget.save puts widget.to_json else abort({errors: widget.errors.full_message}.to_json) end end desc "Update a widget" task :update, [:id, :name] => 'db:environment' do |_, args| widget = Widget.where(id: args[:id]).first abort({errors: ["Widget '#{args[:id]}' not found"]}.to_json) if widget.nil? if widget.update_columns({name: args[:name]}) puts widget.to_json else abort({errors: widget.errors.full_message}.to_json) end end end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/000077500000000000000000000000001472733260400242115ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/config.yml000066400000000000000000000005411472733260400262010ustar00rootroot00000000000000development: adapter: sqlite3 encoding: utf8 database: data/otr_example_70_dev.sqlite3 pool: 5 timeout: 5000 test: adapter: sqlite3 encoding: utf8 database: data/otr_example_70_test.sqlite3 pool: 5 timeout: 5000 production: adapter: sqlite3 encoding: utf8 database: data/otr_example_70_prod.sqlite3 pool: 5 timeout: 5000 otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/migrate/000077500000000000000000000000001472733260400256415ustar00rootroot0000000000000020160731142314_create_widgets.rb000066400000000000000000000002641472733260400325440ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/migrateclass CreateWidgets < ActiveRecord::Migration[5.0] def change create_table :widgets do |t| t.string :name, null: false t.timestamps null: false end end end 20171128231939_create_splines.rb000066400000000000000000000003011472733260400325610ustar00rootroot00000000000000otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/migrateclass CreateSplines < ActiveRecord::Migration[5.2] def change create_table :splines do |t| t.string :name, null: false end add_index :splines, :name, unique: true end end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/migrate/20180423164820_foo.rb000066400000000000000000000002101472733260400304120ustar00rootroot00000000000000class Foo < ActiveRecord::Migration[5.2] def change create_table :foos do |t| t.string :name, null: false end end end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/migrate/20211023013351_bar.rb000066400000000000000000000002101472733260400303520ustar00rootroot00000000000000class Bar < ActiveRecord::Migration[7.0] def change create_table :bars do |t| t.string :name, null: false end end end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/schema.rb000066400000000000000000000024241472733260400260000ustar00rootroot00000000000000# This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # This file is the source Rails uses to define your schema when running `bin/rails # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to # be faster and is potentially less error prone than running all of your # migrations from scratch. Old migrations may fail to apply correctly if those # migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 2021_10_23_013351) do create_table "bars", force: :cascade do |t| t.string "name", null: false end create_table "foos", force: :cascade do |t| t.string "name", null: false end create_table "splines", force: :cascade do |t| t.string "name", null: false t.index ["name"], name: "index_splines_on_name", unique: true end create_table "widgets", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/data/seeds.rb000066400000000000000000000001131472733260400256340ustar00rootroot00000000000000Widget.create! name: 'A' Widget.create! name: 'B' Widget.create! name: 'C' otr-activerecord-2.5.0/examples/rakefile-activerecord8.0/environment.rb000066400000000000000000000004331472733260400261710ustar00rootroot00000000000000require 'json' require 'bundler' Bundler.require(:default, ENV['OTR_ENV'] ? ENV['OTR_ENV'].to_sym : :development) OTR::ActiveRecord.configure_from_file! './data/config.yml' OTR::ActiveRecord.establish_connection! class Widget < ActiveRecord::Base validates_presence_of :name end otr-activerecord-2.5.0/gemfiles/000077500000000000000000000000001472733260400165755ustar00rootroot00000000000000otr-activerecord-2.5.0/gemfiles/ar_6.1.gemfile000066400000000000000000000003641472733260400211200ustar00rootroot00000000000000# This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "appraisal", "~> 2.5" gem "rack", "~> 3.1" gem "activerecord", "~> 6.1.4" gem "sqlite3", "~> 1.4.2" group :test do gem "minitest" end gemspec path: "../" otr-activerecord-2.5.0/gemfiles/ar_6.1.gemfile.lock000066400000000000000000000016731472733260400220530ustar00rootroot00000000000000PATH remote: .. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (6.1.7.8) activesupport (= 6.1.7.8) activerecord (6.1.7.8) activemodel (= 6.1.7.8) activesupport (= 6.1.7.8) activesupport (6.1.7.8) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) zeitwerk (~> 2.3) appraisal (2.5.0) bundler rake thor (>= 0.14.0) concurrent-ruby (1.3.3) i18n (1.14.5) concurrent-ruby (~> 1.0) minitest (5.24.0) rack (3.1.4) rake (13.2.1) sqlite3 (1.4.4) thor (1.3.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) zeitwerk (2.6.16) PLATFORMS aarch64-linux ruby DEPENDENCIES activerecord (~> 6.1.4) appraisal (~> 2.5) minitest otr-activerecord! rack (~> 3.1) rake sqlite3 (~> 1.4.2) BUNDLED WITH 2.5.11 otr-activerecord-2.5.0/gemfiles/ar_7.0.gemfile000066400000000000000000000003641472733260400211200ustar00rootroot00000000000000# This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "appraisal", "~> 2.5" gem "rack", "~> 3.1" gem "activerecord", "~> 7.0.1" gem "sqlite3", "~> 1.4.2" group :test do gem "minitest" end gemspec path: "../" otr-activerecord-2.5.0/gemfiles/ar_7.0.gemfile.lock000066400000000000000000000016151472733260400220470ustar00rootroot00000000000000PATH remote: .. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (7.0.8.4) activesupport (= 7.0.8.4) activerecord (7.0.8.4) activemodel (= 7.0.8.4) activesupport (= 7.0.8.4) activesupport (7.0.8.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) appraisal (2.5.0) bundler rake thor (>= 0.14.0) concurrent-ruby (1.3.3) i18n (1.14.5) concurrent-ruby (~> 1.0) minitest (5.24.0) rack (3.1.4) rake (13.2.1) sqlite3 (1.4.4) thor (1.3.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) PLATFORMS aarch64-linux ruby DEPENDENCIES activerecord (~> 7.0.1) appraisal (~> 2.5) minitest otr-activerecord! rack (~> 3.1) rake sqlite3 (~> 1.4.2) BUNDLED WITH 2.5.11 otr-activerecord-2.5.0/gemfiles/ar_7.1.gemfile000066400000000000000000000003641472733260400211210ustar00rootroot00000000000000# This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "appraisal", "~> 2.5" gem "rack", "~> 3.1" gem "activerecord", "~> 7.1.1" gem "sqlite3", "~> 1.7.3" group :test do gem "minitest" end gemspec path: "../" otr-activerecord-2.5.0/gemfiles/ar_7.1.gemfile.lock000066400000000000000000000022621472733260400220470ustar00rootroot00000000000000PATH remote: .. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (7.1.3.4) activesupport (= 7.1.3.4) activerecord (7.1.3.4) activemodel (= 7.1.3.4) activesupport (= 7.1.3.4) timeout (>= 0.4.0) activesupport (7.1.3.4) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) minitest (>= 5.1) mutex_m tzinfo (~> 2.0) appraisal (2.5.0) bundler rake thor (>= 0.14.0) base64 (0.2.0) bigdecimal (3.1.8) concurrent-ruby (1.3.3) connection_pool (2.4.1) drb (2.2.1) i18n (1.14.5) concurrent-ruby (~> 1.0) minitest (5.24.0) mutex_m (0.2.0) rack (3.1.4) rake (13.2.1) sqlite3 (1.7.3-aarch64-linux) sqlite3 (1.7.3-arm64-darwin) thor (1.3.1) timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) PLATFORMS aarch64-linux arm64-darwin DEPENDENCIES activerecord (~> 7.1.1) appraisal (~> 2.5) minitest otr-activerecord! rack (~> 3.1) rake sqlite3 (~> 1.7.3) BUNDLED WITH 2.5.11 otr-activerecord-2.5.0/gemfiles/ar_7.2.gemfile000066400000000000000000000003641472733260400211220ustar00rootroot00000000000000# This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "appraisal", "~> 2.5" gem "rack", "~> 3.1" gem "activerecord", "~> 7.2.1" gem "sqlite3", "~> 1.7.3" group :test do gem "minitest" end gemspec path: "../" otr-activerecord-2.5.0/gemfiles/ar_7.2.gemfile.lock000066400000000000000000000023561472733260400220540ustar00rootroot00000000000000PATH remote: .. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (7.2.1) activesupport (= 7.2.1) activerecord (7.2.1) activemodel (= 7.2.1) activesupport (= 7.2.1) timeout (>= 0.4.0) activesupport (7.2.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) appraisal (2.5.0) bundler rake thor (>= 0.14.0) base64 (0.2.0) bigdecimal (3.1.8) concurrent-ruby (1.3.4) connection_pool (2.4.1) drb (2.2.1) i18n (1.14.5) concurrent-ruby (~> 1.0) logger (1.6.0) minitest (5.24.0) rack (3.1.4) rake (13.2.1) securerandom (0.3.1) sqlite3 (1.7.3-aarch64-linux) sqlite3 (1.7.3-arm64-darwin) thor (1.3.1) timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) PLATFORMS aarch64-linux arm64-darwin DEPENDENCIES activerecord (~> 7.2.1) appraisal (~> 2.5) minitest otr-activerecord! rack (~> 3.1) rake sqlite3 (~> 1.7.3) BUNDLED WITH 2.5.11 otr-activerecord-2.5.0/gemfiles/ar_8.0.gemfile000066400000000000000000000003641472733260400211210ustar00rootroot00000000000000# This file was generated by Appraisal source "https://rubygems.org" gem "rake" gem "appraisal", "~> 2.5" gem "rack", "~> 3.1" gem "activerecord", "~> 8.0.0" gem "sqlite3", "~> 2.4.1" group :test do gem "minitest" end gemspec path: "../" otr-activerecord-2.5.0/gemfiles/ar_8.0.gemfile.lock000066400000000000000000000025231472733260400220470ustar00rootroot00000000000000PATH remote: .. specs: otr-activerecord (2.5.0) activerecord (>= 6.0, < 8.1) GEM remote: https://rubygems.org/ specs: activemodel (8.0.0.1) activesupport (= 8.0.0.1) activerecord (8.0.0.1) activemodel (= 8.0.0.1) activesupport (= 8.0.0.1) timeout (>= 0.4.0) activesupport (8.0.0.1) base64 benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) appraisal (2.5.0) bundler rake thor (>= 0.14.0) base64 (0.2.0) benchmark (0.4.0) bigdecimal (3.1.8) concurrent-ruby (1.3.4) connection_pool (2.4.1) drb (2.2.1) i18n (1.14.6) concurrent-ruby (~> 1.0) logger (1.6.3) minitest (5.25.4) rack (3.1.8) rake (13.2.1) securerandom (0.4.0) sqlite3 (2.4.1-aarch64-linux-gnu) sqlite3 (2.4.1-arm64-darwin) thor (1.3.2) timeout (0.4.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uri (1.0.2) PLATFORMS aarch64-linux arm64-darwin DEPENDENCIES activerecord (~> 8.0.0) appraisal (~> 2.5) minitest otr-activerecord! rack (~> 3.1) rake sqlite3 (~> 2.4.1) BUNDLED WITH 2.5.11 otr-activerecord-2.5.0/lib/000077500000000000000000000000001472733260400155505ustar00rootroot00000000000000otr-activerecord-2.5.0/lib/otr-activerecord.rb000066400000000000000000000005771472733260400213620ustar00rootroot00000000000000require 'active_record' require 'otr-activerecord/version' require 'otr-activerecord/activerecord' ENV["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.shim = OTR::ActiveRecord::Shim.new otr-activerecord-2.5.0/lib/otr-activerecord/000077500000000000000000000000001472733260400210245ustar00rootroot00000000000000otr-activerecord-2.5.0/lib/otr-activerecord/activerecord.rb000066400000000000000000000060211472733260400240220ustar00rootroot00000000000000require 'erb' require 'uri' require 'yaml' # "Off the Rails" ActiveRecord configuration/integration for Grape, Sinatra, Rack, and any other kind of app module OTR # ActiveRecord configuration module module ActiveRecord autoload :ConnectionManagement, 'otr-activerecord/middleware/connection_management' autoload :QueryCache, 'otr-activerecord/middleware/query_cache' autoload :Shim, "otr-activerecord/shim/v#{::ActiveRecord::VERSION::MAJOR}" 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 :shim 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) ::ActiveRecord::Base.configurations = transform_config({rack_env.to_s => spec}) end # Connect to database with a DB URL. Example: "postgres://user:pass@localhost/db" def self.configure_from_url!(url) uri = URI(url) spec = {"adapter" => uri.scheme} case spec["adapter"] when /^sqlite/i spec["database"] = url =~ /::memory:/ ? ":memory:" : "#{uri.host}#{uri.path}" else spec["host"] = uri.host if uri.host spec["port"] = uri.port if uri.port spec["database"] = uri.path.sub(/^\//, "") spec["username"] = uri.user if uri.user spec["password"] = uri.password if uri.password end if uri.query opts_ary = URI.decode_www_form(uri.query) opts = Hash[opts_ary] spec.merge!(opts) end configure_from_hash! spec end # Connect to database with a yml file. Example: "config/database.yml" def self.configure_from_file!(path) yaml = ERB.new(File.read(path)).result spec = YAML.safe_load(yaml, aliases: true) || {} ::ActiveRecord::Base.configurations = transform_config spec end # Establish a connection to the given db (defaults to current rack env) def self.establish_connection!(db = rack_env) ::ActiveRecord::Base.establish_connection(db) 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 def self.transform_config(spec) fixup = ->(config) { config = config.stringify_keys config["migrations_paths"] ||= migrations_paths config } spec.stringify_keys.transform_values { |config| if config.all? { |_, v| v.is_a? Hash } config.transform_values { |v| fixup.(v) } else fixup.(config) end } end private_class_method :transform_config end end otr-activerecord-2.5.0/lib/otr-activerecord/middleware/000077500000000000000000000000001472733260400231415ustar00rootroot00000000000000otr-activerecord-2.5.0/lib/otr-activerecord/middleware/connection_management.rb000066400000000000000000000012131472733260400300160ustar00rootroot00000000000000module 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.connection_handler.clear_active_connections! unless testing end resp rescue => e ::ActiveRecord::Base.connection_handler.clear_active_connections! unless testing raise e end end end end otr-activerecord-2.5.0/lib/otr-activerecord/middleware/query_cache.rb000066400000000000000000000006321472733260400257570ustar00rootroot00000000000000module OTR module ActiveRecord # # Rack middleware to enable ActiveRecord's query cache for each request. # class QueryCache 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 otr-activerecord-2.5.0/lib/otr-activerecord/shim/000077500000000000000000000000001472733260400217645ustar00rootroot00000000000000otr-activerecord-2.5.0/lib/otr-activerecord/shim/base.rb000066400000000000000000000014571472733260400232320ustar00rootroot00000000000000module OTR module ActiveRecord # Base compatibility layer for ActiveRecord class ShimBase def initialize ::ActiveRecord.default_timezone = :utc 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 major_v = ::ActiveRecord::VERSION::MAJOR minor_v = ::ActiveRecord::VERSION::MINOR "ActiveRecord::Migration[#{major_v}.#{minor_v}]" 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-2.5.0/lib/otr-activerecord/shim/v6.rb000066400000000000000000000003471472733260400226500ustar00rootroot00000000000000require_relative 'base' module OTR module ActiveRecord # Compatibility layer for ActiveRecord 6 class Shim < ShimBase def initialize ::ActiveRecord::Base.default_timezone = :utc end end end end otr-activerecord-2.5.0/lib/otr-activerecord/shim/v7.rb000066400000000000000000000002231472733260400226420ustar00rootroot00000000000000require_relative 'base' module OTR module ActiveRecord # Compatibility layer for ActiveRecord 7 class Shim < ShimBase end end end otr-activerecord-2.5.0/lib/otr-activerecord/shim/v8.rb000066400000000000000000000002231472733260400226430ustar00rootroot00000000000000require_relative 'base' module OTR module ActiveRecord # Compatibility layer for ActiveRecord 8 class Shim < ShimBase end end end otr-activerecord-2.5.0/lib/otr-activerecord/version.rb000066400000000000000000000001231472733260400230320ustar00rootroot00000000000000module OTR module ActiveRecord # Gem version VERSION = '2.5.0' end end otr-activerecord-2.5.0/lib/tasks/000077500000000000000000000000001472733260400166755ustar00rootroot00000000000000otr-activerecord-2.5.0/lib/tasks/otr-activerecord.rake000066400000000000000000000047751472733260400230320ustar00rootroot00000000000000require '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.shim.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.shim.migrations_paths.each do |directory| next unless File.exist?(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.shim.migrations_path path = File.join(dirname, filename) FileUtils.mkdir_p(dirname) File.write path, <<-MIGRATION.strip_heredoc class #{name.camelize} < #{OTR::ActiveRecord.shim.migration_base_class_name} def change end end MIGRATION puts path end end otr-activerecord-2.5.0/otr-activerecord.gemspec000066400000000000000000000014261472733260400216260ustar00rootroot00000000000000# encoding: utf-8 require File.expand_path('../lib/otr-activerecord/version.rb', __FILE__) Gem::Specification.new do |gem| gem.name = 'otr-activerecord' gem.version = OTR::ActiveRecord::VERSION gem.description = 'Off The Rails ActiveRecord: Use ActiveRecord with Grape, Sinatra, Rack, or anything else! Formerly known as \'grape-activerecord\'.' gem.summary = 'Off The Rails: Use ActiveRecord with Grape, Sinatra, Rack, or anything else!' gem.homepage = 'https://github.com/jhollinger/otr-activerecord' gem.authors = ['Jordan Hollinger'] gem.email = 'jordan.hollinger@gmail.com' gem.license = 'MIT' gem.files = Dir['lib/**/**'] + ['README.md', 'LICENSE'] gem.required_ruby_version = '>= 3.0.0' gem.add_runtime_dependency 'activerecord', ['>= 6.0', '< 8.1'] end otr-activerecord-2.5.0/test/000077500000000000000000000000001472733260400157615ustar00rootroot00000000000000otr-activerecord-2.5.0/test/configure_test.rb000066400000000000000000000056721472733260400213400ustar00rootroot00000000000000require 'test_helper' class ConfigureTest < Minitest::Test def test_configure_from_file OTR::ActiveRecord.configure_from_file! "test/fixtures/simple.yml" t = ::ActiveRecord::Base.configurations.find_db_config('test') assert_equal "sqlite3", t.adapter assert_equal "tmp/simple.sqlite3", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_file_with_multiple_roles OTR::ActiveRecord.configure_from_file! "test/fixtures/multi.yml" t = ::ActiveRecord::Base.configurations.find_db_config('test') assert_equal "sqlite3", t.adapter assert_equal "tmp/multi.sqlite3", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_url OTR::ActiveRecord.configure_from_url! "postgresql://foo:bar@my.host/mydb" t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "postgresql", t.adapter assert_equal "my.host", t.host assert_equal "mydb", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_url_with_port OTR::ActiveRecord.configure_from_url! "postgresql://foo:bar@my.host/mydb:5433" t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "postgresql", t.adapter assert_equal "my.host", t.host assert_equal "mydb:5433", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_url_using_sqlite3 OTR::ActiveRecord.configure_from_url! "sqlite3:///srv/db/mydb.sqlite3" t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "sqlite3", t.adapter assert_equal "/srv/db/mydb.sqlite3", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_url_using_sqlite3_memory OTR::ActiveRecord.configure_from_url! "sqlite3::memory:" t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "sqlite3", t.adapter assert_equal ":memory:", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_hash OTR::ActiveRecord.configure_from_hash!({adapter: "postgresql", host: "localhost", database: "db"}) t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "postgresql", t.adapter assert_equal "localhost", t.host assert_equal "db", t.database assert_equal ['db/migrate'], t.migrations_paths end def test_configure_from_hash_with_multiple_roles OTR::ActiveRecord.configure_from_hash!({ primary: {adapter: "postgresql", host: "localhost", database: "primary"}, reading: {adapter: "postgresql", host: "localhost", database: "reading"}, }) t = ::ActiveRecord::Base.configurations.find_db_config('development') assert_equal "postgresql", t.adapter assert_equal "localhost", t.host assert_equal "primary", t.database assert_equal ['db/migrate'], t.migrations_paths end end otr-activerecord-2.5.0/test/connection_management_test.rb000066400000000000000000000040561472733260400237050ustar00rootroot00000000000000require 'test_helper' class ConnectionManagementTest < Minitest::Test def setup @db = Tempfile.create OTR::ActiveRecord.configure_from_hash!({adapter: "sqlite3", database: @db.path}) OTR::ActiveRecord.establish_connection! Schema.load! cat = Category.create!(name: "Foo") Widget.create!(category_id: cat.id, name: "Spline") end def teardown ActiveRecord::Base.connection_handler.clear_all_connections! ActiveRecord::Base.connection_pool.disconnect! File.unlink @db.path end def test_returns_resp app = proc do |env| body = "Testing" [200, {"Content-Type" => "text/plain", "Content-Length" => body.size.to_s}, [body]] end middleware = OTR::ActiveRecord::ConnectionManagement.new(app) status, headers, body = middleware.call({}) assert_equal 200, status assert_equal "text/plain", headers["Content-Type"] assert_equal ["Testing"], body.to_a end def test_with_no_queries called = false app = proc do |env| called = true body = "Testing" [200, {"Content-Type" => "text/plain", "Content-Length" => body.size.to_s}, [body]] end middleware = OTR::ActiveRecord::ConnectionManagement.new(app) middleware.call({}) assert called end def test_with_queries n = nil app = proc do |env| n = Widget.count body = "Testing" [200, {"Content-Type" => "text/plain", "Content-Length" => body.size.to_s}, [body]] end middleware = OTR::ActiveRecord::ConnectionManagement.new(app) middleware.call({}) assert_equal 1, n end def test_with_many_threads app = proc do |env| n = Widget.count body = n.to_s [200, {"Content-Type" => "text/plain", "Content-Length" => body.size.to_s}, [body]] end n = 500 middleware = OTR::ActiveRecord::ConnectionManagement.new(app) results = n.times .map { Thread.new { _, _, body = middleware.call({}) body.close body[0] } } .map(&:value) assert_equal n.times.map { "1" }, results end end otr-activerecord-2.5.0/test/fixtures/000077500000000000000000000000001472733260400176325ustar00rootroot00000000000000otr-activerecord-2.5.0/test/fixtures/multi.yml000066400000000000000000000005141472733260400215070ustar00rootroot00000000000000.defaults: &defaults adapter: sqlite3 database: tmp/multi.sqlite3 development: primary: <<: *defaults reading: <<: *defaults replica: true production: primary: <<: *defaults reading: <<: *defaults replica: true test: primary: <<: *defaults reading: <<: *defaults replica: true otr-activerecord-2.5.0/test/fixtures/simple.yml000066400000000000000000000002311472733260400216420ustar00rootroot00000000000000.defaults: &defaults adapter: sqlite3 database: tmp/simple.sqlite3 development: <<: *defaults production: <<: *defaults test: <<: *defaults otr-activerecord-2.5.0/test/matrix000066400000000000000000000010311472733260400172030ustar00rootroot00000000000000# # Read by bin/testall to test various combinations of Ruby, ActiveRecord, and datbases # ruby-3.3 ar-8.0 sqlite3 ruby-3.3 ar-7.2 sqlite3 ruby-3.3 ar-7.1 sqlite3 ruby-3.3 ar-7.0 sqlite3 ruby-3.3 ar-6.1 sqlite3 ruby-3.2 ar-8.0 sqlite3 ruby-3.2 ar-7.2 sqlite3 ruby-3.2 ar-7.1 sqlite3 ruby-3.2 ar-7.0 sqlite3 ruby-3.2 ar-6.1 sqlite3 ruby-3.1 ar-7.2 sqlite3 ruby-3.1 ar-7.1 sqlite3 ruby-3.1 ar-7.0 sqlite3 ruby-3.1 ar-6.1 sqlite3 ruby-3.0 ar-7.1 sqlite3 ruby-3.0 ar-7.0 sqlite3 ruby-3.0 ar-6.1 sqlite3 otr-activerecord-2.5.0/test/query_cache_test.rb000066400000000000000000000016551472733260400216440ustar00rootroot00000000000000require 'test_helper' class QueryCacheTest < Minitest::Test def setup @db = Tempfile.create OTR::ActiveRecord.configure_from_hash!({adapter: "sqlite3", database: @db.path}) OTR::ActiveRecord.establish_connection! Schema.load! @cat = Category.create!(name: "Foo") Widget.create!(category_id: @cat.id, name: "Spline") end def teardown ActiveRecord::Base.connection_handler.clear_all_connections! ActiveRecord::Base.connection_pool.disconnect! File.unlink @db.path end def test_returns_resp app = proc do |env| Widget.count body = "Testing" [200, {"Content-Type" => "text/plain", "Content-Length" => body.size.to_s}, [body]] end middleware = OTR::ActiveRecord::QueryCache.new(app) status, headers, body = middleware.call({}) assert_equal 200, status assert_equal "text/plain", headers["Content-Type"] assert_equal ["Testing"], body.to_a end end otr-activerecord-2.5.0/test/rake_test.rb000066400000000000000000000030431472733260400202670ustar00rootroot00000000000000require 'test_helper' require 'rake' require 'json' class RakeTest < Minitest::Test def self.test_order; :alpha; end def setup Dir.chdir TestApp::DIR if TestApp.exists? end def teardown Dir.chdir Rake.application.original_dir end def test_1_create TestApp.delete if TestApp.exists? TestApp.create end def test_2_setup skip unless TestApp.exists? assert system "bundle install" assert system "bundle exec rake db:setup" widgets = JSON.parse(`bundle exec rake widgets:list`) assert_equal ["Foo"], widgets.map { |w| w["name"] } end def test_3_create_migration skip unless TestApp.exists? migration = `bundle exec rake db:create_migration[add_active]`.chomp assert File.exist? migration assert_equal <<-STR.chomp, File.read(migration).chomp class AddActive < ActiveRecord::Migration[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}] def change end end STR end def test_4_run_migration skip unless TestApp.exists? migration = Dir.glob("db/migrate/*.rb")[0] File.write migration, <<-STR class AddActive < ActiveRecord::Migration[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}] def change add_column :widgets, :active, :boolean, default: true, null: false end end STR assert system "bundle exec rake db:migrate db:test:prepare" widgets = JSON.parse(`bundle exec rake widgets:list`) assert_equal ["Foo:true"], widgets.map { |w| "#{w['name']}:#{w['active']}" } end def test_5_teardown TestApp.delete end end otr-activerecord-2.5.0/test/support/000077500000000000000000000000001472733260400174755ustar00rootroot00000000000000otr-activerecord-2.5.0/test/support/active_record_connection.rb000066400000000000000000000004131472733260400250500ustar00rootroot00000000000000require 'otr-activerecord' if ENV["TEST_DATABASE_URL"].to_s != "" OTR::ActiveRecord.configure_from_url!(ENV["TEST_DATABASE_URL"]) else OTR::ActiveRecord.configure_from_hash!(adapter: "sqlite3", database: ":memory:", encoding: "utf8", pool: 5, timeout: 5000) end otr-activerecord-2.5.0/test/support/active_record_models.rb000066400000000000000000000001721472733260400241760ustar00rootroot00000000000000class Category < ActiveRecord::Base has_many :widgets end class Widget < ActiveRecord::Base belongs_to :category end otr-activerecord-2.5.0/test/support/active_record_schema.rb000066400000000000000000000007371472733260400241620ustar00rootroot00000000000000ActiveRecord::Base.logger = nil module Schema def self.load! ActiveRecord::Base.connection.instance_eval do drop_table :categories if table_exists? :categories create_table :categories do |t| t.string :name, null: false end drop_table :widgets if table_exists? :widgets create_table :widgets do |t| t.string :name, null: false t.integer :category_id end add_index :widgets, :category_id end end end otr-activerecord-2.5.0/test/support/test_app.rb000066400000000000000000000045251472733260400216470ustar00rootroot00000000000000require 'fileutils' module TestApp DIR = "/tmp/otr-activerecord-test-app" DB_DEV = "db/development.sqlite3" DB_TEST = "db/test.sqlite3" DB_PROD = "db/production.sqlite3" def self.delete FileUtils.rm_r DIR end def self.exists? Dir.exist? DIR end def self.create FileUtils.mkdir_p DIR FileUtils.mkdir_p File.join(DIR, "db", "migrate") File.write File.join(DIR, "Gemfile"), gemfile File.write File.join(DIR, "Rakefile"), rakefile File.write File.join(DIR, "models.rb"), models File.write File.join(DIR, "db", "schema.rb"), schemarb File.write File.join(DIR, "db", "seeds.rb"), seedsrb File.write File.join(DIR, "db", "config.yaml"), dbconfig end def self.models <<-STR class Widget < ActiveRecord::Base end STR end def self.gemfile File .readlines(File.join("gemfiles", "ar_#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}.gemfile")) .select { |line| line =~ /source|rake|activerecord|sqlite/ } .push("gem 'otr-activerecord', path: #{Rake.application.original_dir}") .join("") end def self.rakefile <<-STR require 'json' require 'bundler/setup' load 'tasks/otr-activerecord.rake' namespace :db do task :environment do require_relative "./models" OTR::ActiveRecord.configure_from_file! "db/config.yaml" OTR::ActiveRecord.establish_connection! end end namespace :widgets do desc "List all widgets" task :list => 'db:environment' do widgets = Widget.order('name').to_a puts widgets.map(&:as_json).to_json end end STR end def self.dbconfig <<-STR development: adapter: sqlite3 database: #{DB_DEV} test: adapter: sqlite3 database: #{DB_TEST} production: adapter: sqlite3 database: #{DB_PROD} STR end def self.schemarb <<-STR ActiveRecord::Schema.define(version: 2026_07_02_013351) do create_table "widgets", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end STR end def self.seedsrb <<-STR Widget.create!(name: "Foo") STR end end otr-activerecord-2.5.0/test/test_helper.rb000066400000000000000000000002031472733260400206170ustar00rootroot00000000000000require 'otr-activerecord' require 'rack' require 'minitest/autorun' Dir.glob('./test/support/*.rb').each { |file| require file }