Class: Solrizer::FieldMapper

Inherits:
Object
  • Object
show all
Includes:
Loggable
Defined in:
lib/solrizer/field_mapper.rb

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (FieldMapper) initialize

Returns a new instance of FieldMapper



115
116
117
# File 'lib/solrizer/field_mapper.rb', line 115

def initialize
  self.id_field = self.class.id_field
end

Instance Attribute Details

- (Object) default_index_types (readonly)

—— Instance methods ——



107
108
109
# File 'lib/solrizer/field_mapper.rb', line 107

def default_index_types
  @default_index_types
end

- (Object) id_field (readonly)

—— Instance methods ——



107
108
109
# File 'lib/solrizer/field_mapper.rb', line 107

def id_field
  @id_field
end

Instance Method Details

- (Object) extract_type(value)



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/solrizer/field_mapper.rb', line 166

def extract_type(value)
  case value
  when NilClass
  when Fixnum
    :integer
  when DateTime
    :time
  when TrueClass, FalseClass
    :boolean
  else
    value.class.to_s.underscore.to_sym
  end
end

- (Object) index_type_macro(index_type)

search through the descriptors (class attribute) until a module is found that responds to index_type, then call it.

Parameters:

  • index_type (Symbol)


138
139
140
141
142
143
144
145
# File 'lib/solrizer/field_mapper.rb', line 138

def index_type_macro(index_type)
  klass = self.class.descriptors.find { |klass| klass.respond_to? index_type}
  if klass
    klass.send(index_type)
  else
    raise UnknownIndexMacro, "Unable to find `#{index_type}' in #{self.class.descriptors}"
  end
end

- (Descriptor) indexer(index_type)

Parameters:

  • index_type (Symbol, String, Descriptor)

    is a Descriptor, a symbol that references a method that returns a Descriptor, or a string which will be used as the suffix.

Returns:

Raises:



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/solrizer/field_mapper.rb', line 149

def indexer(index_type)
  index_type = case index_type
  when Symbol
    index_type_macro(index_type)
  when String
    StringDescriptor.new(index_type)
  when Descriptor 
    index_type
  else
    raise Solrizer::InvalidIndexDescriptor, "#{index_type.class} is not a valid indexer_type. Use a String, Symbol or Descriptor."
    #IndexDescriptors::Descriptor.new(*index_type)
  end

  raise InvalidIndexDescriptor, "index type should be an Descriptor, you passed: #{index_type.class}" unless index_type.kind_of? Descriptor
  index_type
end

- (String) solr_name(field_name, *opts)

Given a field name, index_type, etc., returns the corresponding Solr name. TODO field type is the input format, maybe we could just detect that?

Parameters:

  • field_name (String)

    the ruby (term) name which will get a suffix appended to become a Solr field name

  • opts
    • index_type is only needed if the FieldDescriptor requires it (e.g. :searcahble)

Returns:

  • (String)

    name of the solr field, based on the params



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/solrizer/field_mapper.rb', line 124

def solr_name(field_name, *opts)
  index_type, args = if opts.first.kind_of? Hash
    [:stored_searchable, opts.first]
  elsif opts.empty?
    [:stored_searchable, {type: :text}]
  else
    [opts[0], opts[1] || {type: :string}]
  end

  indexer(index_type).name_and_converter(field_name, args).first
end

- (Object) solr_names_and_values(field_name, field_value, index_types)

Given a field name-value pair, a data type, and an array of index types, returns a hash of mapped names and values. The values in the hash are arrays, and may contain multiple values.



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/solrizer/field_mapper.rb', line 183

def solr_names_and_values(field_name, field_value, index_types)
  return {} unless field_value
  
  # Determine the set of index types
  index_types = Array(index_types)
  index_types.uniq!
  index_types.dup.each do |index_type|
    if index_type.to_s =~ /^not_(.*)/
      index_types.delete index_type # not_foo
      index_types.delete $1.to_sym  # foo
    end
  end
  
  # Map names and values
  
  results = {}

  # Time seems to extend enumerable, so wrap it so we don't interate over each of its elements.
  field_value = [field_value] if field_value.kind_of? Time
  
  index_types.each do |index_type|
    Array(field_value).each do |single_value|
      # Get mapping for field
      descriptor = indexer(index_type)
      data_type = extract_type(single_value)
      name, converter = descriptor.name_and_converter(field_name, type: data_type)
      next unless name

      # Is there a custom converter?
      # TODO instead of a custom converter, look for input data type and output data type. Create a few methods that can do that cast.

      value = if converter
        if converter.arity == 1
          converter.call(single_value)
        else
          converter.call(single_value, field_name)
        end
      elsif data_type == :boolean
        single_value
      else
        single_value.to_s
      end
      
      # Add mapped name & value, unless it's a duplicate
      if descriptor.evaluate_suffix(data_type).multivalued?
        values = (results[name] ||= [])
        values << value unless value.nil? || values.include?(value)
      else
        logger.warn "Setting #{name} to `#{value}', but it already had `#{results[name]}'" if results[name]
        results[name] = value
      end
    end
  end
    
  results
end