From 12a22f1b92fa8a3502ba7c15f71d8a36c3721f69 Mon Sep 17 00:00:00 2001 From: bpleslie Date: Fri, 26 Jul 2019 16:54:38 -0700 Subject: [PATCH 1/3] Allow list to accept filter and match on class name --- .ruby-version | 2 +- lib/faker/bot.rb | 5 +- lib/faker/bot/commands/list.rb | 12 +++++ lib/faker/bot/reflectors/list.rb | 22 ++++++-- spec/faker/bot/commands/list_spec.rb | 30 +++++++++-- spec/faker/bot/reflectors/list_spec.rb | 69 +++++++++++++++++++++++++- 6 files changed, 127 insertions(+), 13 deletions(-) diff --git a/.ruby-version b/.ruby-version index 197c4d5..aedc15b 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.4.0 +2.5.3 diff --git a/lib/faker/bot.rb b/lib/faker/bot.rb index 0e91071..af56ec5 100644 --- a/lib/faker/bot.rb +++ b/lib/faker/bot.rb @@ -24,11 +24,12 @@ def version desc: 'Display Faker constants with methods' method_option :verbose, aliases: '-v', type: :boolean, desc: 'Include sample Faker output' - def list(*) + def list(filter=nil) if options[:help] invoke :help, ['list'] else - Faker::Bot::Commands::List.new(options).execute + filter_options = options.merge(filter: filter) + Faker::Bot::Commands::List.new(filter_options).execute end end diff --git a/lib/faker/bot/commands/list.rb b/lib/faker/bot/commands/list.rb index 8a1e8b4..1c163c7 100644 --- a/lib/faker/bot/commands/list.rb +++ b/lib/faker/bot/commands/list.rb @@ -11,6 +11,18 @@ def execute(output: $stdout) result = Reflectors::List.call(options) 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, that class doesn't exist 😢", "\n", "Try something like `Faker::Beer` or `Beer`.", "\n" + end end end end diff --git a/lib/faker/bot/reflectors/list.rb b/lib/faker/bot/reflectors/list.rb index 0cd5382..6a35828 100644 --- a/lib/faker/bot/reflectors/list.rb +++ b/lib/faker/bot/reflectors/list.rb @@ -9,6 +9,7 @@ module Reflectors # @api private # class List < Reflector + attr_reader :filter attr_reader :show_methods def self.call(options) @@ -16,22 +17,35 @@ def self.call(options) end def initialize(options = {}) + @filter = options[:filter] @show_methods = options[:show_methods] super end def call - show_methods ? all_descendants_with_methods : faker_descendants + show_methods ? list_descendants_with_methods : list_descendants end private - def all_descendants_with_methods + def list_descendants_with_methods + list_descendants + descendants_with_methods + end + + def list_descendants faker_descendants.each do |descendant| - store(descendant, descendant.my_singleton_methods) + if filter_matches_class_name?(descendant.to_s) + store(descendant, descendant.my_singleton_methods) + end end - descendants_with_methods + descendants_with_methods.keys + end + + def filter_matches_class_name?(class_name) + return true unless filter + class_name.match(/#{filter}/) end end end diff --git a/spec/faker/bot/commands/list_spec.rb b/spec/faker/bot/commands/list_spec.rb index cfd7fa0..4c4f1d3 100644 --- a/spec/faker/bot/commands/list_spec.rb +++ b/spec/faker/bot/commands/list_spec.rb @@ -7,23 +7,43 @@ let(:options) { {} } let(:command) { Faker::Bot::Commands::List.new(options) } - before do - command.execute(output: output) - end - context 'when single `list` command' do it 'executes successfully' do + command.execute(output: output) expect(output.string).to match(/Faker/) expect(output.string.lines.size).to be_positive end + + context 'when passing a filter option' do + let(:options) { super().merge(filter: filter) } + + context 'when the filter matches' do + let(:filter) { 'Cannabis' } + + it 'executes successfully' do + command.execute(output: output) + expect(output.string).to match(/Faker/) + expect(output.string.lines.size).to be_positive + end + end + + context 'when the filter does not match' do + let(:filter) { 'foobar' } + + it 'returns a not found message' do + command.execute(output: output) + expect(output.string).to match(/Sorry, that class doesn't exist/) + end + end + end end context 'when `list -v` verbose command' do let(:options) { { verbose: true } } it 'executes successfully' do + command.execute(output: output) constant = output.string.lines[0] - expect(constant).to match(/Faker::/) end end diff --git a/spec/faker/bot/reflectors/list_spec.rb b/spec/faker/bot/reflectors/list_spec.rb index 56af3f3..a501f58 100644 --- a/spec/faker/bot/reflectors/list_spec.rb +++ b/spec/faker/bot/reflectors/list_spec.rb @@ -20,6 +20,44 @@ expect(sample_result_value).to be_a(Array) expect(sample_result_value).not_to be_empty end + + context 'when passing a filter' do + context 'when filtering by full class name' do + it 'returns filtered descendants and their methods' do + options = { show_methods: true, filter: 'Faker::Beer' } + + reflector = described_class.new(options) + result = reflector.call + + sample_result = result.first + sample_result_key = sample_result.first.to_s + sample_result_value = sample_result.last + + expect(result).to be_a(Hash) + expect(sample_result_key).to eq('Faker::Beer') + expect(sample_result_value).to be_a(Array) + expect(sample_result_value).not_to be_empty + end + end + + context 'when filtering by partial class name' do + it 'returns filtered descendants and their methods' do + options = { show_methods: true, filter: 'Beer' } + + reflector = described_class.new(options) + result = reflector.call + + sample_result = result.first + sample_result_key = sample_result.first.to_s + sample_result_value = sample_result.last + + expect(result).to be_a(Hash) + expect(sample_result_key).to eq('Faker::Beer') + expect(sample_result_value).to be_a(Array) + expect(sample_result_value).not_to be_empty + end + end + end end context 'when show methods is disabled' do @@ -28,13 +66,42 @@ reflector = described_class.new(options) result = reflector.call - sample_result = result.first.to_s expect(result).to be_a(Array) expect(result).not_to be_empty expect(sample_result).to match(/Faker::/) end + + context 'when passing a filter' do + context 'when filtering by full class name' do + it 'returns filtered descendants and their methods' do + options = { show_methods: false, filter: 'Faker::Beer' } + + reflector = described_class.new(options) + result = reflector.call + sample_result = result.first.to_s + + expect(result).to be_a(Array) + expect(result).not_to be_empty + expect(sample_result).to eq('Faker::Beer') + end + end + + context 'when filtering by partial class name' do + it 'returns filtered descendants and their methods' do + options = { show_methods: false, filter: 'Beer' } + + reflector = described_class.new(options) + result = reflector.call + sample_result = result.first.to_s + + expect(result).to be_a(Array) + expect(result).not_to be_empty + expect(sample_result).to eq('Faker::Beer') + end + end + end end end end From d4dbcf833d570ecbb07314bef27f0f5c6c37a42a Mon Sep 17 00:00:00 2001 From: Brad Leslie Date: Wed, 31 Jul 2019 06:42:50 -0700 Subject: [PATCH 2/3] Update lib/faker/bot.rb Co-Authored-By: Kabiru Mwenja --- lib/faker/bot.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/faker/bot.rb b/lib/faker/bot.rb index af56ec5..bb37778 100644 --- a/lib/faker/bot.rb +++ b/lib/faker/bot.rb @@ -24,7 +24,7 @@ def version desc: 'Display Faker constants with methods' method_option :verbose, aliases: '-v', type: :boolean, desc: 'Include sample Faker output' - def list(filter=nil) + def list(filter = nil) if options[:help] invoke :help, ['list'] else From a721311b8d1f920feebce2c36e317f51fb8d75ab Mon Sep 17 00:00:00 2001 From: Brad Leslie Date: Wed, 31 Jul 2019 06:53:37 -0700 Subject: [PATCH 3/3] Update lib/faker/bot/commands/list.rb Co-Authored-By: Kabiru Mwenja --- lib/faker/bot/commands/list.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/faker/bot/commands/list.rb b/lib/faker/bot/commands/list.rb index 1c163c7..36d400d 100644 --- a/lib/faker/bot/commands/list.rb +++ b/lib/faker/bot/commands/list.rb @@ -21,7 +21,8 @@ def render(result, output) end def not_found(output) - output.puts "\nSorry, that class doesn't exist 😢", "\n", "Try something like `Faker::Beer` or `Beer`.", "\n" + output.puts "\nSorry, that class doesn't exist 😢", "\n", + 'Try something like `Faker::Beer` or `Beer`.', "\n" end end end