Here's my problem, I'll try to be concise.
I have a model Course that has_many Planning.
A Planning has a start_date and an end_date.
I want to retrieve (with sunspot) all the Courses that have a particular planning between a given start_date and an end_date.
The problem is that if I store in the model Course :
searchable do
date :start_date, multiple: true do
plannings.map(&:start_date)
end
date :end_date, multiple: true do
plannings.map(&:end_date)
end
...
end
I loose the fact that start_date and end_date are couples.
Is there a way / trick to store ranges?
Have almost the same problem, in my case start_date and end_date wasn't really a date, just a year (integer), solve it with multiple value fields as range:
searchable do
date :course_date, multiple: true do
plannings.map{|p| (p.start_date..p.end_date).to_a}
end
...
end
so course_date contain all years when courses going. If you have 2001-2003 and 2005-2007(2001, 2002, 2003, 2005, 2006, 2007) and search with equal_to.
A possibility would be to make your query in two times. First find the plannings, then find the courses restricting courses by ID.
Maybe not a very optimised one, but why try to optimize to soon...
Or to index hours with a function:
def happens_between_8_and_9
return true if start_date > 8..
end
searchable do
boolean :happens_between_8_and_9
boolean :happens_between_9_and_10
end
```
Related
I have a rails mongoid model with a string field end_date as follows
class Project
include Mongoid::Document
include Mongoid::Attributes::Dynamic
include Mongoid::Timestamps
field :end_date, type: String
end
end_date is having values stored as September 2021, January 2025 etc.
Now How can I find all the projects which has end_date less than current month?
If i am understanding correctly you want to compare date . You can use the following documentation to fit your purpose -
https://api.rubyonrails.org/v4.2.5/classes/Date.html
Get the date in a controller method and then convert before comparing with the current date . Hopefully this answers the question .
I have a date column in my schema called dob.
I'm using a simple form to render the dob.
I want to format the input as 3 separate integer inputs.
The closest i have gotten is this code:
<%= f.input :dob, order: [:day, :month, :year] %>
However it produces this:
which is close. However i need the inputs to be integer inputs, and not dropdowns. Also i would like the month the be an integer as well.
If i use as: :integer, it just returns one single input.
Any ideas? The simple form documentation is not particularly helpful.
Thanks
you will need 3 integer inputs:
f.integer :day
f.integer :month
f.integer :year
This requires you to have day, month, and year attribute accessors on your model, and to assemble the date from the component integers, perhaps in the controller, e.g.
# users_controller.rb
def create
params[:dob] = Date.new(params[:year], params[:month], params[:day])
#... the rest of the method
end
in order to populate the integer fields for editing, you'll need methods on your model, e.g.
# in User.rb
def day
dob.day
end
# ...etc
You will also need to check that the data that the user inputs is within range.
All this special handling is why this is not normally done.
I'm building a search using Algolia rails but having difficulties when doing sort by dynamically. For example, user can choose from a dropdown to sort by price asc or price desc.
Here is my model where I defined the indices
class Product < ActiveRecord::Base
include AlgoliaSearch
algoliasearch per_environment: true, if: :publishable? do
attribute :id, :name, :description, :seller_id, :condition, :location, :slug, :status, :city, :state, :stock_quantity,
:shipping_method, :price
attribute :created_at_i do
created_at.to_i
end
attribute :updated_at_i do
updated_at.to_i
end
attribute :price do
price.to_f
end
attributesToIndex ['name', 'unordered(description)', 'seller_id',
'condition', 'location', 'slug', 'created_at', 'updated_at', 'status',
'geo(city)', 'geo(state)']
geoloc :latitude, :longitude
numericAttributesToIndex ["price", "stock_quantity"]
attributesForFaceting ['price', 'condition', 'shipping_method']
end
and the products controller
def index
queries = { hitsPerPage: 5, page: params[:page].to_i, facets: '*',
facetFilters: [
"condition: #{params[:condition]}",
"shipping_method: #{params[:shipping_method]}"
],
numericFilters: [
"price:#{params[:min_price] || 0} to #{params[:max_price] || 999999999999999}"
],
sortBy: ["asc(price)"]
}
if latLng.present?
queries[:aroundLatLng] = latLng
queries[:aroundRadius] = radius
end
#response = Product.search(params[:query],queries)
Algolia returns error "invalid parameter sortBy". I tried to search on algolia documentation but couldn't find any information.
Thanks for helping.
Here is a list of relevant documentation pages from Algolia's website which will help you understand how Algolia's ranking work:
[Getting started] Tweak Ranking and Relevance
The reason our engine is so fast is because each index has its own settings and rankings. This means you are able to create different sets of searchable attributes and attribute ranking relevance by storing your data in multiple indices. This is accomplished using slave indices which are seamlessly synchronized with a master index. Each slave index can then be configured with its own set of business metrics to tune the relevance calculation.
An index has a specific ranking formula that can't be changed. You can however easily overcome this limitation by using slave indices with a different ranking formula.
[Tutorials][Ranking Formula] Tie Breaking algorithm
[FAQ] How does Algolia's tie breaking algorithm work?
These two links will help you understand how the ranking with Algolia work and how you can tweak it. Basically, depending on your use-case, sorting by price before text relevance doesn't really make sense. So, depending on your use case, you might just want to change your customRanking to price, or you might want to add your price attribute at the top of your ranking formula.
[FAQ] What are slave indices and what are their benefits?
This last link explain in more depth what a "slave index" is for Algolia.
[Rails documentation] Multiple sort criteria
[Rails GitHub documentation] Master/Slave
On these last links, you'll find code examples using Algolia's Rails client with multiple slaves. The first one actually showcases exactly your use case: sorting by price.
With all of this in mind, in the end, you're just looking to add these in your model (if you want to use the customRanking way):
add_slave 'Product_by_price_asc', per_environment: true do
customRanking ['asc(price)']
end
add_slave 'Product_by_price_desc', per_environment: true do
customRanking ['desc(price)']
end
Then in your controller, you can query them this way
query_params = { slave: "Product_by_price_#{params[:sort_order]}", hitsPerPage: 5, ... }
Product.search params[:query], query_params
You should probably also do this implementation in the front-end to be able to fully use Algolia's instant search capabilities, see [FAQ] Searching from the front-end or the back-end.
As part of an application I'm building, I need to store the days on which some action needs to happen.
Currently I have this stored in a 7-digit bit-string, with each digit corresponding to one day of the week. A value of 1 for any day means the action should happen that day, a value of 0 means it should not.
Ex. String 0101110 means the action should run on Tuesday, Thursday, Friday and Saturday every week.
In my form, I have seven checkboxes set up, one for each name.
How would I go about merging these seven Boolean results into the one bitstring, such that I can save it in the database?
Would you do this in the view, or the model?
I've done some thinking myself, and one option (in the view) could be to set up a hidden field in the form that is the result of joining/concatenating the seven Booleans from the checkboxes. Then the checkboxes' values could be discarded on submit. I'm just not quite sure how to do this in rails.
Another option could be to handle the merging in the model. Again - not quite sure what to do.
Any help appreciated, thanks in advance.
Define the checkbox values for the weekdays as virtual attributes on your model, and concatenate them on a before_save hook. In your model:
attr_writer :mon, :tue, :wed, :thu, :fri, :sat, :sun
before_save :set_weekdays
private
def set_weekdays
self.weekdays = bitstr(#mon) + bitstr(#tue) + bitstr(#wed) # etc
end
def bitstr(bool)
bool ? "1" : "0"
end
Make sure to permit mon and co as strong parameters for the model in Rails 4. You might also want to define getters for these attributes that would get filled from the bitstring, so that the form could render with the correct checkboxes pre-selected on edits.
I am assuming the week column is week
You can make the week column of type: text and add this to your model
serialize :week : this helps to save an array in the column
next, create a class Week, where week.rb:
class Week
include ActiveModel::Model
attr_accessor :id, :name
DAYS = [
{id: 1, "day" => "monday"},
{id: 2, "day" => "tuesday"},
...
]
def self.days
DAYS.map {|d| self.new(
id: d[:id],
name: d[:day]
)}
end
end
and then, you can call the checkboxes from the view as follow:
<%= f.collection_check_boxes(:week, Week.days, :id, :name, include_hidden: false) do |b| %>
<%= b.check_box(class: "check_box") %> <%= b.object.name %>
<% end %>
lastly, dont forget to make the week atribute accesible from the controller. In rails 4, this will be:
params.require(:user).permit(week: [])
Hope this helps you?
I may have over-complicated what I need to do but this is what I now have.
I have a jobs controller that has 2 fields
starts_at as DATETIME
end_time as DATETIME
I save the event_date in a form using a
calendar_date_select :starts_at ,:time => false
I save the date time as
time_select :starts_at, {:twelve_hour => true}
This saves the Event date i.e 12/26/2009 and the start time as 7:00 pm
I need to also save the event end_time without having to re-enter the date, just the time
time_select :end_time, {:twelve_hour => true}
If i just use the above, the time is correct but the date dafaults to 01/01/2000
How do I save the date with the same date from starts_at?
In your controller, if the :end_time is nil, set it to the :starts_at variable like so:
object.end_time = object.starts_at unless not object.end_time.nil?
You may be able to shorten the end to
object.end_time = object.starts_at unless object.end_time.present?
but I'm not sure which version of Rails you are using and what the default implementation of .present? does for dates.
You could do this in the model or controller, but isn't it possible that an event will start late at night and end on the following day? To allow for this possibility I'd recommend having two calendar_date_selects and auto-assigning the ending date when the starting date is chosen (so the second calendar_date_select will rarely be used).
If you really don't want two calendars, maybe use a hidden field for the ending date that follows the start date.
I wouldn't enforce this same-date rule below the interface level unless you're absolutely sure different start and end dates will never occur.