Module: Searchkick::Model

Defined in:
lib/searchkick/model.rb

Instance Method Summary collapse

Instance Method Details

#searchkick(options = {}) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/searchkick/model.rb', line 4

def searchkick(options = {})
  class_eval do
    cattr_reader :searchkick_options, :searchkick_env, :searchkick_klass, :searchkick_index

    class_variable_set :@@searchkick_options, options.dup
    class_variable_set :@@searchkick_env, ENV["RACK_ENV"] || ENV["RAILS_ENV"] || "development"
    class_variable_set :@@searchkick_klass, self

    # set index name
    # TODO support proc
    index_name = options[:index_name] || [options[:index_prefix], model_name.plural, searchkick_env].compact.join("_")
    class_variable_set :@@searchkick_index, Tire::Index.new(index_name)

    extend Searchkick::Search
    extend Searchkick::Reindex
    include Searchkick::Similar

    def reindex
      index = self.class.searchkick_index
      if destroyed?
        index.remove self
      else
        index.store self
      end
    end

    unless options[:callbacks] == false
      # TODO ability to temporarily disable
      after_save :reindex
      after_destroy :reindex
    end

    def search_data
      respond_to?(:to_hash) ? to_hash : serializable_hash
    end

    def to_indexed_json
      source = search_data

      # stringify fields
      source = source.inject({}){|memo,(k,v)| memo[k.to_s] = v; memo}

      # Mongoid 4 hack
      source["_id"] = source["_id"].to_s if source["_id"]

      options = self.class.searchkick_options

      # conversions
      conversions_field = options[:conversions]
      if conversions_field and source[conversions_field]
        source[conversions_field] = source[conversions_field].map{|k, v| {query: k, count: v} }
      end

      # hack to prevent generator field doesn't exist error
      (options[:suggest] || []).map(&:to_s).each do |field|
        source[field] = nil if !source[field]
      end

      # locations
      (options[:locations] || []).map(&:to_s).each do |field|
        if source[field]
          if source[field].first.is_a?(Array) # array of arrays
            source[field] = source[field].map{|a| a.map(&:to_f).reverse }
          else
            source[field] = source[field].map(&:to_f).reverse
          end
        end
      end

      # change all BigDecimal values to floats due to
      # https://github.com/rails/rails/issues/6033
      # possible loss of precision :/
      cast_big_decimal =
        proc do |obj|
          case obj
          when BigDecimal
            obj.to_f
          when Hash
            obj.each do |k, v|
              obj[k] = cast_big_decimal.call(v)
            end
          when Enumerable
            obj.map! do |v|
              cast_big_decimal.call(v)
            end
          else
            obj
          end
        end

      cast_big_decimal.call(source)

      # p search_data

      source.to_json
    end

    # TODO remove

    def self.document_type
      model_name.to_s.underscore
    end

    def document_type
      self.class.document_type
    end

  end
end