3

The goal is for command...

bin/rails generate custom_scaffold Thing

... to generate the following 6 files:

db/migrate/201812031331_create_things.rb
app/models/thing.rb
app/controllers/things_controller.rb
app/serializers/thing_serializer.rb
test/fixtures/things.yml
test/integration/requests/things_request_test.rb

... using Rails 5.

My current setup does generate app/models/thing.rb but does not populate it with Thing.

Expected:

class Thing < ApplicationRecord

end

Currently:

class <%= class_name %> < ApplicationRecord

end

I have read through these Rails guides but to little avail.

Does anyone have a working example?


My setup:

# lib/generators/custom_scaffold/custom_scaffold_generator.rb

class CustomScaffoldGenerator < Rails::Generators::NamedBase
  source_root File.expand_path('templates', __dir__)

  def create_files
    copy_file 'migration.rb', "db/migrate/#{timestamp}_create_#{plural_name}.rb"
    copy_file 'model.rb', "app/models/#{file_name}.rb"
    copy_file 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
    copy_file 'serializer.rb', "app/serializers/#{file_name}_serializer.rb"
    copy_file 'fixture.yml', "test/fixtures/#{plural_name}.yml"
    copy_file 'request_test.rb', "test/integration/requests/#{plural_name}_request_test.rb"
  end

  private

  def timestamp
    Time.now.utc.strftime('%Y%m%d%H%M%S')
  end
end
# lib/generators/custom_scaffold/templates/model.rb

class <%= class_name %> < ApplicationRecord

end
# lib/generators/custom_scaffold/templates/controller.rb

module V1
  module Public
    class <%= class_name.pluralize %>Controller < ApplicationController

    end
  end
end
# lib/generators/custom_scaffold/templates/migration.rb
# Ignore for now
# lib/generators/custom_scaffold/templates/serializer.rb
# Ignore for now
# lib/generators/custom_scaffold/templates/fixture.yml
# Ignore for now
# lib/generators/custom_scaffold/templates/request_test.rb
# Ignore for now
# Gemfile

source 'https://rubygems.org'

ruby '2.4.1'
gem 'rails', '~> 5.1.6'
gem 'puma', '~> 3.7'
gem 'pg'
gem 'rack-cors', require: 'rack/cors'
gem 'olive_branch'
gem 'fast_jsonapi'
gem 'awesome_print'
gem 'byebug', '~> 10.0', groups: %i[development test]
gem 'yaml_db'

group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'mina', '~> 1.2', require: false
  gem 'mina-puma', require: false
  gem 'rubocop', require: false
  gem 'annotate', require: false
end
Jan Werkhoven
  • 2,656
  • 1
  • 22
  • 31

1 Answers1

3

You need to specify the file as a Thor template. Rails uses Thor templates for generating templates with ERB style code inside them.

Replace:
copy_file 'model.rb', "app/models/#{file_name}.rb"

With:
template 'model.rb.tt', "app/models/#{file_name}.rb"

By adding the .tt extension you're telling the generator to handle the file as a Thor template, which will interpret the Ruby code (ERB style) inside the file and then create a file with that same name minus the .tt extension. Any file you have without the .tt extension the generator will copy wholesale, without executing any of the code inside.

A useful tip: Sometimes you want to leave some ERB code inside a Thor template file without it being executed. By default any ERB style tags inside a .tt file will be process and in it's place a string will be written to the output file. You can avoid the processing of ERB tags but using a double percent sign in the tag.

For example, lets say you have a file named foo.erb.tt, which will create the file foo.erb when your generator runs. Let's also say we have a article_name variable and it's value is Breaking News

If you put <%= article_name %> in the file it will write Breaking News to the foo.erb.

If you put <%%= article_name %> (notice the %%) it will write <%= article_name %>to the foo.erb.

I found the following reference handy when learning this stuff.

Thor comes with several actions that help with script and generator tasks. You might be familiar with them since some came from Rails Templates. They are: say, ask, yes?, no?, add_file, remove_file, copy_file, template, directory, inside, run, inject_into_file and a couple more.

Greg Hemphill
  • 295
  • 4
  • 7