【问题标题】:How to call Jekyll commands from Ruby如何从 Ruby 调用 Jekyll 命令
【发布时间】:2026-01-20 02:15:02
【问题描述】:

我有一个 Rails 应用程序,它可以在同一台服务器上创建/构建一些 Jekyll 站点。现在,我用这样的反引号调用 Jekyll 命令:

def build_jekyll
  result = `jekyll build -s /some/source/path -d /some/dest/path`
end

这很好用,但感觉有点不像红宝石。如果 jekyll gem 在我的 Rails Gemfile 中,有没有办法可以使用 ruby​​ 构建 jekyll 站点?

(从文档看来,我会调用Jekyll::Commands::Build.build,但我不确定如何初始化站点参数)。

【问题讨论】:

    标签: ruby-on-rails ruby jekyll


    【解决方案1】:

    TL;DR

    require 'jekyll'
    
    conf = Jekyll.configuration({
      'source'      => 'path/to/source',
      'destination' => 'path/to/destination'
    })
    
    Jekyll::Site.new(conf).process
    

    但是你是怎么发现的?

    我通过查看the source code 发现了这一点。当您运行jekyll build 时,您将进入源文件bin/jekyll。这里有趣的部分是

    command :build do |c|
      # ommitted
    
      c.action do |args, options|
        options = normalize_options(options.__hash__)
        options = Jekyll.configuration(options)
        Jekyll::Commands::Build.process(options)
      end
    end
    

    嗯,看起来实际工作是在Jekyll::Commands::Build.process中完成的,那么我们来看看lib/jekyll/commands/build.rb中的那个方法:

    def self.process(options)
      site = Jekyll::Site.new(options)
      self.build(site, options)
    
      # other stuff
    end
    

    再一次,真正的魔法发生在其他地方,即在Jekyll::Commands::Build.build,也在lib/jekyll/commands/build.rb

    def self.build(site, options)
      # some logging going on here
    
      self.process_site(site)
    end
    

    这又调用了一个名为process_site的类方法,它来自lib/jekyll/command.rb中定义的超类Jekyll::Command

    def self.process_site(site)
      site.process
    rescue Jekyll::FatalException => e
      # some error handling
    end
    

    所以我们实际上想在Jekyll::Site 上调用process。我们还没有弄清楚的一件事是如何为Jekyll::Site 实例指定选项。让我们仔细看看lib/jekyll/site.rb

    def initialize(config)
      # more options ...
    
      self.source          = File.expand_path(config['source'])
      self.dest            = File.expand_path(config['destination'])
    
      # more options ...
    end
    

    所以显然我们需要提供一个带有指向所需目录的'source''destination' 键的哈希。 Jekyll 将使用我们之前在bin/jekyll 中看到的Jekyll.configuration 方法生成其余配置。就是这样。现在,唯一剩下要做的就是将各个部分放在一起;-)

    【讨论】:

    【解决方案2】:

    更新这个,因为它看起来语法改变了,现在可以工作了

    require "jekyll"
    
    options = {
        "source"      => './',
        "destination" => './_site',
        "watch" => true,
        "verbose" => true
      }
    
    Jekyll::Commands::Build.process(options)
    

    【讨论】: