Class: Runestone::Settings

Inherits:
Object
  • Object
show all
Defined in:
lib/runestone/settings.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, name:, dictionary:, &block) ⇒ Settings

Returns a new instance of Settings.



5
6
7
8
9
10
# File 'lib/runestone/settings.rb', line 5

def initialize(model, name: , dictionary: , &block)
  @name = name
  @dictionary = dictionary
  @indexes = {}
  instance_exec(&block)
end

Instance Attribute Details

#dictionaryObject (readonly)

Returns the value of attribute dictionary.



3
4
5
# File 'lib/runestone/settings.rb', line 3

def dictionary
  @dictionary
end

#indexesObject (readonly)

Returns the value of attribute indexes.



3
4
5
# File 'lib/runestone/settings.rb', line 3

def indexes
  @indexes
end

Instance Method Details

#attribute(*names, &block) ⇒ Object Also known as: attributes



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/runestone/settings.rb', line 16

def attribute(*names, &block)
  deps = if block_given? and names.length > 2
    raise ArgumentError.new('Cannot pass multiple attribute names if block given')
  else
    names.length > 1 ? names.pop : names.first
  end
  deps = deps.to_s if !deps.is_a?(Proc)

  @attributes ||= {}
  names.each do |name|
    @attributes[name.to_sym] = [block ? block : nil, deps]
  end
end

#changed?(record) ⇒ Boolean

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
53
54
55
# File 'lib/runestone/settings.rb', line 45

def changed?(record)
  @attributes.detect do |name, value|
    if value[1].is_a?(Proc)
      record.instance_exec(&value[1])
    elsif record.attribute_names.include?(value[1])
      record.previous_changes.has_key?(value[1])
    elsif record._reflections[value[1]] && association = record.association(value[1])
      association.loaded? && association.changed_for_autosave?
    end
  end
end

#corpus(data) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/runestone/settings.rb', line 76

def corpus(data)
  words = []
  
  @indexes.each do |weight, paths|
    paths.each do |path|
      dig(data, path.to_s.split('.')).each do |value|
        next if !value
        value.to_s.split(/\s+/).each do |word|
          words << word.downcase.gsub(/\A\W/, '').gsub(/\W\Z/, '')
        end
      end
    end
  end
  
  words
end

#dig(data, keys) ⇒ Object



112
113
114
115
116
117
118
119
120
121
# File 'lib/runestone/settings.rb', line 112

def dig(data, keys)
  if data.is_a?(Hash)
    key = keys.shift
    dig(data[key.to_sym] || data[key.to_s], keys)
  elsif data.is_a?(Array)
    data.map{ |d| dig(d, keys.dup) }.flatten.compact
  else
    [data]
  end
end

#extract_attributes(record) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/runestone/settings.rb', line 31

def extract_attributes(record)
  attributes = {}

  @attributes.each do |name, value|
    attributes[name] = if value[0].is_a?(Proc)
      record.instance_exec(&value[0])
    else
      rv = record.send(name)
    end
  end

  remove_nulls(attributes)
end

#index(*args, weight: 1) ⇒ Object



12
13
14
# File 'lib/runestone/settings.rb', line 12

def index(*args, weight: 1)
  @indexes[weight] = args.map(&:to_s)
end

#remove_nulls(value) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/runestone/settings.rb', line 93

def remove_nulls(value)
  if value.is_a?(Hash)
    nh = {}
    value.each do |k, v|
      nh[k] = if v.is_a?(Hash) || v.is_a?(Array)
        remove_nulls(v)
      elsif !v.nil?
        v.is_a?(String) ? v.unicode_normalize(:nfc) : v
      end
      nh.delete(k) if nh[k].nil? || (nh[k].is_a?(Hash) && nh[k].empty?)
    end
    nh
  elsif value.is_a?(Array)
    value.select{|i| !i.nil? && !i.empty? }.map { |i| remove_nulls(i) }
  else
    value
  end
end

#vectorize(data) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/runestone/settings.rb', line 57

def vectorize(data)
  conn = Runestone::Model.connection
  tsvector = []

  @indexes.each do |weight, paths|
    tsweight = {4 => 'D', 3 => 'C', 2 => 'B', 1 => 'A'}[weight]
    paths.each do |path|
      path = path.to_s.split('.')
      
      dig(data, path).each do |value|
        next if !value
        language = value.to_s.size <= 5 ? 'simple' : @dictionary
        tsvector << "setweight(to_tsvector(#{conn.quote(language)}, #{conn.quote(value.to_s.downcase)}), #{conn.quote(tsweight)})"
      end
    end
  end
  tsvector.empty? ? ["to_tsvector('')"] : tsvector
end