diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d83f5..da7b6fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,6 +46,7 @@ jobs: matrix: # Every Ruby the core team still maintains (https://endoflife.date/ruby); the -head ones are in head. ruby: ["3.3", "3.4", "4.0"] + rails: [{version: "8.1", gemfile: Gemfile}, {version: "8.0", gemfile: gemfiles/rails_8_0.gemfile}] env: BUNDLE_GEMFILE: ${{ matrix.rails.gemfile != 'Gemfile' && matrix.rails.gemfile || '' }} steps: &test-steps diff --git a/.gitignore b/.gitignore index ce5a268..8a8ae32 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /pkg/ *.gem /.claude/settings.local.json +/gemfiles/*.lock diff --git a/Gemfile b/Gemfile index f13d30a..221286d 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gemspec group :development, :test do gem "minitest" + gem "railties" # test/rails boots an application on it gem "rake" gem "rubocop-performance", require: false gem "standard", require: false diff --git a/README.md b/README.md index 9434786..8fab19e 100644 --- a/README.md +++ b/README.md @@ -128,8 +128,15 @@ barcode "0123456789012", type: :ean13, width: 120, height: 40, text: true data_matrix "alice@example.com", size: 40 ``` -Loading font and SVG support once, before a server such as Puma or Unicorn forks its workers, so they share it in -memory: +Rails, 8.0 and later, with nothing to configure: controllers render PDFs, `.pdf.rb` templates draw them with the +view's helpers and translations, and Gamba loads before the server forks when the application eager loads: + +```ruby +render pdf: InvoiceDocument.new(@invoice), filename: "invoice.pdf" # anything answering to_pdf, or a document +``` + +Outside Rails, loading font and SVG support once, before a server such as Puma or Unicorn forks its workers, so they +share it in memory: ```ruby Gamba.eager_load! diff --git a/Rakefile b/Rakefile index 6a0d7f8..efe6134 100644 --- a/Rakefile +++ b/Rakefile @@ -6,6 +6,13 @@ Rake::TestTask.new(:test) do |task| task.libs << "lib" << "test" task.test_files = FileList["test/*_test.rb"] end + +# Rails in a process of its own: its core extensions would otherwise change the Ruby the other tests run on. +Rake::TestTask.new("test:rails") do |task| + task.libs << "lib" << "test" + task.test_files = FileList["test/rails/*_test.rb"] +end +task test: "test:rails" task default: :test namespace :corpus do diff --git a/docs/guide.html b/docs/guide.html index b095be7..c54a427 100644 --- a/docs/guide.html +++ b/docs/guide.html @@ -45,6 +45,7 @@
In a Rails application, 8.0 or later, Gamba needs no configuration. A controller renders a document, an object of the application answering to_pdf, or a PDF’s bytes; the response is application/pdf, shown in the browser unless disposition: :attachment, and the filename is encoded for any language:
def show
+ render pdf: InvoiceDocument.new(@invoice), filename: "Facture #{@invoice.number}.pdf"
+end
+ Teams that prefer views write show.pdf.rb templates. The code runs in the view, with helpers and translations at hand, and draws on document, a Gamba::Document; Prawn’s API is at document.prawn. A template that ends with a document of its own, Gamba’s or Prawn’s, renders that one.
# app/views/invoices/show.pdf.rb
+document.text t(".title", number: @invoice.number), size: 18
+document.table @invoice.lines, columns: {description: {}, amount: {align: :right}}
+document.text number_to_currency(@invoice.total)
+ Active Storage attachments go straight to image and pdf_page, without a temporary file: anything that answers download is read that way. When the application eager loads, as in production, Gamba loads with it, before the server forks its workers.
TrueType and SVG support load on first use, so a document of standard fonts never pays for them. Before a server forks its workers, load them once, so every worker shares that memory instead of loading its own copy:
-# config/puma.rb, before_fork, or an initializer
+# outside Rails: config/puma.rb, before_fork, or an initializer
Gamba.eager_load!