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