Skip to content

Create a "FileSystem" abstraction to allow loading of templates from DB/URLs/etc #38

@timhanus

Description

@timhanus

Summary

The ruby implementation of liquid defines a "FileSystem" interface than can be used to load template files from sources other than the local disk. This allows a developer to (for example) load template files from s3 buckets or a database seamlessly. This feature becomes particularly useful when using include tags.

https://github.com/Shopify/liquid/blob/master/lib/liquid/file_system.rb
https://www.rubydoc.info/gems/liquid/Liquid/BlankFileSystem

I have an unfinished version of this working locally, but wanted to submit this issue for discussion before I got too far down any particular implementation path.

Suggested Implementation

Trying to stay as close as possible to the ruby implementation we define an interface as:

type LiquidFileSystem interface {
    ReadTemplateFile(templatename string) ([]byte, error)
}

The instance of LiquidFileSystem lives in the render.config struct. A basic implementation (and default behavior to provide backwards compatibility) would be a simple wrapper around
ioutil.ReadFile

func (tl *diskFileSystem) ReadTemplateFile(filename string) ([]byte, error) {
    source, err := ioutil.ReadFile(filename)
    return source, err
}

Any custom implementation would be utilized as follows:

type S3FileSystem struct { ...snip... }
func NewS3FileSystem(...) *S3FileSystem { ...snip... }
func (tl *S3FileSystem) ReadTemplateFile(filename string) ([]byte, error) {  ... snip ...}

e := liquid.NewEngine()
fs := NewS3FileSystem(...)
e.RegisterFilesystem(fs)

As yet Unaddressed Issues

  1. Template Error Reporting (currently I believe we just report filename as opposed to a full URL)
  2. Potentially new classes of errors?
  3. Caching. Another github issue addresses caching, but it becomes more important if we are loading templates files from a relatively high latency source.

Next Steps/Suggestions?

If this approach seems generally sane to you and it's a feature you are interested in adding I will finish cleaning up the code and submit a PR. If you have any alternate implementation ideas I'm more than open to incorporating them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions