Class: Kettle::Jem::Appraisals::ActiveRecordSupportGemfileGenerator
- Inherits:
-
Object
- Object
- Kettle::Jem::Appraisals::ActiveRecordSupportGemfileGenerator
- 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.
The sqlite3 requirement comes from Kettle::Rb::GemDependencies, which
records what each ActiveRecord series' sqlite3 adapter declares. One
support gemfile is written per run of consecutive ActiveRecord series
sharing a requirement, named after the oldest series in the run
(+gemfiles/modular/activerecord_support/v6.0.gemfile+ covers 6.0–7.0).
ActiveRecord newer than the recorded series uses the newest run.
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.
Constant Summary collapse
- GENERATED_HEADER =
Returns header marking a support gemfile as generated (and safe to regenerate).
"# Generated by kettle-jem-appraisals"- SUPPORT_DIR =
Returns directory holding the support gemfiles.
"gemfiles/modular/activerecord_support"- UNKNOWN_PATH =
Returns support gemfile for ActiveRecord older than every recorded series.
"#{SUPPORT_DIR}/unknown.gemfile"- LEGACY_PATHS =
Returns support gemfiles written by kettle-jem-appraisals 0.1.4 and earlier.
[ "gemfiles/modular/activerecord_support.gemfile", "gemfiles/modular/activerecord_support_modern.gemfile" ].freeze
- LEGACY_PATH =
- MODERN_PATH =
- MODERN_ACTIVERECORD =
- VARIANTS =
Instance Attribute Summary collapse
-
#base_dir ⇒ String
readonly
Absolute path to the project root.
Class Method Summary collapse
-
.support_gemfile?(path) ⇒ Boolean
Whether
pathnames an ActiveRecord support gemfile.
Instance Method Summary collapse
- #build_content(group) ⇒ String
-
#eval_path_for(activerecord_version) ⇒ String
The matching support gemfile, relative to
gemfiles/(foreval_gemfile). -
#generate(activerecord_versions) ⇒ Hash{String => Symbol}
Writes the support gemfile needed by each ActiveRecord version, skipping hand-maintained files, and removes support gemfiles generated by kettle-jem-appraisals 0.1.4 and earlier.
-
#initialize(base_dir: Dir.pwd) ⇒ ActiveRecordSupportGemfileGenerator
constructor
A new instance of ActiveRecordSupportGemfileGenerator.
-
#sqlite3_requirements(activerecord_version) ⇒ Array<String>
The sqlite3 requirements for that ActiveRecord version.
-
#unfixed_sqlite3_advisories(activerecord_version) ⇒ Array<String>
Advisories that affect every sqlite3 series the requirements allow.
Constructor Details
#initialize(base_dir: Dir.pwd) ⇒ ActiveRecordSupportGemfileGenerator
Returns a new instance of ActiveRecordSupportGemfileGenerator.
62 63 64 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 62 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.
59 60 61 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 59 def base_dir @base_dir end |
Class Method Details
.support_gemfile?(path) ⇒ Boolean
Returns whether path names an ActiveRecord support gemfile.
50 51 52 53 54 55 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 50 def support_gemfile?(path) normalized = path.to_s.strip.sub(%r{\Agemfiles/}, "") return true if normalized.start_with?("#{SUPPORT_DIR.delete_prefix("gemfiles/")}/") LEGACY_PATHS.any? { |legacy| legacy.delete_prefix("gemfiles/") == normalized } end |
Instance Method Details
#build_content(group) ⇒ String
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 166 def build_content(group) requirements = group ? group.first.requirements : [] sqlite3 = [%("sqlite3"), *requirements.map(&:inspect), "platforms: [:ruby]"].join(", ") notes = [] notes << "# sqlite3 requirement from kettle-rb: #{group.last.source}" if group unfixed = group ? unfixed_sqlite3_advisories(group.first.series) : [] notes << "# kettle-rb: no sqlite3 release allowed here fixes #{unfixed.join(", ")}" unless unfixed.empty? " # frozen_string_literal: true\n\n \#{GENERATED_HEADER}\n # Database drivers for \#{label(group)}: sqlite3 on MRI/TruffleRuby,\n # activerecord-jdbcsqlite3-adapter on JRuby (its release series tracks ActiveRecord).\n \#{notes.join(\"\\n\")}\n gem \#{sqlite3}\n\n platforms :jruby do\n gem \"activerecord-jdbcsqlite3-adapter\", \">= 1.3\"\n gem \"bigdecimal\", \">= 1\"\n end\n GEMFILE\nend\n" |
#eval_path_for(activerecord_version) ⇒ String
Returns the matching support gemfile, relative to gemfiles/ (for eval_gemfile).
99 100 101 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 99 def eval_path_for(activerecord_version) path_for(group_for(activerecord_version)).delete_prefix("gemfiles/") end |
#generate(activerecord_versions) ⇒ Hash{String => Symbol}
Writes the support gemfile needed by each ActiveRecord version, skipping hand-maintained files, and removes support gemfiles generated by kettle-jem-appraisals 0.1.4 and earlier.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 72 def generate(activerecord_versions) results = {} activerecord_versions.map { |version| group_for(version) }.uniq.each do |group| relative_path = path_for(group) absolute = File.join(base_dir, relative_path) if hand_maintained?(absolute) results[relative_path] = :kept next end FileUtils.mkdir_p(File.dirname(absolute)) File.write(absolute, build_content(group)) results[relative_path] = :written end LEGACY_PATHS.each do |relative_path| absolute = File.join(base_dir, relative_path) next unless File.exist?(absolute) && !hand_maintained?(absolute) FileUtils.rm_f(absolute) results[relative_path] = :removed end results end |
#sqlite3_requirements(activerecord_version) ⇒ Array<String>
Returns the sqlite3 requirements for that ActiveRecord version.
105 106 107 108 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 105 def sqlite3_requirements(activerecord_version) group = group_for(activerecord_version) group ? group.first.requirements : [] end |
#unfixed_sqlite3_advisories(activerecord_version) ⇒ Array<String>
Advisories that affect every sqlite3 series the requirements allow.
114 115 116 117 118 119 120 121 122 |
# File 'lib/kettle/jem/appraisals/active_record_support_gemfile_generator.rb', line 114 def unfixed_sqlite3_advisories(activerecord_version) requirement = Gem::Requirement.new(*sqlite3_requirements(activerecord_version)) allowed = Kettle::Rb::GemFloors.entries_for("sqlite3").select { |entry| requirement.satisfied_by?(Gem::Version.new(entry.floor)) } return [] if allowed.empty? || allowed.any? { |entry| entry.unpatched_advisories.empty? } allowed.flat_map(&:unpatched_advisories).uniq.sort end |