Class: Solrizer::FieldMapper

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFieldMapper

Returns a new instance of FieldMapper.



112
113
114
# File 'lib/solrizer/field_mapper.rb', line 112

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

Instance Attribute Details

#default_index_typesObject (readonly)

—— Instance methods ——



104
105
106
# File 'lib/solrizer/field_mapper.rb', line 104

def default_index_types
  @default_index_types
end

#id_fieldObject (readonly)

—— Instance methods ——



104
105
106
# File 'lib/solrizer/field_mapper.rb', line 104

def id_field
  @id_field
end

Instance Method Details

#extract_type(value) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/solrizer/field_mapper.rb', line 163

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

#index_type_macro(index_type) ⇒ Object

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

Parameters:

  • index_type (Symbol)


135
136
137
138
139
140
141
142
# File 'lib/solrizer/field_mapper.rb', line 135

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

#indexer(index_type) ⇒ Descriptor

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:



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

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

#solr_name(field_name, *opts) ⇒ String

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



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/solrizer/field_mapper.rb', line 121

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

#solr_names_and_values(field_name, field_value, index_types) ⇒ Object

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.



180
181
182
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
# File 'lib/solrizer/field_mapper.rb', line 180

def solr_names_and_values(field_name, field_value, index_types)
  return {} if field_value.nil?
  
  # 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
        Solrizer.logger.warn "Setting #{name} to `#{value}', but it already had `#{results[name]}'" if results[name] && Solrizer.logger
        results[name] = value
      end
    end
  end
    
  results
end