Class: Kettle::Jem::Appraisals::ActiveRecordSupportGemfileGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb,
sig/kettle/jem/appraisals.rbs

Overview

Generates the modular gemfiles that give ActiveRecord test suites a database driver on every engine: sqlite3 on MRI/TruffleRuby and activerecord-jdbcsqlite3-adapter (plus bigdecimal) on JRuby.

Two variants exist because sqlite3 2.x is only supported by ActiveRecord >= 7.2, while older ActiveRecord needs the 1.4 series. The JDBC adapter's release series tracks ActiveRecord (52.x, 61.x, 72.x…), so an open requirement lets Bundler pick the adapter matching the resolved ActiveRecord.

Files that exist without the GENERATED_HEADER are treated as hand-maintained and are never overwritten.

Examples:

generator = ActiveRecordSupportGemfileGenerator.new(base_dir: "/path/to/gem")
generator.generate
generator.eval_path_for("7.1.6") #=> "modular/activerecord_support.gemfile"

Constant Summary collapse

GENERATED_HEADER =

Returns header marking a support gemfile as generated (and safe to regenerate).

Returns:

  • (String) —

    header marking a support gemfile as generated (and safe to regenerate)

"# Generated by kettle-jem-appraisals"
LEGACY_PATH =

Returns support gemfile for ActiveRecord below MODERN_ACTIVERECORD.

Returns:

"gemfiles/modular/activerecord_support.gemfile"
MODERN_PATH =

Returns support gemfile for ActiveRecord at or above MODERN_ACTIVERECORD.

Returns:

"gemfiles/modular/activerecord_support_modern.gemfile"
MODERN_ACTIVERECORD =

Returns first ActiveRecord release that supports sqlite3 2.x.

Returns:

  • (Gem::Version) —

    first ActiveRecord release that supports sqlite3 2.x

Gem::Version.new("7.2")
VARIANTS =

Returns per-variant sqlite3 requirements and description.

Returns:

  • (Hash{String => Hash}) —

    per-variant sqlite3 requirements and description

{
  LEGACY_PATH => {sqlite3: [">= 1.4", "< 1.5"], label: "ActiveRecord < 7.2"},
  MODERN_PATH => {sqlite3: [">= 2.1"], label: "ActiveRecord >= 7.2"}
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_dir: Dir.pwd) ⇒ ActiveRecordSupportGemfileGenerator

Returns a new instance of ActiveRecordSupportGemfileGenerator.

Parameters:

  • base_dir (String) (defaults to: Dir.pwd) —

    path to the project root

  • base_dir: (String) (defaults to: Dir.pwd)


57
58
59
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 57

def initialize(base_dir: Dir.pwd)
  @base_dir = base_dir
end

Instance Attribute Details

#base_dir ⇒ String (readonly)

Returns absolute path to the project root.

Returns:

  • (String) —

    absolute path to the project root



54
55
56
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 54

def base_dir
  @base_dir
end

Class Method Details

.support_gemfile?(path) ⇒ Boolean

Returns whether path names one of the ActiveRecord support gemfiles.

Parameters:

  • path (String) —

    a gemfile path, with or without the leading gemfiles/

Returns:

  • (Boolean) —

    whether path names one of the ActiveRecord support gemfiles



47
48
49
50
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 47

def support_gemfile?(path)
  normalized = path.to_s.strip.sub(%r{\Agemfiles/}, "")
  VARIANTS.keys.any? { |variant| variant.delete_prefix("gemfiles/") == normalized }
end

Instance Method Details

#build_content(variant) ⇒ String

Parameters:

  • variant (Hash[Symbol, untyped])

Returns:

  • (String)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 87

def build_content(variant)
  sqlite3 = [%("sqlite3"), *variant.fetch(:sqlite3).map(&:inspect), "platforms: [:ruby]"].join(", ")
  <<~GEMFILE
    # frozen_string_literal: true

    #{GENERATED_HEADER}
    # Database drivers for #{variant.fetch(:label)}: sqlite3 on MRI/TruffleRuby,
    # activerecord-jdbcsqlite3-adapter on JRuby (its release series tracks ActiveRecord).
    gem #{sqlite3}

    platforms :jruby do
      gem "activerecord-jdbcsqlite3-adapter", ">= 1.3"
      gem "bigdecimal", ">= 1"
    end
  GEMFILE
end

#eval_path_for(activerecord_version) ⇒ String

Returns the matching support gemfile, relative to gemfiles/ (for eval_gemfile).

Parameters:

  • activerecord_version (String, Gem::Version) —

    the entry's ActiveRecord version

Returns:

  • (String) —

    the matching support gemfile, relative to gemfiles/ (for eval_gemfile)



80
81
82
83
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 80

def eval_path_for(activerecord_version)
  path = (Gem::Version.new(activerecord_version.to_s) >= MODERN_ACTIVERECORD) ? MODERN_PATH : LEGACY_PATH
  path.delete_prefix("gemfiles/")
end

#generate ⇒ Hash{String => Symbol}

Writes both support gemfiles, skipping any hand-maintained file.

Returns:

  • (Hash{String => Symbol}) —

    relative path => :written or :kept



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 64

def generate
  VARIANTS.each_with_object({}) do |(relative_path, variant), results|
    absolute = File.join(base_dir, relative_path)
    if File.exist?(absolute) && !File.read(absolute).include?(GENERATED_HEADER)
      results[relative_path] = :kept
      next
    end

    FileUtils.mkdir_p(File.dirname(absolute))
    File.write(absolute, build_content(variant))
    results[relative_path] = :written
  end
end