Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

lovd now runs shpinx

  • Loading branch information...
commit cde8c79b8879af54d2d2fb61b872b640317c812f 1 parent c6c274e
@stevenbristol authored
View
3  .gitignore
@@ -8,8 +8,7 @@ log/*.pid
tmp
config/database.yml
config/*.sphinx.conf
-index
public/system
public/javascripts/less_routes.js
test/public/system
-vendor/rails
+vendor/rails
View
15 README
@@ -28,7 +28,7 @@ Quick Setup (currently for non-Windows users only - due to ferret gem issues):
1. Edit config/database.yml.tmp to reflect the database names you would like to use.
2. Edit config/environments/production.rb so asset_host reflects the name of the production asset server
3. cp config/database.yml.tmp config/database.yml
- 4. MAKE SURE YOU UPGRADE TO GEMS 1.2.
+ 4. MAKE SURE YOU UPGRADE TO GEMS 1.3.
5. RUN gem sources -a http://gems.github.com
6. rake lovdbyless:getting_started
7. rake test
@@ -51,11 +51,6 @@ Install the Required Gems:
TIPS:
-Installing ferret on Windows
-1. Running gem install ferret does not work. Instead, download the gem directly from http://rubyforge.org/frs/?group_id=1028
-2. Download file: ferret-0.11.6-mswin32.gem
-3. From the directory you downloaded the gem to: gem install ferret-0.11.6-mswin32.gem
-
Installing ImageMagick and RMagick
See these posts for tips:
http://b.lesseverything.com/2007/9/26/installing-imagemagick-and-rmagick-on-mac-os-x
@@ -84,11 +79,11 @@ Setup default values:
12. Edit application.css to suite your tastes.
13. Edit app/views/home/terms.
-Configure Ferret:
+Configure Thinking Sphinx:
-14. Feel free to replace ferret with the search engine of your choice.
-15. Acts_s_ferret home page: http://projects.jkraemer.net/acts_as_ferret/wiki.
-16. We recommend using the drb server as described here: http://projects.jkraemer.net/acts_as_ferret/wiki/DrbServer.
+14. rake ts:start
+15. rake ts:in
+16. Rake ts:start again in sphinx is not running.
Start Lovd By Less:
View
2  app/controllers/admin/users_controller.rb
@@ -36,6 +36,6 @@ def search_results
else
p = []
end
- @results = Profile.search_results((p.delete(:q) || ''), :page => @page, :per_page => @per_page)
+ @results = Profile.search(p.delete(:q) || '')
end
end
View
2  app/controllers/profiles_controller.rb
@@ -120,6 +120,6 @@ def search_results
else
p = []
end
- @results = Profile.search_results((p.delete(:q) || ''), :page => @page, :per_page => @per_page)
+ @results = Profile.search(p.delete(:q) || '')
end
end
View
7 app/models/profile.rb
@@ -188,13 +188,6 @@ def can_send_messages
- def self.search_results query = '', options = {}
- arr = self.search(query)
- logger.debug arr.inspect
- arr
- end
-
-
protected
def fix_http str
View
4 test/functional/profiles_controller_test.rb
@@ -4,7 +4,7 @@ class ProfilesControllerTest < ActionController::TestCase
context 'on POST to :search' do
setup do
- Profile.stubs(:search_results).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
+ Profile.stubs(:search).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
post :search, {:q => 'user'}
end
@@ -15,7 +15,7 @@ class ProfilesControllerTest < ActionController::TestCase
context 'on GET to :index' do
setup do
- Profile.stubs(:search_results).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
+ Profile.stubs(:search).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
get :index
end
View
2  test/integration/spider_test.rb
@@ -32,7 +32,7 @@ def test_spider_user
def test_spider_admin
- Profile.stubs(:search_results).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
+ Profile.stubs(:search).returns(ThinkingSphinx::Collection.new(1, 1, 1, 1))
puts ''
puts 'test_spider_admin'
get "/login"
View
224 vendor/plugins/thinking-sphinx/lib/thinking_sphinx/index/builder.rb
@@ -0,0 +1,224 @@
+module ThinkingSphinx
+ class Index
+ # The Builder class is the core for the index definition block processing.
+ # There are four methods you really need to pay attention to:
+ # - indexes (aliased to includes and attribute)
+ # - has (aliased to attribute)
+ # - where
+ # - set_property (aliased to set_properties)
+ #
+ # The first two of these methods allow you to define what data makes up
+ # your indexes. #where provides a method to add manual SQL conditions, and
+ # set_property allows you to set some settings on a per-index basis. Check
+ # out each method's documentation for better ideas of usage.
+ #
+ class Builder
+ class << self
+ # No idea where this is coming from - haven't found it in any ruby or
+ # rails documentation. It's not needed though, so it gets undef'd.
+ # Hopefully the list of methods that get in the way doesn't get too
+ # long.
+ HiddenMethods = [:parent, :name, :id, :type].each { |method|
+ define_method(method) {
+ caller.grep(/irb.completion/).empty? ? method_missing(method) : super
+ }
+ }
+
+ attr_accessor :fields, :attributes, :properties, :conditions,
+ :groupings
+
+ # Set up all the collections. Consider this the equivalent of an
+ # instance's initialize method.
+ #
+ def setup
+ @fields = []
+ @attributes = []
+ @properties = {}
+ @conditions = []
+ @groupings = []
+ end
+
+ # This is how you add fields - the strings Sphinx looks at - to your
+ # index. Technically, to use this method, you need to pass in some
+ # columns and options - but there's some neat method_missing stuff
+ # happening, so lets stick to the expected syntax within a define_index
+ # block.
+ #
+ # Expected options are :as, which points to a column alias in symbol
+ # form, and :sortable, which indicates whether you want to sort by this
+ # field.
+ #
+ # Adding Single-Column Fields:
+ #
+ # You can use symbols or methods - and can chain methods together to
+ # get access down the associations tree.
+ #
+ # indexes :id, :as => :my_id
+ # indexes :name, :sortable => true
+ # indexes first_name, last_name, :sortable => true
+ # indexes users.posts.content, :as => :post_content
+ # indexes users(:id), :as => :user_ids
+ #
+ # Keep in mind that if any keywords for Ruby methods - such as id or
+ # name - clash with your column names, you need to use the symbol
+ # version (see the first, second and last examples above).
+ #
+ # If you specify multiple columns (example #2), a field will be created
+ # for each. Don't use the :as option in this case. If you want to merge
+ # those columns together, continue reading.
+ #
+ # Adding Multi-Column Fields:
+ #
+ # indexes [first_name, last_name], :as => :name
+ # indexes [location, parent.location], :as => :location
+ #
+ # To combine multiple columns into a single field, you need to wrap
+ # them in an Array, as shown by the above examples. There's no
+ # limitations on whether they're symbols or methods or what level of
+ # associations they come from.
+ #
+ # Adding SQL Fragment Fields
+ #
+ # You can also define a field using an SQL fragment, useful for when
+ # you would like to index a calculated value.
+ #
+ # indexes "age < 18", :as => :minor
+ #
+ def indexes(*args)
+ options = args.extract_options!
+ args.each do |columns|
+ fields << Field.new(FauxColumn.coerce(columns), options)
+
+ if fields.last.sortable
+ attributes << Attribute.new(
+ fields.last.columns.collect { |col| col.clone },
+ options.merge(
+ :type => :string,
+ :as => fields.last.unique_name.to_s.concat("_sort").to_sym
+ )
+ )
+ end
+ end
+ end
+ alias_method :field, :indexes
+ alias_method :includes, :indexes
+
+ # This is the method to add attributes to your index (hence why it is
+ # aliased as 'attribute'). The syntax is the same as #indexes, so use
+ # that as starting point, but keep in mind the following points.
+ #
+ # An attribute can have an alias (the :as option), but it is always
+ # sortable - so you don't need to explicitly request that. You _can_
+ # specify the data type of the attribute (the :type option), but the
+ # code's pretty good at figuring that out itself from peering into the
+ # database.
+ #
+ # Attributes are limited to the following types: integers, floats,
+ # datetimes (converted to timestamps), booleans and strings. Don't
+ # forget that Sphinx converts string attributes to integers, which are
+ # useful for sorting, but that's about it.
+ #
+ # You can also have a collection of integers for multi-value attributes
+ # (MVAs). Generally these would be through a has_many relationship,
+ # like in this example:
+ #
+ # has posts(:id), :as => :post_ids
+ #
+ # This allows you to filter on any of the values tied to a specific
+ # record. Might be best to read through the Sphinx documentation to get
+ # a better idea of that though.
+ #
+ # Adding SQL Fragment Attributes
+ #
+ # You can also define an attribute using an SQL fragment, useful for
+ # when you would like to index a calculated value. Don't forget to set
+ # the type of the attribute though:
+ #
+ # has "age < 18", :as => :minor, :type => :boolean
+ #
+ # If you're creating attributes for latitude and longitude, don't
+ # forget that Sphinx expects these values to be in radians.
+ #
+ def has(*args)
+ options = args.extract_options!
+ args.each do |columns|
+ attributes << Attribute.new(FauxColumn.coerce(columns), options)
+ end
+ end
+ alias_method :attribute, :has
+
+ # Use this method to add some manual SQL conditions for your index
+ # request. You can pass in as many strings as you like, they'll get
+ # joined together with ANDs later on.
+ #
+ # where "user_id = 10"
+ # where "parent_type = 'Article'", "created_at < NOW()"
+ #
+ def where(*args)
+ @conditions += args
+ end
+
+ # Use this method to add some manual SQL strings to the GROUP BY
+ # clause. You can pass in as many strings as you'd like, they'll get
+ # joined together with commas later on.
+ #
+ # group_by "lat", "lng"
+ #
+ def group_by(*args)
+ @groupings += args
+ end
+
+ # This is what to use to set properties on the index. Chief amongst
+ # those is the delta property - to allow automatic updates to your
+ # indexes as new models are added and edited - but also you can
+ # define search-related properties which will be the defaults for all
+ # searches on the model.
+ #
+ # set_property :delta => true
+ # set_property :field_weights => {"name" => 100}
+ # set_property :order => "name ASC"
+ # set_property :include => :picture
+ # set_property :select => 'name'
+ #
+ # Also, the following two properties are particularly relevant for
+ # geo-location searching - latitude_attr and longitude_attr. If your
+ # attributes for these two values are named something other than
+ # lat/latitude or lon/long/longitude, you can dictate what they are
+ # when defining the index, so you don't need to specify them for every
+ # geo-related search.
+ #
+ # set_property :latitude_attr => "lt", :longitude_attr => "lg"
+ #
+ # Please don't forget to add a boolean field named 'delta' to your
+ # model's database table if enabling the delta index for it.
+ #
+ def set_property(*args)
+ options = args.extract_options!
+ if options.empty?
+ @properties[args[0]] = args[1]
+ else
+ @properties.merge!(options)
+ end
+ end
+ alias_method :set_properties, :set_property
+
+ # Handles the generation of new columns for the field and attribute
+ # definitions.
+ #
+ def method_missing(method, *args)
+ FauxColumn.new(method, *args)
+ end
+
+ # A method to allow adding fields from associations which have names
+ # that clash with method names in the Builder class (ie: properties,
+ # fields, attributes).
+ #
+ # Example: indexes assoc(:properties).column
+ #
+ def assoc(assoc)
+ FauxColumn.new(method)
+ end
+ end
+ end
+ end
+end
View
110 vendor/plugins/thinking-sphinx/lib/thinking_sphinx/index/faux_column.rb
@@ -0,0 +1,110 @@
+module ThinkingSphinx
+ class Index
+ # Instances of this class represent database columns and the stack of
+ # associations that lead from the base model to them.
+ #
+ # The name and stack are accessible through methods starting with __ to
+ # avoid conflicting with the method_missing calls that build the stack.
+ #
+ class FauxColumn
+ # Create a new column with a pre-defined stack. The top element in the
+ # stack will get shifted to be the name value.
+ #
+ def initialize(*stack)
+ @name = stack.pop
+ @stack = stack
+ end
+
+ def self.coerce(columns)
+ case columns
+ when Symbol, String
+ FauxColumn.new(columns)
+ when Array
+ columns.collect { |col| FauxColumn.coerce(col) }
+ when FauxColumn
+ columns
+ else
+ nil
+ end
+ end
+
+ # Can't use normal method name, as that could be an association or
+ # column name.
+ #
+ def __name
+ @name
+ end
+
+ # Can't use normal method name, as that could be an association or
+ # column name.
+ #
+ def __stack
+ @stack
+ end
+
+ # Returns true if the stack is empty *and* if the name is a string -
+ # which is an indication that of raw SQL, as opposed to a value from a
+ # table's column.
+ #
+ def is_string?
+ @name.is_a?(String) && @stack.empty?
+ end
+
+ # This handles any 'invalid' method calls and sets them as the name,
+ # and pushing the previous name into the stack. The object returns
+ # itself.
+ #
+ # If there's a single argument, it becomes the name, and the method
+ # symbol goes into the stack as well. Multiple arguments means new
+ # columns with the original stack and new names (from each argument) gets
+ # returned.
+ #
+ # Easier to explain with examples:
+ #
+ # col = FauxColumn.new :a, :b, :c
+ # col.__name #=> :c
+ # col.__stack #=> [:a, :b]
+ #
+ # col.whatever #=> col
+ # col.__name #=> :whatever
+ # col.__stack #=> [:a, :b, :c]
+ #
+ # col.something(:id) #=> col
+ # col.__name #=> :id
+ # col.__stack #=> [:a, :b, :c, :whatever, :something]
+ #
+ # cols = col.short(:x, :y, :z)
+ # cols[0].__name #=> :x
+ # cols[0].__stack #=> [:a, :b, :c, :whatever, :something, :short]
+ # cols[1].__name #=> :y
+ # cols[1].__stack #=> [:a, :b, :c, :whatever, :something, :short]
+ # cols[2].__name #=> :z
+ # cols[2].__stack #=> [:a, :b, :c, :whatever, :something, :short]
+ #
+ # Also, this allows method chaining to build up a relevant stack:
+ #
+ # col = FauxColumn.new :a, :b
+ # col.__name #=> :b
+ # col.__stack #=> [:a]
+ #
+ # col.one.two.three #=> col
+ # col.__name #=> :three
+ # col.__stack #=> [:a, :b, :one, :two]
+ #
+ def method_missing(method, *args)
+ @stack << @name
+ @name = method
+
+ if (args.empty?)
+ self
+ elsif (args.length == 1)
+ method_missing(args.first)
+ else
+ args.collect { |arg|
+ FauxColumn.new(@stack + [@name, arg])
+ }
+ end
+ end
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.