diff options
Diffstat (limited to 'vendor/plugins/thinking-sphinx/lib/thinking_sphinx/field.rb')
| -rw-r--r-- | vendor/plugins/thinking-sphinx/lib/thinking_sphinx/field.rb | 172 |
1 files changed, 0 insertions, 172 deletions
diff --git a/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/field.rb b/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/field.rb deleted file mode 100644 index 9edaede..0000000 --- a/vendor/plugins/thinking-sphinx/lib/thinking_sphinx/field.rb +++ /dev/null | |||
| @@ -1,172 +0,0 @@ | |||
| 1 | module ThinkingSphinx | ||
| 2 | # Fields - holding the string data which Sphinx indexes for your searches. | ||
| 3 | # This class isn't really useful to you unless you're hacking around with the | ||
| 4 | # internals of Thinking Sphinx - but hey, don't let that stop you. | ||
| 5 | # | ||
| 6 | # One key thing to remember - if you're using the field manually to | ||
| 7 | # generate SQL statements, you'll need to set the base model, and all the | ||
| 8 | # associations. Which can get messy. Use Index.link!, it really helps. | ||
| 9 | # | ||
| 10 | class Field | ||
| 11 | attr_accessor :alias, :columns, :sortable, :associations, :model, :infixes, | ||
| 12 | :prefixes, :faceted | ||
| 13 | |||
| 14 | # To create a new field, you'll need to pass in either a single Column | ||
| 15 | # or an array of them, and some (optional) options. The columns are | ||
| 16 | # references to the data that will make up the field. | ||
| 17 | # | ||
| 18 | # Valid options are: | ||
| 19 | # - :as => :alias_name | ||
| 20 | # - :sortable => true | ||
| 21 | # - :infixes => true | ||
| 22 | # - :prefixes => true | ||
| 23 | # | ||
| 24 | # Alias is only required in three circumstances: when there's | ||
| 25 | # another attribute or field with the same name, when the column name is | ||
| 26 | # 'id', or when there's more than one column. | ||
| 27 | # | ||
| 28 | # Sortable defaults to false - but is quite useful when set to true, as | ||
| 29 | # it creates an attribute with the same string value (which Sphinx converts | ||
| 30 | # to an integer value), which can be sorted by. Thinking Sphinx is smart | ||
| 31 | # enough to realise that when you specify fields in sort statements, you | ||
| 32 | # mean their respective attributes. | ||
| 33 | # | ||
| 34 | # If you have partial matching enabled (ie: enable_star), then you can | ||
| 35 | # specify certain fields to have their prefixes and infixes indexed. Keep | ||
| 36 | # in mind, though, that Sphinx's default is _all_ fields - so once you | ||
| 37 | # highlight a particular field, no other fields in the index will have | ||
| 38 | # these partial indexes. | ||
| 39 | # | ||
| 40 | # Here's some examples: | ||
| 41 | # | ||
| 42 | # Field.new( | ||
| 43 | # Column.new(:name) | ||
| 44 | # ) | ||
| 45 | # | ||
| 46 | # Field.new( | ||
| 47 | # [Column.new(:first_name), Column.new(:last_name)], | ||
| 48 | # :as => :name, :sortable => true | ||
| 49 | # ) | ||
| 50 | # | ||
| 51 | # Field.new( | ||
| 52 | # [Column.new(:posts, :subject), Column.new(:posts, :content)], | ||
| 53 | # :as => :posts, :prefixes => true | ||
| 54 | # ) | ||
| 55 | # | ||
| 56 | def initialize(columns, options = {}) | ||
| 57 | @columns = Array(columns) | ||
| 58 | @associations = {} | ||
| 59 | |||
| 60 | raise "Cannot define a field with no columns. Maybe you are trying to index a field with a reserved name (id, name). You can fix this error by using a symbol rather than a bare name (:id instead of id)." if @columns.empty? || @columns.any? { |column| !column.respond_to?(:__stack) } | ||
| 61 | |||
| 62 | @alias = options[:as] | ||
| 63 | @sortable = options[:sortable] || false | ||
| 64 | @infixes = options[:infixes] || false | ||
| 65 | @prefixes = options[:prefixes] || false | ||
| 66 | @faceted = options[:facet] || false | ||
| 67 | end | ||
| 68 | |||
| 69 | # Get the part of the SELECT clause related to this field. Don't forget | ||
| 70 | # to set your model and associations first though. | ||
| 71 | # | ||
| 72 | # This will concatenate strings if there's more than one data source or | ||
| 73 | # multiple data values (has_many or has_and_belongs_to_many associations). | ||
| 74 | # | ||
| 75 | def to_select_sql | ||
| 76 | clause = @columns.collect { |column| | ||
| 77 | column_with_prefix(column) | ||
| 78 | }.join(', ') | ||
| 79 | |||
| 80 | clause = adapter.concatenate(clause) if concat_ws? | ||
| 81 | clause = adapter.group_concatenate(clause) if is_many? | ||
| 82 | |||
| 83 | "#{adapter.cast_to_string clause } AS #{quote_column(unique_name)}" | ||
| 84 | end | ||
| 85 | |||
| 86 | # Get the part of the GROUP BY clause related to this field - if one is | ||
| 87 | # needed. If not, all you'll get back is nil. The latter will happen if | ||
| 88 | # there's multiple data values (read: a has_many or has_and_belongs_to_many | ||
| 89 | # association). | ||
| 90 | # | ||
| 91 | def to_group_sql | ||
| 92 | case | ||
| 93 | when is_many?, ThinkingSphinx.use_group_by_shortcut? | ||
| 94 | nil | ||
| 95 | else | ||
| 96 | @columns.collect { |column| | ||
| 97 | column_with_prefix(column) | ||
| 98 | } | ||
| 99 | end | ||
| 100 | end | ||
| 101 | |||
| 102 | # Returns the unique name of the field - which is either the alias of | ||
| 103 | # the field, or the name of the only column - if there is only one. If | ||
| 104 | # there isn't, there should be an alias. Else things probably won't work. | ||
| 105 | # Consider yourself warned. | ||
| 106 | # | ||
| 107 | def unique_name | ||
| 108 | if @columns.length == 1 | ||
| 109 | @alias || @columns.first.__name | ||
| 110 | else | ||
| 111 | @alias | ||
| 112 | end | ||
| 113 | end | ||
| 114 | |||
| 115 | def to_facet | ||
| 116 | return nil unless @faceted | ||
| 117 | |||
| 118 | ThinkingSphinx::Facet.new(self) | ||
| 119 | end | ||
| 120 | |||
| 121 | private | ||
| 122 | |||
| 123 | def adapter | ||
| 124 | @adapter ||= @model.sphinx_database_adapter | ||
| 125 | end | ||
| 126 | |||
| 127 | def quote_column(column) | ||
| 128 | @model.connection.quote_column_name(column) | ||
| 129 | end | ||
| 130 | |||
| 131 | # Indication of whether the columns should be concatenated with a space | ||
| 132 | # between each value. True if there's either multiple sources or multiple | ||
| 133 | # associations. | ||
| 134 | # | ||
| 135 | def concat_ws? | ||
| 136 | @columns.length > 1 || multiple_associations? | ||
| 137 | end | ||
| 138 | |||
| 139 | # Checks whether any column requires multiple associations (which only | ||
| 140 | # happens for polymorphic situations). | ||
| 141 | # | ||
| 142 | def multiple_associations? | ||
| 143 | associations.any? { |col,assocs| assocs.length > 1 } | ||
| 144 | end | ||
| 145 | |||
| 146 | # Builds a column reference tied to the appropriate associations. This | ||
| 147 | # dives into the associations hash and their corresponding joins to | ||
| 148 | # figure out how to correctly reference a column in SQL. | ||
| 149 | # | ||
| 150 | def column_with_prefix(column) | ||
| 151 | if column.is_string? | ||
| 152 | column.__name | ||
| 153 | elsif associations[column].empty? | ||
| 154 | "#{@model.quoted_table_name}.#{quote_column(column.__name)}" | ||
| 155 | else | ||
| 156 | associations[column].collect { |assoc| | ||
| 157 | assoc.has_column?(column.__name) ? | ||
| 158 | "#{@model.connection.quote_table_name(assoc.join.aliased_table_name)}" + | ||
| 159 | ".#{quote_column(column.__name)}" : | ||
| 160 | nil | ||
| 161 | }.compact.join(', ') | ||
| 162 | end | ||
| 163 | end | ||
| 164 | |||
| 165 | # Could there be more than one value related to the parent record? If so, | ||
| 166 | # then this will return true. If not, false. It's that simple. | ||
| 167 | # | ||
| 168 | def is_many? | ||
| 169 | associations.values.flatten.any? { |assoc| assoc.is_many? } | ||
| 170 | end | ||
| 171 | end | ||
| 172 | end | ||
