Programmatic content
v0.14.0+
Generate content programmatically from data sources instead of creating files manually. Define a template once and Perron creates resources for every combination of your data. Perfect for programmatic SEO where you need similar pages with different data.
Basic Usage
First create your data files:
# app/content/data/products.csv
id,name,price
1,iPhone,999
2,iPad,799
// app/content/data/countries.json
[
{"id": "de", "name": "Germany"},
{"id": "nl", "name": "The Netherlands"}
]
Then define data sources in your resource class:
# app/models/content/product.rb
class Content::Product < Perron::Resource
sources :countries, :products
def self.source_template(sources)
<<~TEMPLATE
---
title: #{sources.products.name} in #{sources.countries.name}
country_id: #{sources.countries.id}
product_id: #{sources.products.id}
---
# #{sources.products.name}
Available in #{sources.countries.name} for $#{sources.products.price}.
TEMPLATE
end
end
Generate resources:
bin/rails perron:sync_sources
This creates four files in app/content/products/:
1-de.erb1-nl.erb2-de.erb2-nl.erb
Each file is processed like any regular resource with full access to layouts, helpers and routing.
Custom primary keys
By default, Perron uses id to identify records. Use the primary_key option to specify a different column:
class Content::Product < Perron::Resource
sources :countries, products: { primary_key: :code }
def self.source_template(sources)
<<~TEMPLATE
---
title: #{sources.products.name}
country_id: #{sources.countries.id}
product_code: #{sources.products.code}
---
TEMPLATE
end
end
Filenames use the specified primary keys: us-iphone-15.erb
Single source
Use source (singular) for a single data source:
class Content::City < Perron::Resource
source :cities
def self.source_template(sources)
<<~TEMPLATE
---
title: #{sources.cities.name}
city_id: #{sources.cities.id}
---
TEMPLATE
end
end
Syncing
Sync all source-backed resources:
bin/rails perron:sync_sources
Sync a specific resource:
bin/rails "perron:sync_sources[products]"
In zsh, quote the task name:
bin/rails "perron:sync_sources[products]"
Integrate with your build process:
bin/rails perron:sync_sources && bin/rails perron:build
Run the sync task whenever your data changes to regenerate affected resources.
On this page