首页 > 解决方案 > Ruby Gem 项目——雷神生成器导致只读文件系统错误

问题描述

作为一个个人项目,我决定编写一个缩小版的 Ruby on Rails,并使用名为railz_lite.

在我的项目中,我希望实现一个类似于 的生成器rails new,它将为 Web 应用程序创建必要的文件夹,即控制器/、视图/、模型/等。

为此,我将 Thor 作为依赖项包含在内,然后创建了以下文件:

require 'thor/group'

module RailzLite
  module Generators
    class Project < Thor::Group
      include Thor::Actions
      
      def self.source_root
        File.dirname(__FILE__) + "/templates"
      end
      
      def add_controllers
        empty_directory("controllers")
      end

      def add_models
        empty_directory("models")
      end

      def add_server
        template("server.rb", "config/server.rb")
      end

      def add_views
        empty_directory("views")
      end

      def add_public
        empty_directory("public")
      end
    end
  end
end

在 gem 项目的根文件夹中,当我运行时bundle exec railz_lite new,生成器工作正常并创建了必要的文件。

但是,如果我创建一个新项目,将我的 gem (railz_lite) 放入 Gemfile,运行 bundle install,然后执行bundle exec rails_lite new,我会收到以下错误:

.rbenv/versions/2.5.1/lib/ruby/2.5.0/fileutils.rb:232:in `mkdir':
: Read-only file system @ dir_s_mkdir - /controllers (Errno::EROFS)

我怀疑这个错误是因为该empty_directory命令没有引用我刚刚创建的项目的根目录。我希望有一个简单的方法来解决这个问题。

为了进一步参考,CLI 脚本和类如下所示:

railz_lite

#!/usr/bin/env ruby
require 'railz_lite/cli'

RailzLite::CLI.start

cli.rb

require 'thor'
require 'railz_lite'
require 'railz_lite/generators/project'

module RailzLite
  class CLI < Thor
    desc 'new', 'Generates a new RailzLite project'
    def new
      RailzLite::Generators::Project.start([])
    end
  end
end

任何解决方案将不胜感激!

注意:我在 macOS Catalina 上运行它。

标签: ruby-on-railsrubyrubygems

解决方案


因此,在通过 gem 论坛广泛搜索并查看 Rails 源代码后,我找到了一个解决方案。

在生成内部,我必须手动将destination_root 设置为项目的工作目录。工作目录可以通过Dir.pwd

require 'thor/group'

module RailzLite
  module Generators
    class Project < Thor::Group
      include Thor::Actions
      
      def self.source_root
        File.dirname(__FILE__) + "/templates"
      end

      def self.destination_root # this method fixes the problem!
        Dir.pwd # get the current project directory
      end
      
      def add_controllers
        empty_directory("controllers")
      end

      def add_models
        empty_directory("models")
      end

      def add_server
        template("server.rb", "config/server.rb")
      end

      def add_views
        empty_directory("views")
      end

      def add_public
        empty_directory("public")
      end
    end
  end
end

推荐阅读