Class: XapianDb::DocumentBlueprint
- Inherits:
-
Object
- Object
- XapianDb::DocumentBlueprint
- Includes:
- Utilities
- Defined in:
- lib/xapian_db/document_blueprint.rb
Overview
A document blueprint describes the mapping of an object to a Xapian document for a given class.
Defined Under Namespace
Classes: Dependency, IndexOptions
Class Attribute Summary collapse
-
.blueprints ⇒ Object
readonly
Returns the value of attribute blueprints.
Instance Attribute Summary collapse
-
#_natural_sort_order ⇒ Object
readonly
——————————————————————————— Blueprint DSL methods ———————————————————————————.
-
#dependencies ⇒ Object
readonly
——————————————————————————— Blueprint DSL methods ———————————————————————————.
-
#lazy_base_query ⇒ Object
readonly
——————————————————————————— Blueprint DSL methods ———————————————————————————.
-
#type_map ⇒ Object
readonly
——————————————————————————— Instance methods ———————————————————————————.
Class Method Summary collapse
-
.attributes ⇒ Array<Symbol>
Return an array of all defined attributes.
-
.blueprint_for(klass_or_name) ⇒ DocumentBlueprint
Get the blueprint for a class.
-
.configured?(name) ⇒ Boolean
is a blueprint configured for the given name?.
-
.configured_classes ⇒ Array<Class>
Get all configured classes.
- .dependencies_for(klass_name, changed_attrs) ⇒ Object
-
.reset ⇒ Object
reset the blueprint setup.
-
.searchable_prefixes ⇒ Array<String>
Return an array of all configured text methods in any blueprint.
-
.setup(klass_or_name) {|blueprint| ... } ⇒ Object
Configure the blueprint for a class.
-
.type_info_for(attribute) ⇒ Symbol
Get the type info of an attribute.
-
.value_number_for(attribute) ⇒ Integer
Get the value number for an attribute.
Instance Method Summary collapse
-
#_adapter ⇒ Object
return the adpater to use for this blueprint.
-
#accessors_module ⇒ Module
Lazily build and return a module that implements accessors for each field.
-
#adapter(type) ⇒ Object
Set the adapter.
-
#attribute(name, options = {}, &block) ⇒ Object
Add an attribute to the blueprint.
-
#attribute_names ⇒ Array<Symbol>
Get the names of all configured attributes sorted alphabetically.
-
#attributes(*attributes) ⇒ Object
Add a list of attributes to the blueprint.
-
#autoindex(boolean) ⇒ Object
Should objects for this blueprint be automatically reindexed?.
-
#autoindex? ⇒ Boolean
Get the autoindex value.
-
#base_query(expression = nil, &block) ⇒ Object
Define a base query to select one or all objects of the indexed class.
-
#block_for_attribute(attribute) ⇒ Block
Get the block associated with an attribute.
- #dependency(klass_name, when_changed: [], &block) ⇒ Object
-
#ignore_if(&block) ⇒ Object
Add a block of code that evaluates if a model should not be indexed.
-
#index(*args, &block) ⇒ Object
Add an indexed value to the blueprint.
-
#indexed_method_names ⇒ Array<Symbol>
Get the names of all configured index methods sorted alphabetically.
-
#indexer_preprocess_callback(method) ⇒ Object
Set the indexer preprocess callback.
-
#initialize ⇒ DocumentBlueprint
constructor
Construct the blueprint.
-
#natural_sort_order(name = nil, &block) ⇒ Object
Define the natural sort order.
-
#options_for_indexed_method(method) ⇒ IndexOptions
Get the options for an indexed method.
-
#preprocess_terms ⇒ Object
Reader for indexer_preprocess_callback.
-
#searchable_prefixes ⇒ Array<String>
Return an array of all configured text methods in this blueprint.
-
#should_index?(obj) ⇒ Boolean
Should the object go into the index? Evaluates an ignore expression, if defined.
Methods included from Utilities
#assert_valid_keys, #camelize, #constantize
Constructor Details
#initialize ⇒ DocumentBlueprint
Construct the blueprint
272 273 274 275 276 277 278 279 280 |
# File 'lib/xapian_db/document_blueprint.rb', line 272 def initialize @attributes_hash = {} @indexed_methods_hash = {} @type_map = {} @dependencies = [] @_natural_sort_order = :id @autoindex = true @indexer_preprocess_callback = nil end |
Class Attribute Details
.blueprints ⇒ Object (readonly)
Returns the value of attribute blueprints.
29 30 31 |
# File 'lib/xapian_db/document_blueprint.rb', line 29 def blueprints @blueprints end |
Instance Attribute Details
#_natural_sort_order ⇒ Object (readonly)
Blueprint DSL methods
269 270 271 |
# File 'lib/xapian_db/document_blueprint.rb', line 269 def _natural_sort_order @_natural_sort_order end |
#dependencies ⇒ Object (readonly)
Blueprint DSL methods
269 270 271 |
# File 'lib/xapian_db/document_blueprint.rb', line 269 def dependencies @dependencies end |
#lazy_base_query ⇒ Object (readonly)
Blueprint DSL methods
269 270 271 |
# File 'lib/xapian_db/document_blueprint.rb', line 269 def lazy_base_query @lazy_base_query end |
#type_map ⇒ Object (readonly)
Instance methods
185 186 187 |
# File 'lib/xapian_db/document_blueprint.rb', line 185 def type_map @type_map end |
Class Method Details
.attributes ⇒ Array<Symbol>
Return an array of all defined attributes
144 145 146 |
# File 'lib/xapian_db/document_blueprint.rb', line 144 def attributes @attributes || [] end |
.blueprint_for(klass_or_name) ⇒ DocumentBlueprint
Get the blueprint for a class
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/xapian_db/document_blueprint.rb', line 87 def blueprint_for(klass_or_name) if @blueprints if klass_or_name.is_a?(Class) warn "xapian_db: blueprint_for(Class) is deprecated; use blueprint_for(Symbol) or blueprint_for(String) instead" key = klass_or_name.name else key = klass_or_name.to_s end while key != "Object" && key != "BasicObject" if @blueprints.has_key? key return @blueprints[key] else klass = XapianDb::Utilities.constantize key key = klass.superclass.name end end end return nil end |
.configured?(name) ⇒ Boolean
is a blueprint configured for the given name?
65 66 67 |
# File 'lib/xapian_db/document_blueprint.rb', line 65 def configured?(name) @blueprints && @blueprints.has_key?(name.to_s) end |
.configured_classes ⇒ Array<Class>
Get all configured classes
71 72 73 74 75 76 77 |
# File 'lib/xapian_db/document_blueprint.rb', line 71 def configured_classes if @blueprints @blueprints.keys.map {|class_name| XapianDb::Utilities.constantize(class_name) } else [] end end |
.dependencies_for(klass_name, changed_attrs) ⇒ Object
79 80 81 82 83 |
# File 'lib/xapian_db/document_blueprint.rb', line 79 def dependencies_for(klass_name, changed_attrs) @blueprints.values.map(&:dependencies) .flatten .select{ |dependency| dependency.dependent_on == klass_name && dependency.interested_in?(changed_attrs) } end |
.reset ⇒ Object
reset the blueprint setup
59 60 61 |
# File 'lib/xapian_db/document_blueprint.rb', line 59 def reset @blueprints = {} end |
.searchable_prefixes ⇒ Array<String>
Return an array of all configured text methods in any blueprint
138 139 140 |
# File 'lib/xapian_db/document_blueprint.rb', line 138 def searchable_prefixes @searchable_prefixes || [] end |
.setup(klass_or_name) {|blueprint| ... } ⇒ Object
Configure the blueprint for a class. Available options:
-
adapter (see #adapter for details)
-
attribute (see #attribute for details)
-
index (see #index for details)
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/xapian_db/document_blueprint.rb', line 36 def setup(klass_or_name, &block) name = class_name_from klass_or_name @blueprints ||= {} blueprint = DocumentBlueprint.new yield blueprint if block_given? # configure the blueprint through the block validate_type_consistency_on blueprint # Remove a previously loaded blueprint for this class to avoid stale blueprint definitions @blueprints.delete_if { |indexed_class, blueprint| indexed_class == name } @blueprints[name] = blueprint lazy_load_adapter_for blueprint, name @searchable_prefixes = @blueprints.values.map { |blueprint| blueprint.searchable_prefixes }.flatten.compact.uniq || [] # We can always do a field search on the name of the indexed class @searchable_prefixes << "indexed_class" @attributes = @blueprints.values.map { |blueprint| blueprint.attribute_names}.flatten.compact.uniq.sort || [] blueprint end |
.type_info_for(attribute) ⇒ Symbol
Get the type info of an attribute
128 129 130 131 132 133 134 |
# File 'lib/xapian_db/document_blueprint.rb', line 128 def type_info_for(attribute) return nil if @blueprints.nil? @blueprints.values.each do |blueprint| return blueprint.type_map[attribute] if blueprint.type_map.has_key?(attribute) end nil end |
.value_number_for(attribute) ⇒ Integer
Get the value number for an attribute. Please note that this is not the index in the values array of a xapian document but the valueno. Therefore, document.values returns the wrong data, use document.value(value_number) instead.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/xapian_db/document_blueprint.rb', line 112 def value_number_for(attribute) return 0 if attribute.to_sym == :indexed_class return 1 if attribute.to_sym == :natural_sort_order raise ArgumentError.new "attribute #{attribute} is not configured in any blueprint" if @attributes.nil? position = @attributes.index attribute.to_sym if position # We add 2 because slot 0 and 1 are reserved for indexed_class and natural_sort_order return position + 2 else raise ArgumentError.new "attribute #{attribute} is not configured in any blueprint" end end |
Instance Method Details
#_adapter ⇒ Object
return the adpater to use for this blueprint
293 294 295 |
# File 'lib/xapian_db/document_blueprint.rb', line 293 def _adapter @_adapter || XapianDb::Config.adapter || XapianDb::Adapters::GenericAdapter end |
#accessors_module ⇒ Module
Lazily build and return a module that implements accessors for each field
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/xapian_db/document_blueprint.rb', line 228 def accessors_module return @accessors_module unless @accessors_module.nil? @accessors_module = Module.new # Add the accessors for the indexed class and the score @accessors_module.instance_eval do define_method :indexed_class do self.values[0].value end define_method :score do @score end define_method :attributes do blueprint = XapianDb::DocumentBlueprint.blueprint_for indexed_class blueprint.attribute_names.inject({}) { |hash, attr| hash.tap { |hash| hash[attr.to_s] = self.send attr } } end end # Add an accessor for each attribute attribute_names.each do |attribute| index = DocumentBlueprint.value_number_for(attribute) codec = XapianDb::TypeCodec.codec_for @type_map[attribute] @accessors_module.instance_eval do define_method attribute do codec.decode self.value(index) end end end # Let the adapter add its document helper methods (if any) _adapter.add_doc_helper_methods_to(@accessors_module) @accessors_module end |
#adapter(type) ⇒ Object
Set the adapter
287 288 289 290 |
# File 'lib/xapian_db/document_blueprint.rb', line 287 def adapter(type) # We try to guess the adapter name @_adapter = XapianDb::Adapters.const_get("#{camelize(type.to_s)}Adapter") end |
#attribute(name, options = {}, &block) ⇒ Object
Add an attribute to the blueprint. Attributes will be stored in the xapian documents an can be accessed from a search result.
326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/xapian_db/document_blueprint.rb', line 326 def attribute(name, ={}, &block) raise ArgumentError.new("You cannot use #{name} as an attribute name since it is a reserved method name of Xapian::Document") if reserved_method_name?(name) do_not_index = .delete(:index) == false @type_map[name] = (.delete(:as) || :string) if block_given? @attributes_hash[name] = {:block => block}.merge() else @attributes_hash[name] = end self.index(name, , &block) unless do_not_index end |
#attribute_names ⇒ Array<Symbol>
Get the names of all configured attributes sorted alphabetically
189 190 191 |
# File 'lib/xapian_db/document_blueprint.rb', line 189 def attribute_names @attributes_hash.keys.sort end |
#attributes(*attributes) ⇒ Object
Add a list of attributes to the blueprint. Attributes will be stored in the xapian documents ans can be accessed from a search result.
342 343 344 345 346 347 348 349 |
# File 'lib/xapian_db/document_blueprint.rb', line 342 def attributes(*attributes) attributes.each do |attr| raise ArgumentError.new("You cannot use #{attr} as an attribute name since it is a reserved method name of Xapian::Document") if reserved_method_name?(attr) @attributes_hash[attr] = {} @type_map[attr] = :string self.index attr end end |
#autoindex(boolean) ⇒ Object
Should objects for this blueprint be automatically reindexed?
299 300 301 |
# File 'lib/xapian_db/document_blueprint.rb', line 299 def autoindex(boolean) @autoindex = boolean end |
#autoindex? ⇒ Boolean
Get the autoindex value
305 306 307 |
# File 'lib/xapian_db/document_blueprint.rb', line 305 def autoindex? @autoindex end |
#base_query(expression = nil, &block) ⇒ Object
Define a base query to select one or all objects of the indexed class. The reason for a base query is to optimize the query avoiding th 1+n problematic. The base query should only include joins(…) and includes(…) calls.
396 397 398 399 400 401 402 |
# File 'lib/xapian_db/document_blueprint.rb', line 396 def base_query(expression = nil, &block) if expression warn "xapian_db: directly passing a base query in a blueprint configuration is deprecated, wrap them in a block" block = lambda { expression } end @lazy_base_query = block end |
#block_for_attribute(attribute) ⇒ Block
Get the block associated with an attribute
196 197 198 |
# File 'lib/xapian_db/document_blueprint.rb', line 196 def block_for_attribute(attribute) @attributes_hash[attribute][:block] end |
#dependency(klass_name, when_changed: [], &block) ⇒ Object
413 414 415 |
# File 'lib/xapian_db/document_blueprint.rb', line 413 def dependency(klass_name, when_changed: [], &block) @dependencies << Dependency.new(klass_name.to_s, when_changed, block) end |
#ignore_if(&block) ⇒ Object
Add a block of code that evaluates if a model should not be indexed
386 387 388 |
# File 'lib/xapian_db/document_blueprint.rb', line 386 def ignore_if &block @ignore_expression = block end |
#index(*args, &block) ⇒ Object
Add an indexed value to the blueprint. Indexed values are not accessible from a search result. Available options:
-
:weight (default: 1) The weight for this indexed value
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/xapian_db/document_blueprint.rb', line 367 def index(*args, &block) case args.size when 1 @indexed_methods_hash[args.first] = IndexOptions.new(:weight => 1, :block => block) when 2 # Is it a method name with options? if args.last.is_a? Hash = args.last assert_valid_keys , :weight, :prefixed, :no_split @indexed_methods_hash[args.first] = IndexOptions.new(.merge(:block => block)) else add_indexes_from args end else # multiple arguments add_indexes_from args end end |
#indexed_method_names ⇒ Array<Symbol>
Get the names of all configured index methods sorted alphabetically
202 203 204 |
# File 'lib/xapian_db/document_blueprint.rb', line 202 def indexed_method_names @indexed_methods_hash.keys.sort end |
#indexer_preprocess_callback(method) ⇒ Object
Set the indexer preprocess callback.
430 431 432 |
# File 'lib/xapian_db/document_blueprint.rb', line 430 def indexer_preprocess_callback(method) @indexer_preprocess_callback = method end |
#natural_sort_order(name = nil, &block) ⇒ Object
Define the natural sort order. Pass a method name or a block, but not both
408 409 410 411 |
# File 'lib/xapian_db/document_blueprint.rb', line 408 def natural_sort_order(name=nil, &block) raise ArgumentError.new("natural_sort_order accepts a method name or a block, but not both") if name && block @_natural_sort_order = name || block end |
#options_for_indexed_method(method) ⇒ IndexOptions
Get the options for an indexed method
209 210 211 |
# File 'lib/xapian_db/document_blueprint.rb', line 209 def (method) @indexed_methods_hash[method] end |
#preprocess_terms ⇒ Object
Reader for indexer_preprocess_callback. Returns the terms preprocessing method for this blueprint, the global method from config or nil.
436 437 438 |
# File 'lib/xapian_db/document_blueprint.rb', line 436 def preprocess_terms @indexer_preprocess_callback || XapianDb::Config.preprocess_terms end |
#searchable_prefixes ⇒ Array<String>
Return an array of all configured text methods in this blueprint
215 216 217 |
# File 'lib/xapian_db/document_blueprint.rb', line 215 def searchable_prefixes @searchable_prefixes ||= indexed_method_names end |
#should_index?(obj) ⇒ Boolean
Should the object go into the index? Evaluates an ignore expression, if defined
221 222 223 224 |
# File 'lib/xapian_db/document_blueprint.rb', line 221 def should_index? obj return obj.instance_eval(&@ignore_expression) == false if @ignore_expression true end |