mirror of
https://github.com/inspec/inspec
synced 2024-11-23 05:03:07 +00:00
add #entries to filter table + remodel configuration
This commit is contained in:
parent
048a1584b9
commit
0c8e891ee1
3 changed files with 102 additions and 34 deletions
|
@ -34,8 +34,9 @@ module Inspec::Resources
|
|||
@params ||= read_params
|
||||
end
|
||||
|
||||
filter = FilterTable.create(self, :service_lines)
|
||||
filter.add_delegator(:where)
|
||||
filter = FilterTable.create
|
||||
filter.add_accessor(:where)
|
||||
.add_accessor(:entries)
|
||||
.add(:services, field: 'service')
|
||||
.add(:ids, field: 'id')
|
||||
.add(:socket_types, field: 'socket_type')
|
||||
|
@ -43,6 +44,7 @@ module Inspec::Resources
|
|||
.add(:wait, field: 'wait')
|
||||
.add(:disabled?) { |x| x.where('disable' => 'no').services.empty? }
|
||||
.add(:enabled?) { |x| x.where('disable' => 'yes').services.empty? }
|
||||
.connect(self, :service_lines)
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -19,12 +19,25 @@ module FilterTable
|
|||
filters = ''
|
||||
table = @params
|
||||
conditions.each do |field, condition|
|
||||
filters += " #{field} = #{condition.inspect}"
|
||||
filters += " #{field} == #{condition.inspect}"
|
||||
table = filter_lines(table, field, condition)
|
||||
end
|
||||
self.class.new(@resource, table, @filters + filters)
|
||||
end
|
||||
|
||||
def new_entry(*_)
|
||||
fail "#{self.class} must not be used on its own. It must be inherited "\
|
||||
'and the #new_entry method must be implemented. This is an internal '\
|
||||
'error and should not happen.'
|
||||
end
|
||||
|
||||
def entries
|
||||
f = @resource.to_s + @filters.to_s + ' one entry'
|
||||
@params.map do |line|
|
||||
new_entry(line, f)
|
||||
end
|
||||
end
|
||||
|
||||
def get_fields(*fields)
|
||||
@params.map do |line|
|
||||
fields.map { |f| line[f] }
|
||||
|
@ -53,26 +66,60 @@ module FilterTable
|
|||
end
|
||||
|
||||
class Factory
|
||||
def initialize(resource, accessor)
|
||||
@resource = resource
|
||||
@accessor = accessor
|
||||
@table = Class.new(Table)
|
||||
def initialize
|
||||
@accessors = []
|
||||
@fields = {}
|
||||
@blocks = {}
|
||||
end
|
||||
|
||||
def table(instance)
|
||||
table.new(self, instance.method(table_accessor).call, '')
|
||||
def connect(resource, table_accessor) # rubocop:disable Metrics/AbcSize
|
||||
# create the table structure
|
||||
fields = @fields
|
||||
blocks = @blocks
|
||||
struct_fields = fields.values
|
||||
|
||||
# the struct to hold single items from the #entries method
|
||||
entry_struct = Struct.new(*struct_fields.map(&:to_sym)) do
|
||||
attr_accessor :__filter
|
||||
def to_s # rubocop:disable Lint/NestedMethodDefinition
|
||||
@__filter || super
|
||||
end
|
||||
end unless struct_fields.empty?
|
||||
|
||||
# the main filter table
|
||||
table = Class.new(Table) {
|
||||
fields.each do |method, field_name|
|
||||
block = blocks[method]
|
||||
define_method method.to_sym do |condition = Show|
|
||||
return block.call(self) unless block.nil?
|
||||
return where(nil).get_fields(field_name) if condition == Show
|
||||
where({ field_name => condition })
|
||||
end
|
||||
end
|
||||
|
||||
define_method :new_entry do |hashmap, filter = ''|
|
||||
return entry_struct.new if hashmap.nil?
|
||||
res = entry_struct.new(*struct_fields.map { |x| hashmap[x] })
|
||||
res.__filter = filter
|
||||
res
|
||||
end
|
||||
}
|
||||
|
||||
# define all access methods with the parent resource
|
||||
accessors = @accessors + @fields.keys
|
||||
accessors.each do |method_name|
|
||||
resource.send(:define_method, method_name.to_sym) do |*args|
|
||||
filter = table.new(self, method(table_accessor).call, ' with')
|
||||
filter.method(method_name.to_sym).call(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_delegator(method_name)
|
||||
def add_accessor(method_name)
|
||||
if method_name.nil?
|
||||
throw RuntimeError, "Called filter.add_delegator for resource #{@resource} with method name nil!"
|
||||
end
|
||||
table_accessor = @accessor
|
||||
table = @table
|
||||
@resource.send(:define_method, method_name.to_sym) do |*args|
|
||||
filter = table.new(self, method(table_accessor).call, '')
|
||||
filter.method(method_name.to_sym).call(*args)
|
||||
end
|
||||
@accessors.push(method_name)
|
||||
self
|
||||
end
|
||||
|
||||
|
@ -82,17 +129,13 @@ module FilterTable
|
|||
end
|
||||
|
||||
field_name = opts[:field] || method_name
|
||||
@table.send(:define_method, method_name.to_sym) do |condition = Show|
|
||||
return block.call(self) unless block.nil? # rubocop:disable Performance/RedundantBlockCall
|
||||
return where(nil).get_fields(field_name) if condition == Show
|
||||
where({ field_name => condition })
|
||||
end
|
||||
|
||||
add_delegator(method_name)
|
||||
@fields[method_name.to_sym] = field_name
|
||||
@blocks[method_name.to_sym] = block
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
def self.create(resource, accessor)
|
||||
Factory.new(resource, accessor)
|
||||
def self.create
|
||||
Factory.new
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,30 +21,30 @@ describe FilterTable do
|
|||
end
|
||||
}
|
||||
|
||||
let (:factory) { FilterTable.create(resource, :data) }
|
||||
let (:factory) { FilterTable.create }
|
||||
let (:instance) { resource.new(data) }
|
||||
|
||||
it 'has a create utility which creates a filter factory' do
|
||||
factory.must_be_kind_of FilterTable::Factory
|
||||
end
|
||||
|
||||
describe 'when calling add_delegator' do
|
||||
describe 'when calling add_accessor' do
|
||||
it 'is chainable' do
|
||||
factory.add_delegator(:sth).must_equal factory
|
||||
factory.add_accessor(:sth).must_equal factory
|
||||
end
|
||||
|
||||
it 'wont add nil' do
|
||||
proc { factory.add_delegator(nil) }.must_throw RuntimeError
|
||||
proc { factory.add_accessor(nil) }.must_throw RuntimeError
|
||||
end
|
||||
|
||||
it 'can expose the where method' do
|
||||
factory.add_delegator(:where)
|
||||
factory.add_accessor(:where).connect(resource, :data)
|
||||
_(instance.respond_to?(:where)).must_equal true
|
||||
instance.where({ baz: 'yay' }).params.must_equal [data[0]]
|
||||
end
|
||||
|
||||
it 'will delegate even non-existing methods' do
|
||||
factory.add_delegator(:not_here)
|
||||
factory.add_accessor(:not_here).connect(resource, :data)
|
||||
_(instance.respond_to?(:not_here)).must_equal true
|
||||
end
|
||||
end
|
||||
|
@ -59,13 +59,36 @@ describe FilterTable do
|
|||
end
|
||||
|
||||
it 'can expose a data column' do
|
||||
factory.add(:baz)
|
||||
factory.add(:baz).connect(resource, :data)
|
||||
instance.baz(123).must_be_kind_of(FilterTable::Table)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when calling entries' do
|
||||
before { factory.add(:baz).connect(resource, :data) }
|
||||
let(:entries) { instance.baz(/.*/).entries }
|
||||
let(:entry) { instance.baz('yay').entries }
|
||||
|
||||
it 'retrieves all entries with this field' do
|
||||
entries.length.must_equal 3
|
||||
entry.length.must_equal 1
|
||||
end
|
||||
|
||||
it 'retrieves all entries with this field' do
|
||||
entry[0].must_be_kind_of(Struct)
|
||||
end
|
||||
|
||||
it 'retrieves all entries with this field' do
|
||||
entry[0].baz.must_equal 'yay'
|
||||
end
|
||||
|
||||
it 'prints nicely' do
|
||||
entry[0].to_s.must_match(/ with baz == "yay" one entry/)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with the number field' do
|
||||
before { factory.add(:num) }
|
||||
before { factory.add(:num).connect(resource, :data) }
|
||||
|
||||
it 'filter by nil' do
|
||||
instance.num(nil).params.must_equal [data[0]]
|
||||
|
@ -81,7 +104,7 @@ describe FilterTable do
|
|||
end
|
||||
|
||||
describe 'with the string field' do
|
||||
before { factory.add(:baz) }
|
||||
before { factory.add(:baz).connect(resource, :data) }
|
||||
|
||||
it 'filter by existing strings' do
|
||||
instance.baz('yay').params.must_equal [data[0]]
|
||||
|
|
Loading…
Reference in a new issue