The app is using typeahead and bootstrap 3 for, autocomplete function. but now we have so many records that , it is getting really slower.
var substringMatcher = function(strs) {
return function findMatches(q, cb) {
var matches, substrRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function(i, str) {
if (substrRegex.test(str)) {
// the typeahead jQuery plugin expects suggestions to a
// JavaScript object, refer to typeahead docs for more info
matches.push({ value: str });
}
});
cb(matches);
};
};
$('.typeahead').each(function(elem) {
$(elem).typeahead({
hint: false,
highlight: true,
minLength: 3
}, {
displayKey: 'value',
source: substringMatcher($(elem).data('source'))
});
});
these are javasxript parts of typeahead fuction used by the app
on the view side of the form
<div class="form-group">
<label class="col-sm-2 control-label" for="typeahead_book">Title</label>
<div class="col-sm-3">
<input value="<%=@option.book.try(:title)%>" name="option[book_title]" type="text" class="form-control typeahead typeahead-remote-book" id="typeahead_book" data-provide="typeahead" data-items="10" data-source='<%=@book_titles%>'>
<p class="help-block"><small><%= $autocomplete_message %></small></p>
</div>
i use a callback as
before_filter :get_autocomplete_lists, only: [:new, :edit]
def get_autocomplete_lists
@book_titles = Rails.cache.fetch("booktitles", :force => true, expires_in: 10.minutes) do
Book.scoped.map(&:title)
end
@publisher_names = Rails.cache.fetch("publishernames", :force => true, expires_in: 10.minutes) do
Publisher.all.map(&:name)
end
@users_by_email_name = Rails.cache.fetch("users", :force => true, expires_in: 7.days) do
User.scoped.map{|user| "#{user.email} - #{user.name}"}
end
@country_names = Rails.cache.fetch("countrynames", :force => true, expires_in: 7.days) do
Country.all.map(&:first).sort
end
# @languages = LanguageList::COMMON_LANGUAGES.map(&:name)
# @country_names = Anatolialit::Country::List.sort
#
@languages = Rails.cache.fetch("languages", :force => true, expires_in: 7.days) do
Anatolialit::Language::EnList.sort
end
end
on controller that generates source of the book , as @book_titles , THE APP IS WORKING NOW but i have to refactor the code for performance issues.Because after 10k record @book_titles is very big.
THAN WHAT I DID i created a new controller action on application controller
def book_titles
searchterm = (params[:title])
books =Book.any_of({ :title => /.*#{searchterm}.*/ })
respond_to do |format|
format.json { render json: books.map(&:title) }
end
end
and i defined a route to use as application controller as an api service
get 'booktitles/:title' => 'application#book_titles', format: :json
now when i use a localhost:3000/booktitles/the it brings me as a json data all the books that indicates 'the' in the title. I think everything Until here is ok. about refactoring.
but when i use this code below for userside per request for sourcing typeahead
$(document).ready(function() {
$('.typeahead-remote-book').typeahead({
source: function (query, process) {
return $.get('/booktitles', { query: query }, function (data) {
return typeahead.process(data);
});
}
});
});
and i changed the view part of the form to
<div class="form-group">
<label class="col-sm-2 control-label" for="typeahead_book">Title</label>
<div class="col-sm-3">
<input value="<%=@option.book.try(:title)%>" name="option[book_title]" type="text" class="form-control typeahead typeahead-remote-book" id="typeahead_book" data-provide="typeahead" data-items="10" >
<p class="help-block"><small><%= $autocomplete_message %></small></p>
</div>
</div>
*I do not know what is wrong with the situation , but it does not work *
could u please help me ? about solving the problem. Thanks for your kind help.. best regards.
Aucun commentaire:
Enregistrer un commentaire