How to change source for a custom rails generator? (Thor)

偶尔善良 提交于 2019-12-13 15:53:30

问题


I'm making a custom generator that generates a new rails app, and I do it like this

require 'thor'
require 'rails/generators/rails/app/app_generator'

class AppBuilder < Rails::AppBuilder
  include Thor::Actions
  include Thor::Shell
  ...
end

The problem is, how do I add a new source directory (which is then used by Thor::Actions#copy_file, Thor::Actions#template, and the others)? I saw in the Thor's documentation that Thor::Actions#source_paths holds the sources (it's an array of paths), so I tried overriding it inside my class (since I've included Thor::Actions):

def source_paths
  [File.join(File.expand_path(File.dirname(__FILE__)), "templates")] + super
end

With this I wanted to add the ./templates directory in the sources, while still keeping the Rails' one (that's why the + super at the end). But it doesn't work, it still lists the Rails' source path as the only one.

I tried browsing through the Rails' source code, but I couldn't find how Rails put his directory in the source paths. And I really want to know that :)


回答1:


This worked:

require 'thor'
require 'rails/generators/rails/app/app_generator'

module Thor::Actions
  def source_paths
    [MY_TEMPLATES]
  end
end

class AppBuilder < Rails::AppBuilder
  ...
end

I don't understand why, but I've spent too much time on this already, so I don't care.




回答2:


Thor will access your source_paths method and add these to the defaults:

  # Returns the source paths in the following order:
  #
  #   1) This class source paths
  #   2) Source root
  #   3) Parents source paths
  #
  def source_paths_for_search
    paths = []
    paths += self.source_paths
    paths << self.source_root if self.source_root
    paths += from_superclass(:source_paths, [])
    paths
  end

So all you need to do in your class is:

class NewgemGenerator < Thor::Group

  include Thor::Actions

  def source_paths
    ['/whatever', './templates']
  end

end

Hope this helps :)




回答3:


The source_paths method doesn't work when using AppBuilder. (which is another option to using rails templates). I have a files directory next to the app_builder.rb file that this class is in. I have this working, though it seems there should still be a more elegant way.

tree .
|-- app_builder.rb
|-- files
     `-- Gemfile
class AppBuilder < Rails::AppBuilder

  def initialize generator
    super generator
    path = File.expand_path( File.join( '..', File.dirname( __FILE__ )) )
    source_paths << path
  end

  def gemfile
    copy_file 'files/Gemfile', 'Gemfile'
  end

and then on the console:

rails new my_app -b path_to_app_builder.rb

The dots are required since the ruby file 'app_builder.rb' is slurped up and eval'd after the rails new command changes into the new app directory (I think).




回答4:


It's an old post, however, the problem remains the same, I spent time to figure that out. I let a comment here if it can help.

Rails add by default the path lib/templates so you can custom any templates by copying them in this directory.

Check out the correct directories structures https://github.com/rails/rails/tree/v6.0.1/railties/lib/rails/generators/rails

There is subtle though and is not so obvious to catch.

Take for instance the helper generator, as mentioned in the official Rails documentation, the structure is

https://github.com/rails/rails/tree/v6.0.1/railties/lib/rails/generators/rails/helper

- helper
  - templates
    - helper.rb.tt
  - helper_generator.rb 

Here, what Railties expects to find in your project:

- lib
  - templates 
    - helper
      - helper.rb

your helper.rb is a copy of helper.rb.tt

the last thing, if you plan to use it in Rails::Engine you have to tell it to load that path

# lib/blorgh/engine.rb 
module Blorgh
  class Engine < ::Rails::Engine
    isolate_namespace Blorgh
    config.generators.templates << File.expand_path('../templates', __dir__)
  end
end

Really hope that can help and save time for others.

  1. https://github.com/rails/rails/blob/v6.0.1/railties/lib/rails/application/configuration.rb#L188
  2. https://guides.rubyonrails.org/generators.html#customizing-your-workflow-by-changing-generators-templates
  3. https://github.com/rails/rails/blob/v6.0.1/railties/CHANGELOG.md
  4. https://guides.rubyonrails.org/engines.html


来源:https://stackoverflow.com/questions/9879891/how-to-change-source-for-a-custom-rails-generator-thor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!