Class: FilterTable::Table
- Inherits:
-
Object
- Object
- FilterTable::Table
- Defined in:
- lib/inspec/utils/filter.rb
Instance Attribute Summary collapse
-
#criteria_string ⇒ Object
readonly
Returns the value of attribute criteria_string.
-
#raw_data ⇒ Object
readonly
Returns the value of attribute raw_data.
-
#resource_instance ⇒ Object
readonly
Returns the value of attribute resource_instance.
Instance Method Summary collapse
- #callback_for_lazy_field(field_name) ⇒ Object
- #create_eval_context_for_row(*_) ⇒ Object
- #entries ⇒ Object
- #field?(proposed_field) ⇒ Boolean
- #field_populated?(field_name) ⇒ Boolean
- #get_column_values(field) ⇒ Object
-
#initialize(resource_instance, raw_data, criteria_string) ⇒ Table
constructor
A new instance of Table.
- #is_field_lazy?(sought_field_name) ⇒ Boolean
- #list_fields ⇒ Object
- #mark_lazy_field_populated(field_name) ⇒ Object
- #params ⇒ Object
- #populate_lazy_field(field_name, criterion) ⇒ Object
- #resource ⇒ Object
- #to_s ⇒ Object (also: #inspect)
-
#where(conditions = {}, &block) ⇒ Object
Filter the raw data based on criteria (as method params) or by evaling a block; then construct a new Table of the same class as ourselves, wrapping the filtered data, and return it.
Constructor Details
#initialize(resource_instance, raw_data, criteria_string) ⇒ Table
Returns a new instance of Table.
84 85 86 87 88 89 90 |
# File 'lib/inspec/utils/filter.rb', line 84 def initialize(resource_instance, raw_data, criteria_string) @resource_instance = resource_instance @raw_data = raw_data @raw_data = [] if @raw_data.nil? @criteria_string = criteria_string @populated_lazy_columns = {} end |
Instance Attribute Details
#criteria_string ⇒ Object (readonly)
Returns the value of attribute criteria_string.
83 84 85 |
# File 'lib/inspec/utils/filter.rb', line 83 def criteria_string @criteria_string end |
#raw_data ⇒ Object (readonly)
Returns the value of attribute raw_data.
83 84 85 |
# File 'lib/inspec/utils/filter.rb', line 83 def raw_data @raw_data end |
#resource_instance ⇒ Object (readonly)
Returns the value of attribute resource_instance.
83 84 85 |
# File 'lib/inspec/utils/filter.rb', line 83 def resource_instance @resource_instance end |
Instance Method Details
#callback_for_lazy_field(field_name) ⇒ Object
212 213 214 215 216 217 218 |
# File 'lib/inspec/utils/filter.rb', line 212 def callback_for_lazy_field(field_name) return unless is_field_lazy?(field_name) custom_properties_schema.values.find do |property_struct| property_struct.field_name == field_name end.opts[:lazy] end |
#create_eval_context_for_row(*_) ⇒ Object
138 139 140 141 142 |
# File 'lib/inspec/utils/filter.rb', line 138 def create_eval_context_for_row(*_) raise "#{self.class} must not be used on its own. It must be inherited "\ "and the #create_eval_context_for_row method must be implemented. This is an internal "\ "error and should not happen." end |
#entries ⇒ Object
153 154 155 156 157 158 |
# File 'lib/inspec/utils/filter.rb', line 153 def entries row_criteria_string = resource.to_s + criteria_string + " one entry" raw_data.map do |row| create_eval_context_for_row(row, row_criteria_string) end end |
#field?(proposed_field) ⇒ Boolean
172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/inspec/utils/filter.rb', line 172 def field?(proposed_field) # Currently we only know about a field if it is present in a at least one row of the raw data. # If we have no rows in the raw data, assume all fields are acceptable (and rely on failing to match on value, nil) return true if raw_data.empty? # Most resources have Symbol keys in their raw data. Some have Strings (looking at you, `shadow`). is_field = false is_field ||= list_fields.include?(proposed_field.to_s) is_field ||= list_fields.include?(proposed_field.to_sym) is_field ||= is_field_lazy?(proposed_field.to_s) is_field ||= is_field_lazy?(proposed_field.to_sym) is_field end |
#field_populated?(field_name) ⇒ Boolean
220 221 222 |
# File 'lib/inspec/utils/filter.rb', line 220 def field_populated?(field_name) @populated_lazy_columns[field_name] end |
#get_column_values(field) ⇒ Object
160 161 162 163 164 |
# File 'lib/inspec/utils/filter.rb', line 160 def get_column_values(field) raw_data.map do |row| row[field] end end |
#is_field_lazy?(sought_field_name) ⇒ Boolean
205 206 207 208 209 210 |
# File 'lib/inspec/utils/filter.rb', line 205 def is_field_lazy?(sought_field_name) custom_properties_schema.values.any? do |property_struct| sought_field_name == property_struct.field_name && \ property_struct.opts[:lazy] end end |
#list_fields ⇒ Object
166 167 168 169 170 |
# File 'lib/inspec/utils/filter.rb', line 166 def list_fields @__fields_in_raw_data ||= raw_data.reduce([]) do |fields, row| fields.concat(row.keys).uniq end end |
#mark_lazy_field_populated(field_name) ⇒ Object
224 225 226 |
# File 'lib/inspec/utils/filter.rb', line 224 def mark_lazy_field_populated(field_name) @populated_lazy_columns[field_name] = true end |
#params ⇒ Object
148 149 150 151 |
# File 'lib/inspec/utils/filter.rb', line 148 def params # TODO: consider deprecating raw_data end |
#populate_lazy_field(field_name, criterion) ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/inspec/utils/filter.rb', line 193 def populate_lazy_field(field_name, criterion) return unless is_field_lazy?(field_name) return if field_populated?(field_name) raw_data.each do |row| next if row.key?(field_name) # skip row if pre-existing data is present callback_for_lazy_field(field_name).call(row, criterion, self) end mark_lazy_field_populated(field_name) end |
#resource ⇒ Object
144 145 146 |
# File 'lib/inspec/utils/filter.rb', line 144 def resource resource_instance end |
#to_s ⇒ Object Also known as: inspect
187 188 189 |
# File 'lib/inspec/utils/filter.rb', line 187 def to_s resource.to_s + criteria_string end |
#where(conditions = {}, &block) ⇒ Object
Filter the raw data based on criteria (as method params) or by evaling a block; then construct a new Table of the same class as ourselves, wrapping the filtered data, and return it.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/inspec/utils/filter.rb', line 95 def where(conditions = {}, &block) return self unless conditions.is_a?(Hash) return self if conditions.empty? && !block_given? # Initialize the details of the new Table. new_criteria_string = criteria_string filtered_raw_data = raw_data # If we were provided params, interpret them as criteria to be evaluated # against the raw data. Criteria are assumed to be hash keys. conditions.each do |raw_field_name, desired_value| raise(ArgumentError, "'#{decorate_symbols(raw_field_name)}' is not a recognized criterion - expected one of #{decorate_symbols(list_fields).join(", ")}'") unless field?(raw_field_name) populate_lazy_field(raw_field_name, desired_value) if is_field_lazy?(raw_field_name) new_criteria_string += " #{raw_field_name} == #{desired_value.inspect}" filtered_raw_data = filter_raw_data(filtered_raw_data, raw_field_name, desired_value) end # If we were given a block, make a special Struct for each row, that has an accessor # for each field declared using `register_custom_property`, then instance-eval the block # against the struct. if block_given? # Perform the filtering. filtered_raw_data = filtered_raw_data.find_all { |row_as_hash| create_eval_context_for_row(row_as_hash, "").instance_eval(&block) } # Try to interpret the block for updating the stringification. src = Trace.new # Swallow any exceptions raised here. # See https://github.com/chef/inspec/issues/2929 begin src.instance_eval(&block) rescue # rubocop: disable Lint/HandleExceptions # Yes, robocop, ignoring all exceptions is normally # a bad idea. Here, an exception just means we don't # understand what was in a `where` block, so we can't # meaningfully sytringify it. We still have a decent # default stringification. end new_criteria_string += Trace.to_ruby(src) end self.class.new(resource, filtered_raw_data, new_criteria_string) end |