-
-
Save chrise86/bea1162bc2fefd6ddb860de664ccaf24 to your computer and use it in GitHub Desktop.
Rails generator for services and lib objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ServiceGenerator < Rails::Generators::NamedBase | |
argument :arguments, type: :array, default: [], banner: "argument argument" | |
source_root File.expand_path('../templates', __FILE__) | |
check_class_collision suffix: "Service" | |
def create_service_files | |
template "service.rb.tt", File.join("lib", class_path, "#{file_name}_service.rb") | |
template( | |
'service_spec.rb.tt', | |
File.join('spec', 'lib', class_path, "#{file_name}_service_spec.rb"), | |
) | |
end | |
private | |
def file_name | |
@_file_name ||= remove_possible_suffix(super) | |
end | |
def remove_possible_suffix(name) | |
name.sub(/_?service$/i, "") | |
end | |
def class_name_without_module | |
file_name.camelize | |
end | |
# Wrap block with `module` blocks. | |
def module_namespacing(&block) | |
content = capture(&block) | |
class_path.reverse.each do |module_name| | |
content = wrap_with_module(module_name, content) | |
end | |
concat(content) | |
end | |
def indent(content, multiplier = 2) | |
spaces = " " * multiplier | |
content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join | |
end | |
def wrap_with_module(module_name, content) # :doc: | |
content = indent(content).chomp | |
"module #{module_name.camelize}\n#{content}\nend\n" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
<% module_namespacing do -%> | |
class <%= class_name_without_module %>Service | |
class SpecificErrorClass < StandardError; end | |
<%- if arguments.any? -%> | |
def initialize(<%= arguments.map { |argument| "#{argument}:" }.join(', ') %>) | |
<%- for argument in arguments -%> | |
@<%= argument %> = <%= argument %> | |
<%- end -%> | |
end | |
<%- end -%> | |
def run! | |
raise SpecificErrorClass, "TODO: Implement this." | |
end | |
def run | |
run! | |
true | |
rescue SpecificErrorClass | |
false | |
end | |
private | |
<%- for argument in arguments -%> | |
attr_reader :<%= argument %> | |
<%- end -%> | |
end | |
<% end -%> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'rails_helper' | |
RSpec.describe <%= class_name %>Service do | |
<%- if arguments.empty? -%> | |
let(:service) { described_class.new } | |
<%- else -%> | |
let(:service) { | |
described_class.new( | |
<%- for argument in arguments -%> | |
<%= argument %>: <%= argument %>, | |
<%- end -%> | |
) | |
} | |
<%- for argument in arguments -%> | |
let(:<%= argument %>) { nil } | |
<%- end -%> | |
<%- end -%> | |
before do | |
pending "TODO: Implement these specs and remove this `before` block." | |
end | |
describe '#run!' do | |
subject(:run!) { service.run! } | |
context 'when things go well' do | |
it 'does something' | |
end | |
context 'when things go wrong' do | |
it 'raises an error' do | |
expect { run! }.to raise_error(<%= class_name %>Service::SpecificErrorClass) | |
end | |
end | |
end | |
describe '#run' do | |
subject(:run) { service.run } | |
context 'when things go well' do | |
it 'returns true' do | |
expect(run).to be_truthy | |
end | |
end | |
context 'when things go wrong' do | |
it 'returns false' do | |
expect(run).to be_falsey | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Description: | |
Stubs a new Service object in the `lib` folder and a spec for it. | |
Providing a list of argument names will set up the initializer to accept them | |
and create private accessors for each of them. | |
To create a service within a module, specify the service name as a | |
path like 'parent_module/service_name' or 'ParentModule::ServiceName'. | |
Example: | |
rails generate service ParentModule::Thing foo bar | |
This will create: | |
Service: lib/parent_module/thing_service.rb | |
Spec: spec/lib/parent_module/thing_service_spec.rb |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment