Class | Ultrasphinx::Fields |
In: |
lib/ultrasphinx/fields.rb
|
Parent: | Object |
This is a special singleton configuration class that stores the index field configurations. Rather than using a magic hash and including relevant behavior in Ultrasphinx::Configure and Ultrasphinx::Search, we unify it here.
TYPE_MAP | = | { 'string' => 'text', 'text' => 'text', 'integer' => 'integer', 'date' => 'date', 'datetime' => 'date', 'timestamp' => 'date', 'float' => 'float', 'boolean' => 'bool' |
classes | [RW] | |
types | [RW] |
# File lib/ultrasphinx/fields.rb, line 27 27: def initialize 28: @types = {} 29: @classes = Hash.new([]) 30: @groups = [] 31: end
# File lib/ultrasphinx/fields.rb, line 72 72: def cast(source_string, field) 73: if types[field] == "date" 74: "UNIX_TIMESTAMP(#{source_string})" 75: elsif types[field] == "integer" 76: source_string # "CAST(#{source_string} AS UNSIGNED)" 77: else 78: source_string 79: end + " AS #{field}" 80: end
# File lib/ultrasphinx/fields.rb, line 99 99: def configure(configuration) 100: 101: configuration.each do |model, options| 102: 103: klass = model.constantize 104: save_and_verify_type('class_id', 'integer', nil, klass) 105: save_and_verify_type('class', 'string', nil, klass) 106: 107: begin 108: 109: # Fields are from the model 110: options['fields'] = options['fields'].to_a.map do |entry| 111: extract_table_alias!(entry, klass) 112: extract_field_alias!(entry, klass) 113: 114: unless klass.columns_hash[entry['field']] 115: # XXX I think this is here for migrations 116: Ultrasphinx.say "warning: field #{entry['field']} is not present in #{model}" 117: else 118: save_and_verify_type(entry['as'], klass.columns_hash[entry['field']].type, nil, klass) 119: install_duplicate_fields!(entry, klass) 120: end 121: end 122: 123: # Joins are whatever they are in the target 124: options['include'].to_a.each do |entry| 125: extract_table_alias!(entry, klass) 126: extract_field_alias!(entry, klass) 127: 128: association_model = get_association_model(klass, entry) 129: 130: save_and_verify_type(entry['as'] || entry['field'], association_model.columns_hash[entry['field']].type, nil, klass) 131: install_duplicate_fields!(entry, klass) 132: end 133: 134: # Regular concats are CHAR, group_concats are BLOB and need to be cast to CHAR 135: options['concatenate'].to_a.each do |entry| 136: extract_table_alias!(entry, klass) 137: save_and_verify_type(entry['as'], 'text', nil, klass) 138: install_duplicate_fields!(entry, klass) 139: end 140: 141: rescue ActiveRecord::StatementInvalid 142: Ultrasphinx.say "warning: model #{model} does not exist in the database yet" 143: end 144: end 145: 146: self 147: end
# File lib/ultrasphinx/fields.rb, line 170 170: def extract_field_alias!(entry, klass) 171: unless entry['as'] 172: entry['as'] = entry['field'] 173: end 174: end
# File lib/ultrasphinx/fields.rb, line 177 177: def extract_table_alias!(entry, klass) 178: unless entry['table_alias'] 179: entry['table_alias'] = if entry['field'] and entry['field'].include? "." and entry['association_sql'] 180: # This field is referenced by a table alias in association_sql 181: table_alias, entry['field'] = entry['field'].split(".") 182: table_alias 183: elsif get_association(klass, entry) 184: # Refers to the association 185: get_association(klass, entry).name 186: elsif entry['association_sql'] 187: # Refers to the association_sql class's table 188: entry['class_name'].constantize.table_name 189: else 190: # Refers to this class 191: klass.table_name 192: end 193: end 194: end
# File lib/ultrasphinx/fields.rb, line 34 34: def groups 35: @groups.compact.sort_by do |string| 36: string[/= (.*)/, 1] 37: end 38: end
# File lib/ultrasphinx/fields.rb, line 150 150: def install_duplicate_fields!(entry, klass) 151: if entry['facet'] 152: # Source must be a string 153: save_and_verify_type(entry['as'], 'text', nil, klass, 154: "#{klass}##{entry['as']}: 'facet' option is only valid for text fields; numeric fields are enabled by default") 155: # Install facet column 156: save_and_verify_type("#{entry['as']}_facet", 'integer', nil, klass) 157: end 158: 159: if entry['sortable'] 160: # Source must be a string 161: save_and_verify_type(entry['as'], 'text', nil, klass, 162: "#{klass}##{entry['as']}: 'sortable' option is only valid for text columns; numeric fields are enabled by default") 163: # Install sortable column 164: save_and_verify_type("#{entry['as']}_sortable", 'text', true, klass) 165: end 166: entry 167: end
# File lib/ultrasphinx/fields.rb, line 83 83: def null(field) 84: case types[field] 85: when 'text' 86: "''" 87: when 'integer', 'float', 'bool' 88: "0" 89: when 'date' 90: "18000" # Midnight on 1/1/1970 91: when nil 92: raise "Field #{field} is missing" 93: else 94: raise "Field #{field} does not have a valid type #{types[field]}." 95: end + " AS #{field}" 96: end
# File lib/ultrasphinx/fields.rb, line 41 41: def save_and_verify_type(field, new_type, string_sortable, klass, msg = nil) 42: # Smoosh fields together based on their name in the Sphinx query schema 43: field, new_type = field.to_s, TYPE_MAP[new_type.to_s] 44: 45: if types[field] 46: # Existing field name; verify its type 47: msg ||= "Column type mismatch for #{field.inspect}; was already #{types[field].inspect}, but is now #{new_type.inspect}." 48: raise ConfigurationError, msg unless types[field] == new_type 49: classes[field] = (classes[field] + [klass]).uniq 50: 51: else 52: # New field 53: types[field] = new_type 54: classes[field] = [klass] 55: 56: @groups << case new_type 57: when 'integer' 58: "sql_attr_uint = #{field}" 59: when 'float' 60: "sql_attr_float = #{field}" 61: when 'bool' 62: "sql_attr_bool = #{field}" 63: when 'date' 64: "sql_attr_timestamp = #{field}" 65: when 'text' 66: "sql_attr_str2ordinal = #{field}" if string_sortable 67: end 68: end 69: end