Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for gem consumer custom templates #39

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ Lint:

Metrics/BlockLength:
Exclude:
- '**/*.gemspec'
- '**/*.rake'
- 'Rakefile'
- 'spec/**/*.rb'
- "**/*.gemspec"
- "**/*.rake"
- "Rakefile"
- "spec/**/*.rb"

RSpec:
Language:
Expand All @@ -48,4 +48,8 @@ RSpec/NestedGroups:

Style/BlockDelimiters:
Exclude:
- 'spec/**/*'
- "spec/**/*"

Style/FrozenStringLiteralComment:
Exclude:
- lib/generators/onesie/templates/template.rb
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added `.DS_Store` to `.gitignore`
- Added support for Rails > 5
- Added support for custom templates

### Changed
- Switch `colorize` gem for `rainbow`
Expand Down
13 changes: 9 additions & 4 deletions doc/how_to_guides/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ be achieved with either the Rails generator or the Rake task
#### API
```
Usage:
rails generate onesie:task NAME PRIORITY [options]
rails generate onesie:task NAME [options]

Options:
[--skip-namespace], [--no-skip-namespace] # Skip namespace (affects only isolated applications)
[--priority] # Specify a priority that the onesie should run as
[--template] # Specify a custom template for generating the onesie
Comment on lines +23 to +24
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timlkelly let me know if this is what you'd expect. I figured since we now accept multiple args, using options is acceptable like this.


Runtime options:
-f, [--force] # Overwrite files that already exist
Expand All @@ -31,22 +33,25 @@ Runtime options:

#### Examples
```bash
bundle exec rails generate onesie:task MyTask # creates a normal priority task
bundle exec rails generate onesie:task MyTask high # creates a high priority task
bundle exec rails generate onesie:task MyTask # creates a normal priority task
bundle exec rails generate onesie:task MyTask --priority high # creates a high priority task
bundle exec rails generate onesie:task MyTask --template SampleTemplate # creates a onesie using a custom template called SampleTemplate
bundle exec rails generate onesie:task MyTask --priority high --template SampleTemplate # creates a onesie specifying both priority and the custom template
```

### Rake

#### API
```bash
rake onesie:new[name,priority] # Generates a new Onesie Task
rake onesie:new[name,priority,template] # Generates a new Onesie Task
```

#### Examples

```bash
bundle exec rake onesie:new['MyTask'] # creates a normal priority task
bundle exec rake onesie:new['MyTask','high'] # creates a high priority task
bundle exec rake onesie:new['MyTask','high','SampleTemplate'] # creates a high priority task using 'SampleTemplate'
```

## Write your Onesie Task
Expand Down
29 changes: 27 additions & 2 deletions lib/generators/onesie/task_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ class TaskGenerator < Rails::Generators::NamedBase
desc 'Generate a new Onesie Task'
source_root File.expand_path('./templates', __dir__)

class_option :priority, type: :string, default: nil
PRIORITY_ARG = 0

class_option :template, type: :string, default: nil
TEMPLATE_ARG = 1

TEMPLATE_FILENAME = 'task.rb'
DEFAULT_TEMPLATE = '# Write your Onesie Task here'

def create_task
template(TEMPLATE_FILENAME, filename, class_name: class_name)
Expand All @@ -21,10 +28,28 @@ def filename
"#{Onesie::Manager.tasks_path}/#{task_version}_#{file_name}#{task_priority}.rb"
end

def run_contents
read_template || DEFAULT_TEMPLATE
end

def read_template
return unless custom_template

Onesie::TemplateReader.read_template(custom_template_path)
end

def custom_template_path
Rails.root.join('onesie', 'templates', "#{custom_template.underscore}.rb")
end

def task_priority
return unless args[0]
return unless (priority = options.priority || args[PRIORITY_ARG])

".#{priority}"
end

".#{args[0]}"
def custom_template
options.template || args[TEMPLATE_ARG]
end

def task_version
Expand Down
25 changes: 25 additions & 0 deletions lib/generators/onesie/template_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require 'rails/generators/named_base'

module Onesie
module Generators
# Generates a new Onesie template
class TemplateGenerator < Rails::Generators::NamedBase
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add documentation in the how_to_guides/usage.md about this generator please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can do!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timlkelly Done!

desc 'Generate a new Onesie template'
source_root File.expand_path('./templates', __dir__)

TEMPLATE_FILENAME = 'template.rb'

def create_template
template(TEMPLATE_FILENAME, filename)
end

private

def filename
"onesie/templates/#{file_name}.rb"
end
end
end
end
2 changes: 1 addition & 1 deletion lib/generators/onesie/templates/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class <%= class_name %> < Onesie::Task
manual_task enabled: false

def run
# Write your Onesie Task here
<%= run_contents.chomp.indent(8) %>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this line not work if it is intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see a template in which consumers of the gem do not want the output to be formatted properly?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it should be formatted correctly. I was wondering why it was required to call the .indent method. I'm assuming it has to do with the template parsing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if required is the right term here. From a formatting perspective, if we don't include the indent, a onesie generated via template will appear as:

# frozen_string_literal: true
module Onesie
  module Tasks
    class <%= class_name %> < Onesie::Task
      allowed_environments :all
      manual_task enabled: false
      def run
template here      
      end
    end
  end
end

Which will either make engineer's eyes twitch (or rubocop 😂 )

end
end
end
Expand Down
1 change: 1 addition & 0 deletions lib/generators/onesie/templates/template.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Write the contents of Onesie::Tasks#run here!
1 change: 1 addition & 0 deletions lib/onesie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require_relative 'onesie/task_proxy'
require_relative 'onesie/task_record'
require_relative 'onesie/task_wrapper'
require_relative 'onesie/template_reader'
require_relative 'onesie/version'

module Onesie
Expand Down
15 changes: 13 additions & 2 deletions lib/onesie/tasks/onesie.rake
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,23 @@ namespace :onesie do

# bundle exec rake onesie:new['MyTask']
# bundle exec rake onesie:new['MyTask','high']
# bundle exec rake onesie:new['MyTask','high','ExampleTemplateName']
# bundle exec rake onesie:new['MyTask',,'ExampleTemplateName']
desc 'Generates a new Onesie Task'
task :new, [:name, :priority] do |_t, args|
task :new, [:name, :priority, :template] do |_t, args|
name = args.fetch(:name)
priority = args.fetch(:priority, nil)
task_template = args.fetch(:template, nil)

Rails::Generators.invoke('onesie:task', [name, priority])
Rails::Generators.invoke('onesie:task', [name, priority, task_template])
end

# bundle exec rake onesie:new_template['ExampleTemplateName']
desc 'Generates a new Onesie Template'
task :new_template, [:filename] do |_t, args|
filename = args.fetch(:filename)

Rails::Generators.invoke('onesie:template', [filename])
end

# bundle exec rake onesie:rerun
Expand Down
17 changes: 17 additions & 0 deletions lib/onesie/template_reader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

using Rainbow

module Onesie
# Responsible for loading custom template files
class TemplateReader
def self.read_template(path)
unless File.exist?(path)
puts "Custom Template could not be found at #{path}".red
return
Comment on lines +9 to +11
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timlkelly this is to resolve the file being created despite the template not existing.

I was not able to find a way to prevent the generator to not create the file, even with raising an exception here, so I'm defaulting to an error message being printed, and in the consumer of this, defaulting back to the default template.

end

File.read(path)
end
end
end
41 changes: 36 additions & 5 deletions spec/onesie/generators/task_generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,45 @@

RSpec.describe Onesie::Generators::TaskGenerator, type: :generator do
destination File.expand_path('../../../tmp', __dir__)
arguments %w[TestTask]

before do
prepare_destination
run_generator
allow(Rails).to receive(:root).and_return(Pathname.new('.'))
end

it 'creates a new task file' do
assert_migration 'onesie/tasks/test_task.rb', /class TestTask < Onesie::Task/
context 'when only task name is specified' do
arguments %w[TestTask]

it 'creates a new task file with default template' do
allow(Onesie::TemplateReader).to receive(:read_template).and_return(nil)

prepare_destination
run_generator

assert_migration 'onesie/tasks/test_task.rb', /class TestTask < Onesie::Task/
assert_migration 'onesie/tasks/test_task.rb', /# Write your Onesie Task here/
end
end

context 'when template file is specified' do
arguments ['TestTask', nil, 'example_task']

it 'creates a new task file with the template file inside #run' do
allow(Onesie::TemplateReader).to receive(:read_template).and_return('# sample custom content')

prepare_destination
run_generator

assert_migration 'onesie/tasks/test_task.rb', /class TestTask < Onesie::Task/
assert_migration 'onesie/tasks/test_task.rb', /# sample custom content/
end
end

context 'when template file does not exist' do
it 'gracefully reverts to default template' do
prepare_destination
run_generator

assert_migration 'onesie/tasks/test_task.rb', /# Write your Onesie Task here/
end
end
end
23 changes: 23 additions & 0 deletions spec/onesie/generators/template_generator_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require 'generator_spec'
require 'generators/onesie/template_generator'

RSpec.describe Onesie::Generators::TemplateGenerator, type: :generator do
destination File.expand_path('../../../tmp', __dir__)
arguments %w[ExampleTemplate]

before do
prepare_destination
run_generator
end

it 'creates a new template file' do
path = 'tmp/onesie/templates/example_template.rb'
expect(File.exist?(path)).to be(true)

contents = File.read(path)

expect(contents).to eq("# Write the contents of Onesie::Tasks#run here!\n")
end
end
Loading