【问题标题】:How to have the scaffold to generate another partial view template file如何让脚手架生成另一个局部视图模板文件
【发布时间】:2011-06-09 11:27:53
【问题描述】:

我正在尝试自定义我的脚手架生成器,并且我想在同一目录中为视图创建一个新的partial,尤其是_item被称为 inside index 和 show。我可以获取所有模板,但我无法通过

生成此文件
rails g scaffold foo name:string

我尝试将 _item.erb 放入 /lib/templates/erb/scaffold/(与其他文件一起),但它被忽略了 - 有人知道吗?

我在 rails 3 上使用 ruby​​,但请让我知道该解决方案是否也适用于 rails 2。 我也使用 simple_form(因此我已经有了 _form 部分),但我认为即使没有它,解决方案也应该是有效的。

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3 customization scaffold


【解决方案1】:

我遇到了这个问题,希望能找到答案,因为如果你想的话,默认的 rails 脚手架生成器已经很残废了:

  1. 重构脚手架视图或使用局部视图
  2. 使用控制器和视图继承
  3. 支持其他控制器操作及其视图
  4. 支持混合模板引擎、erb、haml、slim、jbuilder、prawn 等

唉,我卷起袖子,想出了如何让 rails 脚手架生成器支持我在当前项目中使用的上述要求。

如果您想在键入 rails g scaffold Foo ... 时完全控制您的脚手架模板,请继续阅读!

问题

默认的 rails 脚手架生成器是特定于模板引擎的,并且硬编码了一组它查找的固定视图文件。

解决方案

使用自定义生成器并将其连接到脚手架模板生成。

我在下面包含了一个生成器,它在lib/templates/scaffold 中查找,并将为在那里找到的所有文件生成脚手架视图,包括模板、部分和子目录,无论模板引擎如何。

IMO 这应该是默认的 rails 行为,而不是我们必须像这样跳过箍..

实施

执行以下操作:

  1. 将您在搭建脚手架时想要创建的任何模板或部分放入lib/templates/scaffold。注意没有erb 子目录!!
  2. 为您的项目配置生成器模板引擎,如下所示
  3. 添加我的自定义视图生成器(包含在下面)

Rails 4 生成器配置:

# config/initializers/generators.rb
Rails.application.config.generators do |g|
  # ...
  g.template_engine :all
  g.fallbacks[:all] = :erb # or haml/slim etc
end

Rails 3 生成器配置:

# config/application.rb
config.generators do |g|
  # ...
  g.template_engine :all
  g.fallbacks[:all] = :erb # or haml/slim etc
end

自定义脚手架生成器:

# lib/generators/all/scaffold/scaffold_generator.rb
require 'rails/generators/named_base'
require 'rails/generators/resource_helpers'

module All # :nodoc:
  module Generators # :nodoc:
    class ScaffoldGenerator < Rails::Generators::NamedBase # :nodoc:
      include Rails::Generators::ResourceHelpers

      source_root File.join(Rails.root, 'lib', 'templates', 'scaffold', File::SEPARATOR)

      argument :attributes, type: :array, default: [], banner: "field:type field:type"

      def create_root_folder
        empty_directory File.join("app/views", controller_file_path)
      end

      def copy_view_files
        available_views.each do |view|
          template view, File.join("app/views", controller_file_path, view)
        end
      end

    protected
      def available_views
        # use all template files contained in source_root ie 'lib/templates/scaffold/**/*'
        base = self.class.source_root
        base_len = base.length
        Dir[File.join(base, '**', '*')].select { |f| File.file?(f) }.map{|f| f[base_len..-1]}
      end
    end
  end
end

注意事项

不提供保修:)

我希望这可以帮助其他想要使用部分重构其脚手架视图并支持多个模板引擎的人。

【讨论】:

  • 我们不能只 monkey patch ScaffoldGenerator 类吗?
  • @RSK。上面的生成器是一个猴子补丁,它用一个有用的替代了脚手架生成器类。因为这不仅仅是覆盖原始类中的一个或两个函数(注意类定义中的source_rootargument 调用,它们在原始类中以不同的方式完成,从那时起有效地损坏了原始类)。在这种情况下,完整的类替换更简洁。
  • 这里我们定义了所有新的All模板引擎对吧?为什么我们不能修补Erb::Generators::ScaffoldGenerator中的available_views方法
  • @RSK 看看我上面的代码,它显然不仅仅是覆盖单个方法。如果您无法阅读完整的类定义并看到需要定义其他必需的方法,以便它按照我描述的方式工作并且类级别的方法调用(需要调用 source_root 和参数)加上我之前对您的解释以上我真的帮不了你。如果您认为您有一个可以工作的班轮,请发布答案。我知道上面的代码有效并且做了我所描述的。你的一个班轮会影响发电机,但不会像我描述的那样。
  • 这在 Rails 5 中仍然为我工作,非常感谢这个!
【解决方案2】:

刚刚找到。

它是硬编码的。你可以改变它:

https://github.com/rails/rails/blob/master/railties/lib/rails/generators/erb/scaffold/scaffold_generator.rb

  def available_views
    %w(index edit show new _form)
  end

在我的索引模板中,我这样做了:

        <thead id="thead_js">
        <%%= render 'thead' %>

        <!-- CUT TO _thead.html.erb -->
        <tr>
            <% for attribute in attributes -%>
                <th><%%= sortable( <%= attribute.name %>, <%= attribute.human_name %> ) %></th>
            <% end %>
            <th>&nbsp;</th>
        </tr>
        <!-- END CUT TO -->

    </thead>

然后,刚刚创建了一个读取该评论并创建新文件的 rake 任务。

丑陋但有效。

【讨论】:

  • 非常感谢!我一定会找到时间以我的方式实施它。
【解决方案3】:

我相信这是硬编码到脚手架 g 中的。我所做的是创建一个添加更多文件的 rake 任务。

【讨论】:

    猜你喜欢
    • 2017-07-29
    • 2017-02-10
    • 1970-01-01
    • 2022-10-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多