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.
92 93 94 95 96 97 98 |
# File 'lib/inspec/utils/filter.rb', line 92 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.
91 92 93 |
# File 'lib/inspec/utils/filter.rb', line 91 def criteria_string @criteria_string end |
#raw_data ⇒ Object (readonly)
Returns the value of attribute raw_data.
91 92 93 |
# File 'lib/inspec/utils/filter.rb', line 91 def raw_data @raw_data end |
#resource_instance ⇒ Object (readonly)
Returns the value of attribute resource_instance.
91 92 93 |
# File 'lib/inspec/utils/filter.rb', line 91 def resource_instance @resource_instance end |
Instance Method Details
#callback_for_lazy_field(field_name) ⇒ Object
220 221 222 223 224 225 226 |
# File 'lib/inspec/utils/filter.rb', line 220 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
146 147 148 149 150 |
# File 'lib/inspec/utils/filter.rb', line 146 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
161 162 163 164 165 166 |
# File 'lib/inspec/utils/filter.rb', line 161 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
180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/inspec/utils/filter.rb', line 180 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
228 229 230 |
# File 'lib/inspec/utils/filter.rb', line 228 def field_populated?(field_name) @populated_lazy_columns[field_name] end |
#get_column_values(field) ⇒ Object
168 169 170 171 172 |
# File 'lib/inspec/utils/filter.rb', line 168 def get_column_values(field) raw_data.map do |row| row[field] end end |
#is_field_lazy?(sought_field_name) ⇒ Boolean
213 214 215 216 217 218 |
# File 'lib/inspec/utils/filter.rb', line 213 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
174 175 176 177 178 |
# File 'lib/inspec/utils/filter.rb', line 174 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
232 233 234 |
# File 'lib/inspec/utils/filter.rb', line 232 def mark_lazy_field_populated(field_name) @populated_lazy_columns[field_name] = true end |
#params ⇒ Object
156 157 158 159 |
# File 'lib/inspec/utils/filter.rb', line 156 def params # TODO: consider deprecating raw_data end |
#populate_lazy_field(field_name, criterion) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/inspec/utils/filter.rb', line 201 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
152 153 154 |
# File 'lib/inspec/utils/filter.rb', line 152 def resource resource_instance end |
#to_s ⇒ Object Also known as: inspect
195 196 197 |
# File 'lib/inspec/utils/filter.rb', line 195 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.
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 137 138 139 140 141 142 143 144 |
# File 'lib/inspec/utils/filter.rb', line 103 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 |