Module: ProductTaxonomy::Indexed
- Included in:
- Attribute, Category, Disclosure, ReturnReason, Value
- Defined in:
- lib/product_taxonomy/models/mixins/indexed.rb
Overview
Mixin providing indexing for a model, using hashes to support fast uniqueness checks and lookups by field value.
Defined Under Namespace
Classes: UniquenessValidator
Constant Summary collapse
- NotFoundError =
Class.new(StandardError)
Class Method Summary collapse
-
.extended(indexed_model_class) ⇒ Object
Keep track of which model class used "extend Indexed" so that the model can be subclassed while still storing model objects in a shared index on the superclass.
Instance Method Summary collapse
-
#add(model) ⇒ Object
Add a model to the index.
-
#all ⇒ Array<Object>
Get all models in the index.
-
#create_validate_and_add! ⇒ Object
Convenience method to create a model, validate it, and add it to the index.
-
#duplicate?(model:, field:) ⇒ Boolean
Check if a field value is a duplicate of an existing model.
-
#find_by(**conditions) ⇒ Object?
Find a model by field value.
-
#find_by!(**conditions) ⇒ Object
Find a model by field value.
-
#hashed_by(field) ⇒ Hash
Get the hash of models indexed by a given field.
-
#hashed_models ⇒ Hash
Get the hash of hash of models, indexed by fields marked unique.
-
#size ⇒ Integer
Get the number of models in the index.
Class Method Details
.extended(indexed_model_class) ⇒ Object
Keep track of which model class used "extend Indexed" so that the model can be subclassed while still storing model objects in a shared index on the superclass.
11 12 13 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 11 def extended(indexed_model_class) indexed_model_class.instance_variable_set(:@is_indexed, true) end |
Instance Method Details
#add(model) ⇒ Object
Add a model to the index.
28 29 30 31 32 33 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 28 def add(model) hashed_models.keys.each do |field| hashed_models[field][model.send(field)] ||= [] hashed_models[field][model.send(field)] << model end end |
#all ⇒ Array<Object>
Get all models in the index.
100 101 102 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 100 def all hashed_models.first[1].values.flatten end |
#create_validate_and_add! ⇒ Object
Convenience method to create a model, validate it, and add it to the index. If the model is not valid, raise an error.
40 41 42 43 44 45 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 40 def create_validate_and_add!(...) model = new(...) model.validate!(:create) add(model) model end |
#duplicate?(model:, field:) ⇒ Boolean
Check if a field value is a duplicate of an existing model. A model is considered to be a duplicate if it was added after the first model with that value.
53 54 55 56 57 58 59 60 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 53 def duplicate?(model:, field:) raise ArgumentError, "Field not hashed: #{field}" unless hashed_models.key?(field) existing_models = hashed_models[field][model.send(field)] return false if existing_models.nil? existing_models.first != model end |
#find_by(**conditions) ⇒ Object?
Find a model by field value. Returns the first matching record or nil. Only works for fields marked unique.
66 67 68 69 70 71 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 66 def find_by(**conditions) field, value = conditions.first raise ArgumentError, "Field not hashed: #{field}" unless hashed_models.key?(field) hashed_models[field][value]&.first end |
#find_by!(**conditions) ⇒ Object
Find a model by field value. Returns the first matching record or raises an error if not found. Only works for fields marked unique.
78 79 80 81 82 83 84 85 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 78 def find_by!(**conditions) record = find_by(**conditions) return record if record field, value = conditions.first field = field.to_s.humanize(capitalize: false, keep_id_suffix: true) raise NotFoundError, "#{self.name.demodulize} with #{field} \"#{value}\" not found" end |
#hashed_by(field) ⇒ Hash
Get the hash of models indexed by a given field. Only works for fields marked unique.
91 92 93 94 95 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 91 def hashed_by(field) raise ArgumentError, "Field not hashed: #{field}" unless hashed_models.key?(field) hashed_models[field] end |
#hashed_models ⇒ Hash
Get the hash of hash of models, indexed by fields marked unique.
114 115 116 117 118 119 120 121 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 114 def hashed_models # If we're a subclass of the model class that originally extended Indexed, use the parent class' hashed_models. return superclass.hashed_models unless @is_indexed @hashed_models ||= unique_fields.each_with_object({}) do |field, hash| hash[field] = {} end end |
#size ⇒ Integer
Get the number of models in the index.
107 108 109 |
# File 'lib/product_taxonomy/models/mixins/indexed.rb', line 107 def size all.size end |