Skip to content

Commit

Permalink
Add CLI - Integrate fakerbot 🤖 (#1507)
Browse files Browse the repository at this point in the history
* feat(cli): Pull in fakerbot gem logic

* chore(cli): Extract module outside of `faker` dir

The module dir `faker` houses the main "faker" namespaces; and it should
remain that way.

Best to have the CLI live outside the directory; similar to helpers

* feat(cli): Add `faker` excecutable

* feat(cli): Add renderer; reflector unit tests

* feat(cli): Add commands tests

* feat(cli): Add integration tests

* feat(cli): Add documentation 📖

* chore(cli): Extract constructor to base command

* fix(cli): Amend faker version load path

- Add integration test to cover that

* fix(cli): Skip default deprecation warning output in the CLI

* chore(cli): Amend var names

* chore(reflectors): Distribute Reflector responsibilities

The Reflector was doing too much; handling Search and List reflections
which made it a tad harder to follow.

This commit defines a Reflection interface and the correspoding
subclasses.

* chore: Don't specify bunlder version

There's an erroneous 'null byte' error in the CI which could be caused
by the bundler version.

Further, As of Ruby 2.6.0, bundler is now built into Ruby, so no need to
install it ourselves

* chore: Address review comments

* move cli doc to unreleased
* Reinstate rubygems deprecation warnings

* chore: Skip Gem::Deprecate warning output in CLI
  • Loading branch information
akabiru authored and vbrazo committed Mar 3, 2019
1 parent f873bab commit 2ef261c
Show file tree
Hide file tree
Showing 23 changed files with 918 additions and 39 deletions.
54 changes: 42 additions & 12 deletions Gemfile.lock
Expand Up @@ -3,26 +3,40 @@ PATH
specs:
faker (1.9.3)
i18n (>= 0.7)
pastel (~> 0.7.2)
thor (~> 0.20.0)
tty-pager (~> 0.12.0)
tty-screen (~> 0.6.5)
tty-tree (~> 0.2.0)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
coderay (1.1.2)
concurrent-ruby (1.1.4)
docile (1.3.1)
i18n (1.5.3)
equatable (0.5.0)
i18n (1.4.0)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.1)
jaro_winkler (1.5.2)
json (2.1.0)
method_source (0.9.2)
minitest (5.11.3)
parallel (1.12.1)
parser (2.5.1.2)
parser (2.5.3.0)
ast (~> 2.4.0)
pastel (0.7.2)
equatable (~> 0.5.0)
tty-color (~> 0.4.0)
power_assert (1.1.3)
powerpack (0.1.2)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rainbow (3.0.0)
rake (12.3.1)
rubocop (0.59.2)
rubocop (0.59.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
Expand All @@ -36,22 +50,38 @@ GEM
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
strings (0.1.4)
strings-ansi (~> 0.1.0)
unicode-display_width (~> 1.4.0)
unicode_utils (~> 1.4.0)
strings-ansi (0.1.0)
test-unit (3.2.8)
power_assert
thor (0.20.3)
timecop (0.9.1)
unicode-display_width (1.4.0)
tty-color (0.4.3)
tty-pager (0.12.0)
strings (~> 0.1.4)
tty-screen (~> 0.6)
tty-which (~> 0.4)
tty-screen (0.6.5)
tty-tree (0.2.0)
tty-which (0.4.0)
unicode-display_width (1.4.1)
unicode_utils (1.4.0)

PLATFORMS
ruby

DEPENDENCIES
faker!
minitest
rake
rubocop
simplecov
test-unit
timecop
minitest (= 5.11.3)
pry (= 0.12.2)
rake (= 12.3.1)
rubocop (= 0.59.1)
simplecov (= 0.16.1)
test-unit (= 3.2.8)
timecop (= 0.9.1)

BUNDLED WITH
1.17.1
1.17.3
19 changes: 19 additions & 0 deletions bin/faker
@@ -0,0 +1,19 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

lib_path = File.expand_path('../lib', __dir__)
$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)

require 'cli'

Signal.trap('INT') do
warn("\n#{caller.join("\n")}: interrupted")
exit(1)
end

begin
Faker::CLI::Base.start
rescue Faker::CLI::Base::Error => err
puts "ERROR: #{err.message}"
exit 1
end
56 changes: 33 additions & 23 deletions faker.gemspec
Expand Up @@ -3,30 +3,40 @@
$LOAD_PATH.push File.expand_path('lib', __dir__)
require 'faker/version'

Gem::Specification.new do |s|
s.name = 'faker'
s.version = Faker::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ['Benjamin Curtis']
s.email = ['benjamin.curtis@gmail.com']
s.homepage = 'https://github.com/stympy/faker'
s.summary = 'Easily generate fake data'
s.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.'
s.license = 'MIT'
Gem::Specification.new do |spec|
spec.name = 'faker'
spec.version = Faker::VERSION
spec.platform = Gem::Platform::RUBY
spec.authors = ['Benjamin Curtis']
spec.email = ['benjamin.curtis@gmail.com']

s.add_runtime_dependency('i18n', '>= 0.7')
s.add_development_dependency('minitest')
s.add_development_dependency('rake')
s.add_development_dependency('rubocop')
s.add_development_dependency('simplecov')
s.add_development_dependency('test-unit')
s.add_development_dependency('timecop')
s.required_ruby_version = '>= 2.3'
spec.summary = 'Easily generate fake data'
spec.description = 'Faker, a port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.'
spec.homepage = 'https://github.com/stympy/faker'
spec.license = 'MIT'

s.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md]
s.require_paths = ['lib']
spec.files = Dir['lib/**/*'] + %w[History.md License.txt CHANGELOG.md README.md]
spec.bindir = 'bin'
spec.executables = ['faker']
spec.require_paths = ['lib']
spec.required_ruby_version = '>= 2.3'

s.metadata['changelog_uri'] = 'https://github.com/stympy/faker/blob/master/CHANGELOG.md'
s.metadata['source_code_uri'] = 'https://github.com/stympy/faker'
s.metadata['bug_tracker_uri'] = 'https://github.com/stympy/faker/issues'
spec.metadata['changelog_uri'] = 'https://github.com/stympy/faker/blob/master/CHANGELOG.md'
spec.metadata['source_code_uri'] = 'https://github.com/stympy/faker'
spec.metadata['bug_tracker_uri'] = 'https://github.com/stympy/faker/issues'

spec.add_dependency('i18n', '>= 0.7')
spec.add_dependency('pastel', '~> 0.7.2')
spec.add_dependency('thor', '~> 0.20.0')
spec.add_dependency('tty-pager', '~> 0.12.0')
spec.add_dependency('tty-screen', '~> 0.6.5')
spec.add_dependency('tty-tree', '~> 0.2.0')

spec.add_development_dependency('minitest', '5.11.3')
spec.add_development_dependency('pry', '0.12.2')
spec.add_development_dependency('rake', '12.3.1')
spec.add_development_dependency('rubocop', '0.59.1')
spec.add_development_dependency('simplecov', '0.16.1')
spec.add_development_dependency('test-unit', '3.2.8')
spec.add_development_dependency('timecop', '0.9.1')
end
53 changes: 53 additions & 0 deletions lib/cli.rb
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require 'thor'

require 'cli/commands/list'
require 'cli/commands/search'
require 'faker/version'

module Faker
module CLI
class Base < Thor
Error = Class.new(StandardError)
# Skip default deprecation warning output; the CLI will display that.
Gem::Deprecate.skip_during do
desc 'version', 'Faker version'
def version
puts "v#{Faker::VERSION}"
end
map %w[--version -v] => :version

desc 'list', 'List all Faker constants'
method_option :help, aliases: '-h', type: :boolean,
desc: 'Display usage information'
method_option :show_methods, aliases: '-m', type: :boolean, default: true,
desc: 'Display Faker constants with methods'
method_option :verbose, aliases: '-v', type: :boolean,
desc: 'Include sample Faker output'
def list(*)
if options[:help]
invoke :help, ['list']
else
Faker::CLI::Commands::List.new(options).execute
end
end

desc 'search [Faker]', 'Search Faker method(s)'
method_option :help, aliases: '-h', type: :boolean,
desc: 'Display usage information'
method_option :show_methods, aliases: '-m', type: :boolean, default: true,
desc: 'Display Faker constants with methods'
method_option :verbose, aliases: '-v', type: :boolean,
desc: 'Include sample Faker output'
def search(query)
if options[:help]
invoke :help, ['search']
else
Faker::CLI::Commands::Search.new(options).execute(query)
end
end
end
end
end
end
55 changes: 55 additions & 0 deletions lib/cli/README.md
@@ -0,0 +1,55 @@
# faker (cli)

## Usage

1.) Run a quick lookup

```bash
$ faker search name
# Faker::SwordArtOnline
# └── real_name
# └── game_name
# Faker::Superhero
# └── name
# ....
```

2.) List methods

```sh
$ faker list
# Faker::BackToTheFuture
# ├── quote
# ├── date
# └── character
# Faker::Finance
# └── credit_card
# ....
```

`faker` also includes an option to display sample output via the `--verbose` or `-v` flag. :wink:

3.)

```sh
$ faker list -v
# Faker::Appliance
# ├── brand=> Whirlpool
# └── equipment=> Sump pump
# Faker::UmphreysMcgee
# └── song=> Headphones & Snowcones
$ faker search name -v
# Faker::App
# └── name=> Subin
# Faker::Address
# └── street_name=> Percy Landing
# ....
```

## Features! :sunglasses: :dancers:

- [x] List classes with methods E.g. Faker::FunnyName is displayed with `.name`,`.first_name` e.t.c.
- [x] Expand search to Faker::Base sub classes
- [x] Paginate results :book:

![screenshot 2019-01-05 at 03 02 08](https://user-images.githubusercontent.com/17295175/50717135-59d85780-1096-11e9-8d0d-eca95646644d.jpg)
24 changes: 24 additions & 0 deletions lib/cli/command.rb
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require 'forwardable'

require_relative 'renderer'

module Faker
module CLI
class Command
extend Forwardable

def_delegators :command, :run
attr_reader :options

def initialize(options)
@options = options
end

def render(result, output)
Renderer.call(result, options, output)
end
end
end
end
17 changes: 17 additions & 0 deletions lib/cli/commands/list.rb
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require_relative '../command'
require_relative '../reflectors/list'

module Faker
module CLI
module Commands
class List < Command
def execute(output: $stdout)
result = Reflectors::List.call(options)
render(result, output)
end
end
end
end
end
29 changes: 29 additions & 0 deletions lib/cli/commands/search.rb
@@ -0,0 +1,29 @@
# frozen_string_literal: true

require_relative '../command'
require_relative '../reflectors/search'

module Faker
module CLI
module Commands
class Search < Command
def execute(input, output: $stdout)
result = Reflectors::Search.call(input)
render(result, output)
end

private

def render(result, output)
return not_found(output) if result.empty?

super(result, output)
end

def not_found(output)
output.puts "\nSorry, we couldn't find a match 😢", "\n"
end
end
end
end
end

0 comments on commit 2ef261c

Please sign in to comment.