comparison Operators in thinking Sphinix - ruby-on-rails

I have a model with attributes start_date and end_date. I have search form where user will put the date and I should get a data from the model if date is in between start_date and end_date.
how should I create a query with thinking sphinx.

You will need to do something like the following:
Add both start_date and end_date as attributes (not fields) to your model's Sphinx index.
Translate form params into a date or time value
Use range filters to limit search queries.
I've opted for very large windows of time, but essentially this ensures the given date is equal to or larger than the start date and less than or equal to the end date.
beginning, ending = Time.utc(1970), Time.utc(2030)
Model.search :with => {
:start_date => beginning..date_from_params,
:end_date => date_from_params..ending
}

Related

The smallest and the largest possible date

I am creating a filtering partial view, where user can pick a from-date and a to-date using a calendar. These dates are used then within model scope to perform SQL Where clause in database query. If a user does not pick one of dates, the default value should be assigned: minimal available date for from and maximal for to.
unless params[:from].blank? and params[:to].blank?
from = begin Date.parse(params[:from]) rescue ??? end
to = begin Date.parse(params[:to]) rescue ??? end
#model_instances = #model_instances.start_end from, to
end
(...)
scope :start_end, -> (start_date, end_date) { where('(:start_date <= "from" AND "from" <= :end_date ) OR' +
'(:start_date <= "to" AND "to" <= :end_date ) OR' +
'("from" <= :start_date AND :end_date <= "to")',
{start_date: start_date, end_date: end_date}) }
The from and to model Date attributes are also database fields in related table.
In Rails, Date class has a family of methods beginning_of (day, week, month, etc.), but there are no methods such beginning_of_time, end_of_time, Date.min, Date.max.
Are there any methods to obtain the minimal and maximal dates?
You could skip the condition on start and end dates if no params is given:
if params[:from].present? and params[:to].present?
#model_instances.start_end(params[:from], params[:to])
end
And then you will get results not depending on dates since no from and/or end dates have been filled.
You could compare ranges of dates to your model's values and setup default values if params not passed.
#setup default if desired, or you can skip if params are blank
from = params[:from] || default_from
to = params[:to] || default_to
#model_instances.start_end(from, to)
and your scope would look something like this if you used date ranges for activerecord
scope :start_end, ->(start_date, end_date){where(from: start_date..end_date, to:start_date..end_date)}

How to express negation with symbol in ActiveRecord?

How can I query activities for a given week except for the day with name equal to the string "summary"?
Activity.where(:week => wk, :day => "Summary").each do |daily_activity|
end
How do you express the negation? And show the activities for each day in the week, but not when the day is "Summary" (as it's not an actual day).
You can't do it directly with a hash, but you can do it with something like the following:
Activity.where(:week => wk).where('day != ?', 'Summary')
If you want expanded options for finders, check out the squeel gem.

Supporting timezones in a Rails application

I added a calendar to my rails application. We have events with a start date and an end date (both includes hours and minutes). This ones are fields in the events table, actually their format is datetime. When you select the start date, end date, title and description (among others) for an specific event the the parameters hash is something like this:
parameters = {"event" => {"title" => "a title", "description" => "a description", "start_date" => "2012-09-23 23:45", "end_date" => "2012-09-24 15:32"}}
In the events controller i have something like this:
Event.create(:title => params[:event][:title],
:description => params[:event][:description],
:start_date => params[:event][:start_date].present? ? DateTime.strptime(params[:event][:start_date], "%Y-%m-%d %H:%M") : nil,
:end_date => params[:event][:end_date].present? ? DateTime.strptime(params[:event][:end_date], "%Y-%m-%d %H:%M") : nil,
...
)
Well, when this event is stored into the database (mysql) the value for start date is "2012-09-23 20:45" while the value for end date is "2012-09-24 12:32". I understand that Rails is automatically dealing with timezones. My problem is that when I want to fetch all the events for a specific time (for example, all events that occurs today) I do:
query = "((start_date between ? AND ?) OR (end_date between ? AND ?))"
query << "title NOT LIKE ? AND ..."
self.events.where(query,
Time.now.beginning_of_day, Time.now.end_of_day,
Time.now.beginning_of_day, Time.now.end_of_day,
some_restriction_here, ...)
I get the wrong events! (it is obvious why, the date and time is different in the database from the inputs). There's and obvious solution also, bring all the events into memory and the date and time will be as the original again but this is expensive in terms of resources. By the other hand this don't solve the problem of timezones, if someone in china crate an event the value in the database will be relative to the time offset of the server localization. I could have a field somewhere where the user can set a time zone and work with this storing a specific date for such user and working through this, what is your suggestion about the best way to deal with this?
Rails stores all dates in database in the UTC format. So one way is to always do operations in UTC and in the view convert the displayed dates to current time zone. The other way is to change Rails timezone on the beginning of every action. All parsed times and dates will then be in your custom time zone.
def action_name
Time.zone = "Prague"
# ... logic
end

Select records based on date comparison

I have a bunch of "rides" in my database. I want to display just the ones whose "date_range_end" field (which is a Date) is after the current date. In my controller I have this:
Ride.find(:all, :conditions => [ :date_range_end > Date.today ])
but that causes this error: comparison of Symbol with Date failed
So how do I perform this query?
Ride.where('date_range_end > ?', Date.today).all

thinking sphinx date range problem

Why does this return results:
#results = Index.search "#{#keywords}", :with => {
:published_on => 1.week.ago..Time.now,
}
but not this?
#results = Index.search "#{#keywords}", :with => {
:published_on => '2011-04-01'..'2011-04-08',
}
published_on is a datetime field, but I have tried it with hour, minutes and seconds as well.
Given you're getting results, I'm guessing published_on is actually an attribute, not a field?
If the attribute is a datetime data type, then you need to pass in Ruby Time objects for filters - that, or integer timestamps (which is what Thinking Sphinx converts times to anyway). TS doesn't try to parse strings, so you'll need to manage that yourself.
Sphinx isn't as fancy as MySQL when it comes to auto-parsing dates and times - you need to use the right data type.

Resources