I have a problem with a relevant search. Results of following request are very strange:
Candidate.search('martin', fields: [:first_name, :last_name],
match: :word_start, misspellings: false).map(&:name)
["Kautzer Martina",
"Funk Martin",
"Jaskolski Martin",
"Gutmann Martine",
"Wiegand Martina",
"Schueller Martin",
"Dooley Martin",
"Stiedemann Martine",
"Bartell Martina",
"Gerlach Martine",
"Green Martina",
"Lang Martine",
"Legros Martine",
"Ernser Martina",
"Boehm Martina",
"Green Martine",
"Nolan Martin",
"Schmidt Martin",
"Hoppe Martin",
"Macejkovic Martine",
"Emard Martine"]
Why Martina is going earlier than Martin?
Searckick config:
searchkick language: %w(German English), word_start: [:first_name, :last_name]
Searchkick 1.4 fixes this issue. There's even a test case dedicated to this question :)
When using word_start, what searchkick actually does is to tokenize the chosen fields (:first_name and :last_name) using the searchkick_word_start_index analyzer. That analyzer is a custom one which uses the following edgeNGram token filter:
searchkick_edge_ngram: {
type: "edgeNGram",
min_gram: 1,
max_gram: 50
},
So, when Kautzer Martina gets indexed, the following tokens are actually produced and indexed:
:first_name: m, ma, mar, mart, marti, martin, martina
:last_name: k, ka, kau, kaut, kautz, kautze, kautzer
Similarly, for Funk Martin:
:first_name: m, ma, mar, mart, marti, martin
:last_name: f, fu, fun, funk
As you can see, when searching for martin, both will match because both contain the token martin and they will be sorted by descending score (default). If you want to order the results differently, you can use sorting and call your search with
order: [{last_name: :asc},{first_name: :asc}]
Try this
misspellings: {edit_distance: 0}
The problem with match: is you have to match the exact word, and caps.
I hope this works.
Related
I would like to humanized_money_with_symbol method to return something like USD$ 100, not only $ 100. Also I would like to do it only when currency symbol is $, we want to let users know when $ is USD and when AUD.
Never used MoneyRails but it looks like humanized_money_with_symbol just calls humanized_money merging in symbol: true to the parameters you passed it.
That helper then in turn calls format on the money object passed in, passing in the options you specified. In the Money gem, you can pass in a :symbol to render the currency with such as
m = Money.new('123', :gbp) # => #<Money fractional:123 currency:GBP>
m.format( symbol: m.currency.to_s + ' ') # => "GBP 1.23"
So, if you call
humanized_money(Money.new('123', :usd), symbol: 'USD $')
# => "USD $1.23"
You could then set up a helper method in your application, to avoid always having to pass that symbol in such as:
def render_custom_currency(value, options = {})
value.currency.iso_code == "USD" ? humanized_money(value, options.merge(symbol: 'USD $')) : humanized_money(value, options.merge(symbol: true))
end
that should get you what you're wanting to do.
You can override the USD configuration in initializers/money.rb to display "USD" as part of the symbol:
MoneyRails.configure do |config|
config.register_currency = {
"priority": 2,
"iso_code": "USD",
"name": "United States Dollar",
"symbol": "USD $",
"subunit": "Cent",
"subunit_to_unit": 100,
"symbol_first": true,
"decimal_mark": ".",
"thousands_separator": ",",
}
end
Restart the server and you should see "USD $100". I don't use multiple currencies but this should leave your other currencies displayed as normal.
Finally I used built-in in MoneyRails gem option disambiguate: true.
To use it you call method like below:
humanized_money_with_symbol(value, disambiguate: true)
Some examples how it works are here
According to this blog post, Algolia now allows several geolocations on a single record. All we have to do is to pass it as an array. I've tried it with the algolia-rails gem but was unable to do it.
Here are the combinations I've tried that does not work:
"geoloc": [
{"lat": :latitude, "lng": :longitude}
]
geoloc [{:latitude, :longitude}]
And a bunch of other combinations. Most of it results in an error indicating that geoloc is expecting 2 arguments instead of 1 which is an array.
My original code for a single geoloc which works is:
geoloc :latitude, :longitude
One workaround is:
def _geoloc
[{ lat: x_1, lng: y_1 }, { lat: x_2, lng: y_2 }]
end
algoliasearch do
attributes :_geoloc
end
This does the trick.
I have this line of code in my function:
people << {"id": person.id, "name": person.name, "age": person.age}
This ran fine in my development environment. But in my friend's pc, it says there is a syntax error in this line. It says that the colon in "id": person.id is wrong. Writing the above code as "id"=> person.id fixed the issue. Is this issue possibly due to different ruby versions?
people << {"id": person.id, "name": person.name, "age": person.age}
This syntax is new in 2.2.0. Before 2.2, the Symbols in the JSON-style Hash literals could only be valid Ruby identifiers (strictly speaking, valid Ruby labels) and could not be quoted.
See Feature #4276: Allow use of quotes in symbol syntactic sugar for hashes for details.
Writing the above code as "id"=> person.id fixed the issue.
Those two are not equivalent! The Hash above has Symbols as keys, your replacement has Strings as keys. There are several equivalent notations for the Hash literal above, but yours isn't:
{ id: person.id, name: person.name, age: person.age } # 1.9+
{ 'id': person.id, 'name': person.name, 'age': person.age } # 2.2+
{ :id => person.id, :name => person.name, :age => person.age } # all versions
{ :'id' => person.id, :'name' => person.name, :'age' => person.age } # all versions
{ :"id" => person.id, :"name" => person.name, :"age" => person.age } # all versions
I ordered them roughly in order of preference, with the first one being the most preferred. You shouldn't quote Symbol literals that don't need quoting, and you shouldn't use double quotes if you don't intend to use interpolation.
Your friend is probably using Ruby < v1.9.
That short syntax was introduced in 1.9. Before that it was all hash rocket (=>) syntax.
I'm trying to build an advanced search option (similar to Twitter's). Users can enter the words included, words excluded, words containing, exact phrase, and such in a search query.
I'm using Searchkick to do this. Particularity Searckick's regexp searches.
Here is what I'm doing to find the companies which have the words "Facebook or less" in their slogans.
Company.search("Be", where: { short_desc: /.*(#{ar}).*/ })
This works well. But, how would I do a negative of this search?
Doing something like, Company.search("Be", where: { short_desc: /.*(?!(#{ar})).*/ }) is not yielding results. Also, can I combine a search that has words to be included AND words to be excluded?
May be this helps you, try this:
Business.search("Be", where: { short_desc: {not: /.*(#{ar}).*/} })
And check the results. You can combine this with AND or OR operators. Anywhere using the where clause. Extracted from the gem readme file:
where: {
expires_at: {gt: Time.now}, # lt, gte, lte also available
orders_count: 1..10, # equivalent to {gte: 1, lte: 10}
aisle_id: [25, 30], # in
store_id: {not: 2}, # not
aisle_id: {not: [25, 30]}, # not in
user_ids: {all: [1, 3]}, # all elements in array
category: /frozen .+/, # regexp
or: [
[{in_stock: true}, {backordered: true}]
]
}
This is how you can combine it with query.
Hope this helps.
My array is:
[{:age=>28, :name=>"John", :id=>1}, {:name=>"David", :age=>20, :id=>2}]
Order:
[:id, :name, :age] or ['id', 'name', 'age']
The result should be:
[{:id=>1, :name=>"John", :age=>28}, {:id=>2, :name=>"David", :age=>20}]
P/s: I am using Ruby 1.8.7 and Rails 2.3.5
Thanks
Order doesn't matter when it comes to hashes. You do not need to do that. Trust me.
What you're using is an Hash which, unlike Array doesn't care for positions. You only access the value by it's Symbol or Key.
So, there is no need of doing what you want to.
As others have said, you cannot do that with Ruby 1.87 or prior. Here is one way to do that with Ruby 1.9+:
arr = [{:age=>28, :name=>"John", :id=>1}, {:name=>"David", :age=>20, :id=>2}]
order = [:id, :name, :age]
arr.map { |h| Hash[order.zip(h.values_at(*order))] }
#=> [{:id=>1, :name=>"John", :age=>28}, {:id=>2, :name=>"David", :age=>20}]
In Ruby 2.0+, you can write:
arr.map { |h| order.zip(h.values_at(*order)).to_h }
I thought 1.8.7 went out with the steam engine.