Skip to content

Sources procs + class support#173

Merged
eelcoj merged 2 commits intomainfrom
sources-procs
Mar 23, 2026
Merged

Sources procs + class support#173
eelcoj merged 2 commits intomainfrom
sources-procs

Conversation

@eelcoj
Copy link
Copy Markdown
Contributor

@eelcoj eelcoj commented Mar 23, 2026

This extends the sources/programmatic content feature.

First off lamda filtering for sources, like so:

class Content::Product
  sources, :countries, products: -> (products) { products.select(&:featured?) }
end

Then support for class for sources, for which pulling data from external APIs is the most obvious use case. This has been on my list since I first launched Perron. 😊

Initially I thought of adding first-party support for API handling. But instead I opted for a more maintainable and flexible option of simply support adding a class to the sources feature. This is as simple as it is elegant (at least I think it is).

Syntax looks like this:

class Content::Product
  sources repos: { class: GitHubRepo, primary_key: :name }
end

A complete example implementation that pulls GitHub repositories data could look like this (using the Active Resource gem):

class GitHubRepo < ActiveResource::Base
  self.site = "https://api.github.com/"

  def self.all
    find(:all, from: "/users/Rails-Designer/repos", params: { per_page: 5 })
  end
end

Then the typical template setup:

class Content::Project < Perron::Resource
  sources repos: { class: GitHubRepo, primary_key: :name }

  def self.source_template(source)
    <<~TEMPLATE
    ---
    title: #{source.repos.name}
    description: #{source.repos.description}
    language: #{source.repos.language}
    stars: #{source.repos.stargazers_count}
    ---

    #{source.repos.description}
    TEMPLATE
  end
end

Above would pull the repo data and create (and update if changes) erb files into app/content/projects just like it does with local files. ✨

This extends the sources/[programmatic content](https://perron.railsdesigner.com/docs/programmatic-content-creation/) feature

First off lamda filtering for sources, like so:
```ruby
class Content::Product
  sources, :countries, products: -> (products) { products.select(&:featured?) }
end
```

Then pulling data from external APIs. This has been on my list almost since I first launched Perron. 😊 Initially I thought of adding first-party support for API handling. But instead I opted for a more maintainable and flexible option of simply support adding a class to the sources feature. This is as simple as it is elegant (at least I think it is).

Syntax looks like this:
```ruby
class Content::Product
  sources repos: { class: GitHubRepo, primary_key: :name }
end
```

More complete example implementation that pulls GitHub repositories (using the [Active
Resource gem](https://github.com/rails/activeresource):
```ruby
class GitHubRepo < ActiveResource::Base
  self.site = "https://api.github.com/"

  def self.all
    find(:all, from: "/users/Rails-Designer/repos", params: { per_page: 5 })
  end
end

Then the typical template setup:
```ruby
class Content::Project < Perron::Resource
  sources repos: {
    class: GitHubRepo,
    primary_key: :name
  }

  def self.source_template(sources)
    <<~TEMPLATE
    ---
    title: #{sources.repos.name}
    description: #{sources.repos.description}
    language: #{sources.repos.language}
    stars: #{sources.repos.stargazers_count}
    ---

    #{sources.repos.description}
    TEMPLATE
  end
end
```

Above would pull the repo data and create (and update if changes) erb
files into `app/content/projects` just like it does with local files. ✨
I think this reads better instead of `sources.products`:
```
class Content::Product < Perron::Resource
  sources :countries, :products

  def self.source_template(source)
    <<~TEMPLATE
    ---
    product_code: #{source.products.code}
    country_id: #{source.countries.id}
    title: #{source.products.name} in #{source.countries.name}
    slug: #{source.products.slug}-#{source.countries.code.downcase}
    ---

  # …
end
```

Aliased to `sources` so you could still use if you like that syntax
better.
@eelcoj eelcoj changed the title Sources procs Sources procs + class support Mar 23, 2026
@eelcoj eelcoj merged commit a1e20fc into main Mar 23, 2026
3 checks passed
@eelcoj eelcoj deleted the sources-procs branch March 23, 2026 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant