Rails thinking sphinx includes not working - ruby-on-rails

I have the code like following
Listing.search(
Riddle::Query.escape(params[:search]),
:include => params[:include],
:page => page,
:per_page => per_page,
:star => true,
:with => with,
:with_all => with_all,
:order => params[:sort]
)
params[:include] contains the value like [:listing_images, :author, :category, :origin_loc]
I don’t know what was wrong here.

Related

Thinking Sphinx without condition

I have a following model:
class Article < ActiveRecord::Base
define_index do
indexes content
indexes :name, sortable: true
has type
end
end
and special type of an article is:
class About < Article
end
and the same for Contact
I would like to have searchable articles index action without articles with type of "About" or "Contact"
class ArticlesController < ApplicationController
load_and_authorize_resource
def index
#articles = Article.search(params[:search],
:with_all => {:type => nil},
:page => params[:page],
:per_page => 10)
end
end
But the #articles instance variable contains everytime also "About" & "Contact" articles.
This is very strange (seems like will_paginate messing everything up):
#articles = Article.search(
:without => {:type => %w(About Contact)}).include?(About.first) # false
#articles = Article.search(
:without => {:type => %w(About Contact)},
:page => 1,
:per_page => 1000).include?(About.first) # true
=============================================================================
Finally I did:
class Article < ActiveRecord::Base
define_index do
indexes content
indexes :name, sortable: true
has "CRC32(type)", :as => :article_type, :type => :integer
end
end
and:
class ArticlesController < ApplicationController
load_and_authorize_resource
def index
#articles = Article.search(params[:search],
:without => {:article_type => ["About".to_crc32, "Contact".to_crc32]},
:page => params[:page],
:per_page => 10)
end
end
and it works. Thanks guys!
From the Thinking Sphinx FAQ:
Filtering on String Attributes
While you can have string columns as
attributes in Sphinx, they aren’t stored as strings. Instead, Sphinx
figures out the alphabetical order, and gives each string an integer
value to make them useful for sorting. However, this means it’s close
to impossible to filter on these attributes.
So, to get around this, there’s two options: firstly, use integer
attributes instead, if you possibly can. This works for small result
sets (for example: gender). Otherwise, you might want to consider
manually converting the string to a CRC integer value:
has "CRC32(category)", :as => :category, :type => :integer
This way, you can filter on it like so:
Article.search 'pancakes', :with => { :category => 'Ruby'.to_crc32 }
Of course, this isn’t amazingly clean, but it will work quite well.
You should also take note that CRC32 encoding can have collisions, so
it’s not the perfect solution.
Exclude About & Contact type from conditions like -
#articles = Article.search(params[:search],
:without => {:type => %w(About Contact)},
:page => params[:page],
:per_page => 10)
OR
I am not very sure on below but you can give it try..
define_index do
indexes content
indexes :name, sortable: true
indexes(:type), :as => :article_type
end
#articles = Article.search(params[:search],
:without => {:article_type => %w(About Contact)},
:page => params[:page],
:per_page => 10)
Also, make sure inside your database records you have type attribute got inserted properly..
Couldn't you use "with" instead of "with_all"? For example:
#articles = Article.search(params[:search],
:with => {:type => nil},
:page => params[:page],
:per_page => 10)

Ruby on Rails logic in active record condition

I'm building a site for users to post events they wish to sell tickets for.
I'm writing a query where the conditions are the follow:
active equals true
sales_stop is < Time.now
The problem I am having is coming up with a condition which tests whether or not a record's sales_stop time is less than Time.now.
Below is what I have as of now:
#events = Event.paginate :page => params[:page],
:conditions => {:active => true},
:order => "created_at DESC"
In turn, I've been toying around with the sales_stop condition with no luck.
I've been trying something like this:
#events = Event.paginate :page => params[:page],
:conditions => {:active => true, :sales_stop < Time.now},
:order => "created_at DESC"
This of course doesn't work.
Does anyone know how I can set this query up so that I only retrieve records where the sales_stop attribute is less than Time.now?
Thank you.
Use the alternate syntax for :conditions, which uses a bind-style:
#events = Event.paginate :page => params[:page],
:conditions => ['active = ? AND sales_stop < ?', true, Time.now],
:order => "created_at DESC"
This should work:
#events = Event.paginate :page => params[:page],
:conditions => ['active=? AND sales_stop < ?', true, Time.now],
:order => "created_at DESC"
Just a different syntax.

group_by using value from other model

Using ROR 2.3.8
I have this in cities_controller.rb:
#shops = Shop.published.search params[:keyword], {
:conditions => conditions,
:star => true,
:group_by => 'city_id',
:group_function => :attr,
:page => params[:page]
}.merge(:order => 'rating_average DESC')
#cities = #shops.collect { |shop| shopy.city }
How can I tell Rails to get the rating_average from City model instead of Shop model? Because the Shop model does not have rating_average. It's actually City model that gets rated.
Thank you.
UPDATES
published namescope in Shop.rb
sphinx_scope(:published) {
{:conditions => {:status => 'published'}}
}
Indexes in Shop.rb
define_index do
indexes city.name, :as => :name, :sortable => true
indexes city.duration, :as => :duration
indexes city.status, :as => :status
#has city.budget, :as => :budget
#has city(:created_at), :as => :created_at
has city(:rating_average), :as => :rating_average
has city_id
end
UPDATES 2
class City < ActiveRecord::Base
has_many :shops, :dependent => :destroy
...
end
You should use joins to acheive this:
#shops = Shop.published.search params[:keyword], {
:conditions => conditions,
:star => true,
:group_by => :city_id,
:group_function => :attr,
:page => params[:page]
}.merge(:order => :rating_average,
:sort_mode => :desc)
You should also add cities. or shops. before columns to specify which table's column.

Search many fields with will_paginate / searchlogic

How do you effectively search among many fields in a model?
# user.rb model
def self.search(search, page)
paginate :per_page => 20, :page => page,
:conditions =>
['name like ? OR notes like ? OR code like ? OR city like ? OR state like ?,
"%#{search}%","%#{search}%","%#{search}%","%#{search}%","%#{search}%"
], :order => 'name'
This code is horrible for any more than a few fields, and it doesn't return a result if, for instance word #1 comes from :name and word #2 comes from :code. Is there a more elegant way?
I think that do work
def self.search(search, page)
fields = [:name, :notes, :code, :city, :state]
paginate :per_page => 20, :page => page,
:conditions => [fields.map{|f| "#{f} like ?"}.join(' OR '),
*fields.map{|f| "%#{search}%"}], :order => 'name'
You can use searchlogic
def self.search(search, page)
search_cond = resource.search(name_or_notes_or_code_or_city_or_state_like => search.to_s)
search_cond.all
end
Hope you got the idea
def self.search(search, page)
fields = %w(name notes code city state)
paginate :per_page => 20, :page => page,
:conditions => [fields.map{|f| "#{f} like :phrase"}.join(' OR '), {:phrase => search}],
:order => 'name'

Thinking Sphinx and acts_as_taggable_on plugin

I installed Sphinx and Thinking Sphinx for ruby on rails 2.3.2.
When I search without conditions search works ok. Now, what I'd like to do is filter by tags, so, as I'm using the acts_as_taggable_on plugin, my Announcement model looks like this:
class Announcement < ActiveRecord::Base
acts_as_taggable_on :tags,:category
define_index do
indexes title, :as => :title, :sortable => true
indexes description, :as => :description, :sortable => true
indexes tags.name, :as => :tags
indexes category.name, :as => :category
has category(:id), :as => :category_ids
has tags(:id), :as => :tag_ids
end
For some reason, when I run the following command, it will bring just one announcement, that has nothing to do with what I expect. I've got many announcements, so I expected a lot of results instead.
Announcement.search params[:announcement][:search].to_s, :with => {:tag_ids => 1}, :page => params[:page], :per_page => 10
I guess something is wrong, and it's not searching correctly.
Can anyone give my a clue of what's going on?
Thanks,
Brian
Thinking Sphinx relies on associations in model. In common situations you only have to put index definition below your associations.
With acts_as_taggable_on plug-in you don't have tag-related associations in model file and when you write
indexes tags.name, :as => :tags
TS interprets it like:
CAST(`announcements`.`name` AS CHAR) AS `tags`
(look at sql_query in development.sphinx.conf, in my case).
I suppose that you have attribute name in model Announcement and don't run into error when rebuild index.
But we expect:
CAST(GROUP_CONCAT(DISTINCT IFNULL(`tags`.`name`, '0') SEPARATOR ' ') AS CHAR) AS `tags`
and:
LEFT OUTER JOIN `taggings` ON (`announcements`.`id` = `taggings`.`taggable_id`)
LEFT OUTER JOIN `tags` ON (`tags`.`id` = `taggings`.`tag_id`) AND taggings.taggable_type = 'Announcement'
To get things working just add tag-related associations in your model before you rebuild index:
class Announcement < ActiveRecord::Base
acts_as_taggable_on :tags,:category
has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging",
:conditions => "taggings.taggable_type = 'Announcement'"
#for context-dependent tags:
has_many :category_tags, :through => :taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag",
:conditions => "taggings.context = 'categories'"
In define_index method:
indexes category_tags(:name), :as => :tags
has category_tags(:id), :as => :tag_ids, :facet => true
In controller:
#announcement_facets = Announcement.facets params[:search], :with => {:tag_ids => [...]}
#announcements = #announcement_facets.for.paginate( :page => params[:page], :per_page => 10 )
I found that simply defining the index thus:
Class Thing < ActiveRecord::Base
acts_as_taggable
define_index do
..other indexing...
indexes taggings.tag.name, :as => :tags
end
end
worked fine.
One possibility is that you need to declare the type for tag_ids as :multi because TS can get confused (I just discovered this here http://groups.google.com/group/thinking-sphinx/browse_thread/thread/9bd4572398f35712/14d4c1503f5959a9?lnk=gst&q=yanowitz#14d4c1503f5959a9).
But why not use the tag names to search? E.g.,
Announcement.search params[:announcement][:search].to_s, :conditions => {:tags => "my_tag"}, :page => params[:page], :per_page => 10
Or, if you need to search for multiple tags:
Announcement.search( "#{params[:announcement][:search].to_s} (#tags my_tag | #tags your_tag)", :page => params[:page], :per_page => 10 )
(as aside, you may want to sanitize/remove sphinx-control-characters from the user-provided query before using it).
For debugging, I would go into console and strip down your query as much as possible (eliminate pagination arguments, even the query (just do ""), etc.).

Resources