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 CLI - Integrate fakerbot 🤖 #1507

Merged
merged 17 commits into from Mar 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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')
Copy link
Member

Choose a reason for hiding this comment

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

Adding these dependencies is a pretty big deal. Are we comfortable with them? I saw the terminal response. It's pretty cool.

Thoughts? @stympy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a valid concern, from my POV, these libraries go a long way in making the CLI interface easier to work with. 🙂 The alternative would be to write it all ourselves which I'm not sure about

Choose a reason for hiding this comment

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

FWIW, I find all these dependencies to be a big deal. I opened an issue about it (#1642) and plan to stay on 1.9.3 for the time being.

Copy link
Member

Choose a reason for hiding this comment

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

@myronmarston your concern is valid.

@akabiru would you agree to remove these dependencies and just show a formatted list of searched results?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey folks, apologies for the very delayed response (on vacation). I think the move to a separate gem is the sensible approach. And allows users to opt-in into using the gem.

It did start as a separate gem , no strong objections on this one. 🙂

@vbrazo I'm happy to assist with the extraction &/migration as well.


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
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wrapping the CLI methods in Gem::Deprecate.skip_during block ensures we safely skip the warnings only in the CLI. Although it's intended for use in tests only, it seems like a sensible solution to me. Ref. https://ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html

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