Module: Esse::Repository::ClassMethods
- Included in:
- Esse::Repository
- Defined in:
- lib/esse/repository/actions.rb,
lib/esse/repository/documents.rb,
lib/esse/repository/object_document_mapper.rb,
lib/esse/repository/lazy_document_attributes.rb
Instance Method Summary collapse
- #action(name, options = {}, &block) ⇒ Object
-
#collection(collection_klass = nil, **_, &block) ⇒ void
Used to define the source of data.
-
#document(klass = nil, &block) ⇒ Object
Define the document type that will be used to serialize the data.
-
#documents(**kwargs) ⇒ Enumerator
Wrap collection data into serialized documents.
- #documents_for_lazy_attribute(name, ids_or_doc_headers) ⇒ Object
-
#each_serialized_batch(lazy_attributes: false, **kwargs) {|Array, **context| ... } ⇒ Enumerator
Wrap collection data into serialized batches.
- #fetch_lazy_document_attribute(attr_name) ⇒ Object
- #import(**kwargs) ⇒ Object
- #lazy_document_attribute(attr_name, klass = nil, **kwargs, &block) ⇒ Object
- #lazy_document_attribute_names(all = true) ⇒ Object
- #lazy_document_attributes ⇒ Object
- #retrieve_lazy_attribute_values(name, ids_or_doc_headers) ⇒ Object
-
#serialize(model, **kwargs) ⇒ Esse::Document
Convert ruby object to json by using the document of the given document type.
- #update_documents_attribute(name, ids_or_doc_headers = [], kwargs = {}) ⇒ Object
Instance Method Details
#action(name, options = {}, &block) ⇒ Object
6 7 |
# File 'lib/esse/repository/actions.rb', line 6 def action(name, = {}, &block) end |
#collection(collection_klass = nil, **_, &block) ⇒ void
This method returns an undefined value.
Used to define the source of data. A block is required. And its content should yield an array of each object that should be serialized. The list of arguments will be passed throught the document method.
Example:
collection AdminStore
collection do |**conditions, &block|
User.where(conditions).find_in_batches(batch_size: 5000) do |batch|
block.call(batch, conditions)
end
end
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/esse/repository/object_document_mapper.rb', line 57 def collection(collection_klass = nil, **_, &block) if collection_klass.nil? && block.nil? raise ArgumentError, 'a document type, followed by a collection class or block that stream the data ' \ 'is required to define the collection' end if block.nil? && collection_klass.is_a?(Class) && !collection_klass.include?(Enumerable) msg = '%<arg>p is not a valid collection class.' \ ' Collections should implement the Enumerable interface.' raise ArgumentError, format(msg, arg: collection_klass) end @collection_proc = collection_klass || block end |
#document(klass = nil, &block) ⇒ Object
Define the document type that will be used to serialize the data. Arguments will be same of passed through the collection. It’s allowed a block or a class with the ‘to_h` instance method. Example with block
document do |model, **context|
{
id: model.id,
admin: context[:is_admin],
}
end
Example with document class
document UserDocument
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/esse/repository/object_document_mapper.rb', line 20 def document(klass = nil, &block) if @document_proc raise ArgumentError, format('Document for %p already defined', repo_name) end if block @document_proc = ->(model, **kwargs) { coerce_to_document(block.call(model, **kwargs)) } elsif klass.is_a?(Class) && klass <= Esse::Document @document_proc = ->(model, **kwargs) { klass.new(model, **kwargs) } elsif klass.is_a?(Class) && klass.instance_methods.include?(:to_h) @document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).to_h) } elsif klass.is_a?(Class) && klass.instance_methods.include?(:as_json) # backward compatibility @document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).as_json) } elsif klass.is_a?(Class) && klass.instance_methods.include?(:call) @document_proc = ->(model, **kwargs) { coerce_to_document(klass.new(model, **kwargs).call) } else msg = format("%<arg>p is not a valid document. The document should inherit from Esse::Document or respond to `to_h'", arg: klass) raise ArgumentError, msg end end |
#documents(**kwargs) ⇒ Enumerator
Wrap collection data into serialized documents
Example:
GeosIndex.documents(id: 1).first
102 103 104 105 106 107 108 |
# File 'lib/esse/repository/object_document_mapper.rb', line 102 def documents(**kwargs) Enumerator.new do |yielder| each_serialized_batch(**kwargs) do |docs, **_collection_kargs| docs.each { |document| yielder.yield(document) } end end end |
#documents_for_lazy_attribute(name, ids_or_doc_headers) ⇒ Object
17 18 19 20 21 |
# File 'lib/esse/repository/documents.rb', line 17 def documents_for_lazy_attribute(name, ids_or_doc_headers) retrieve_lazy_attribute_values(name, ids_or_doc_headers).map do |doc_header, datum| doc_header.to_doc(name => datum) end end |
#each_serialized_batch(lazy_attributes: false, **kwargs) {|Array, **context| ... } ⇒ Enumerator
Wrap collection data into serialized batches
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/esse/repository/object_document_mapper.rb', line 77 def each_serialized_batch(lazy_attributes: false, **kwargs) each_batch(**kwargs) do |*args| batch, collection_context = args collection_context ||= {} entries = [*batch].map { |entry| serialize(entry, **collection_context) }.compact if lazy_attributes attrs = lazy_attributes.is_a?(Array) ? lazy_attributes : lazy_document_attribute_names(lazy_attributes) attrs.each do |attr_name| retrieve_lazy_attribute_values(attr_name, entries).each do |doc_header, value| doc = entries.find { |d| doc_header.id.to_s == d.id.to_s && doc_header.type == d.type && doc_header.routing == d.routing } doc&.mutate(attr_name) { value } end end end yield entries, **kwargs end end |
#fetch_lazy_document_attribute(attr_name) ⇒ Object
23 24 25 26 27 28 |
# File 'lib/esse/repository/lazy_document_attributes.rb', line 23 def fetch_lazy_document_attribute(attr_name) klass, kwargs = lazy_document_attributes.fetch(attr_name) klass.new(**kwargs) rescue KeyError raise ArgumentError, format('Attribute %<attr>p is not defined as a lazy document attribute', attr: attr_name) end |
#import(**kwargs) ⇒ Object
6 7 8 |
# File 'lib/esse/repository/documents.rb', line 6 def import(**kwargs) index.import(repo_name, **kwargs) end |
#lazy_document_attribute(attr_name, klass = nil, **kwargs, &block) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/esse/repository/lazy_document_attributes.rb', line 30 def lazy_document_attribute(attr_name, klass = nil, **kwargs, &block) if attr_name.nil? raise ArgumentError, 'Attribute name is required to define a lazy document attribute' end if lazy_document_attribute?(attr_name.to_sym) || lazy_document_attribute?(attr_name.to_s) raise ArgumentError, format('Attribute %<attr>p is already defined as a lazy document attribute', attr: attr_name) end @lazy_document_attributes = lazy_document_attributes.dup if block klass = Class.new(Esse::DocumentLazyAttribute) do define_method(:call, &block) end @lazy_document_attributes[attr_name] = [klass, kwargs] elsif klass.is_a?(Class) && klass <= Esse::DocumentLazyAttribute @lazy_document_attributes[attr_name] = [klass, kwargs] elsif klass.is_a?(Class) && klass.instance_methods.include?(:call) @lazy_document_attributes[attr_name] = [klass, kwargs] elsif klass.nil? raise ArgumentError, format('A block or a class that responds to `call` is required to define a lazy document attribute') else raise ArgumentError, format('%<arg>p is not a valid lazy document attribute. Class should inherit from Esse::DocumentLazyAttribute or respond to `call`', arg: klass) end ensure @lazy_document_attributes&.freeze end |
#lazy_document_attribute_names(all = true) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/esse/repository/lazy_document_attributes.rb', line 11 def lazy_document_attribute_names(all = true) case all when false [] when true lazy_document_attributes.keys else filtered = Array(all).map(&:to_s) lazy_document_attributes.keys.select { |name| filtered.include?(name.to_s) } end end |
#lazy_document_attributes ⇒ Object
7 8 9 |
# File 'lib/esse/repository/lazy_document_attributes.rb', line 7 def lazy_document_attributes @lazy_document_attributes ||= {}.freeze end |
#retrieve_lazy_attribute_values(name, ids_or_doc_headers) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/esse/repository/documents.rb', line 23 def retrieve_lazy_attribute_values(name, ids_or_doc_headers) unless lazy_document_attribute?(name) raise ArgumentError, <<~MSG The attribute `#{name}` is not defined as a lazy document attribute. Define the attribute as a lazy document attribute using the `lazy_document_attribute` method. MSG end docs = LazyDocumentHeader.coerce_each(ids_or_doc_headers) return [] if docs.empty? result = fetch_lazy_document_attribute(name).call(docs) return [] unless result.is_a?(Hash) result.each_with_object({}) do |(key, value), memo| if key.is_a?(LazyDocumentHeader) && (doc = docs.find { |d| d == key || d.id == key.id }) memo[doc] = value elsif (doc = docs.find { |d| d.id == key }) memo[doc] = value end end end |
#serialize(model, **kwargs) ⇒ Esse::Document
Convert ruby object to json by using the document of the given document type.
114 115 116 117 118 119 120 |
# File 'lib/esse/repository/object_document_mapper.rb', line 114 def serialize(model, **kwargs) if @document_proc.nil? raise NotImplementedError, format('there is no %<t>p document defined for the %<k>p index', t: repo_name, k: index.to_s) end @document_proc.call(model, **kwargs) end |
#update_documents_attribute(name, ids_or_doc_headers = [], kwargs = {}) ⇒ Object
10 11 12 13 14 15 |
# File 'lib/esse/repository/documents.rb', line 10 def update_documents_attribute(name, ids_or_doc_headers = [], kwargs = {}) batch = documents_for_lazy_attribute(name, ids_or_doc_headers) return if batch.empty? index.bulk(**kwargs.transform_keys(&:to_sym), update: batch) end |