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
- #callback_for_lazy_instance_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
- #is_field_lazy_instance?(sought_field_name) ⇒ Boolean
- #list_fields ⇒ Object
- #mark_lazy_field_populated(field_name) ⇒ Object
- #params ⇒ Object
- #populate_lazy_field(field_name, criterion) ⇒ Object
- #populate_lazy_instance_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
247 248 249 250 251 252 253 |
# File 'lib/inspec/utils/filter.rb', line 247 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 |
#callback_for_lazy_instance_field(field_name) ⇒ Object
255 256 257 258 259 260 261 |
# File 'lib/inspec/utils/filter.rb', line 255 def callback_for_lazy_instance_field(field_name) return unless is_field_lazy_instance?(field_name) custom_properties_schema.values.find do |property_struct| property_struct.field_name == field_name end.opts[:lazy_instance] end |
#create_eval_context_for_row(*_) ⇒ Object
147 148 149 150 151 |
# File 'lib/inspec/utils/filter.rb', line 147 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
162 163 164 165 166 167 |
# File 'lib/inspec/utils/filter.rb', line 162 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
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/inspec/utils/filter.rb', line 181 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 ||= is_field_lazy_instance?(proposed_field.to_s) is_field ||= is_field_lazy_instance?(proposed_field.to_sym) is_field end |
#field_populated?(field_name) ⇒ Boolean
263 264 265 |
# File 'lib/inspec/utils/filter.rb', line 263 def field_populated?(field_name) @populated_lazy_columns[field_name] end |
#get_column_values(field) ⇒ Object
169 170 171 172 173 |
# File 'lib/inspec/utils/filter.rb', line 169 def get_column_values(field) raw_data.map do |row| row[field] end end |
#is_field_lazy?(sought_field_name) ⇒ Boolean
233 234 235 236 237 238 |
# File 'lib/inspec/utils/filter.rb', line 233 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 |
#is_field_lazy_instance?(sought_field_name) ⇒ Boolean
240 241 242 243 244 245 |
# File 'lib/inspec/utils/filter.rb', line 240 def is_field_lazy_instance?(sought_field_name) custom_properties_schema.values.any? do |property_struct| sought_field_name == property_struct.field_name && \ property_struct.opts[:lazy_instance] end end |
#list_fields ⇒ Object
175 176 177 178 179 |
# File 'lib/inspec/utils/filter.rb', line 175 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
267 268 269 |
# File 'lib/inspec/utils/filter.rb', line 267 def mark_lazy_field_populated(field_name) @populated_lazy_columns[field_name] = true end |
#params ⇒ Object
157 158 159 160 |
# File 'lib/inspec/utils/filter.rb', line 157 def params # TODO: consider deprecating raw_data end |
#populate_lazy_field(field_name, criterion) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/inspec/utils/filter.rb', line 204 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 |
#populate_lazy_instance_field(field_name, criterion) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/inspec/utils/filter.rb', line 216 def populate_lazy_instance_field(field_name, criterion) return unless is_field_lazy_instance?(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 lazy_caller = callback_for_lazy_instance_field(field_name) if lazy_caller.is_a?(Proc) lazy_caller.call(row, criterion, resource_instance) elsif lazy_caller.is_a?(Symbol) resource_instance.send(lazy_caller, row, criterion, self) end end mark_lazy_field_populated(field_name) end |
#resource ⇒ Object
153 154 155 |
# File 'lib/inspec/utils/filter.rb', line 153 def resource resource_instance end |
#to_s ⇒ Object Also known as: inspect
198 199 200 |
# File 'lib/inspec/utils/filter.rb', line 198 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 145 |
# 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) populate_lazy_instance_field(raw_field_name, desired_value) if is_field_lazy_instance?(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 |