Implementing the search field

:  ~ 1 min read

Well, it's done. Thanks to the desire to publish when mobile, I had to implement some sort of Dropbox sync, which forced me to implement a database for a better user experience than handling files directly, which, lastly, gave me the opportunity to implement search: a feature that was ==a lot== easier to implement than I've expected: 30 lines of code.

The search form:

<form class="search" action="/search" method="get">
  <input type="text" class="search" name="query" size="15" maxlength="20" placeholder="Search..."/>
</form>

Sinatra's route block:

get %r{^/search$} do
  query = request.env['rack.request.query_hash']['query']
  query_array = []
  # Store all search terms in an array. If the search was done using "",
  # add the whole search query as the single element in the array.
  if query[0,1] == '"' and query[-1,1] == '"'
    query_array << query.gsub('"', '').downcase
  else
    query_array = query.downcase.split(' ')
  end

  # This returns an array of structures containing all the posts' data.
  all_posts = repository(:default).adapter.select('SELECT * FROM application_posts')
  # Convert the structures to hashes.
  all_posts.map! { |struc| struc.to_h}
  # Sort the array by the datetime field of our hashes. Newest to oldest.
  all_posts.sort! { |a, b| a[:datetime] <=> b[:datetime]}.reverse!

  # This is the core and the most beautiful part.
  # Could have been a one-liner too, but I wanted it to be more readable.
  all_posts.select! do |p|
    # Iterate through the posts array and keep the ones that include in their body or title an element from the query_array
    query_array.any? { |w| p[:body].downcase.include?(w) or p[:title].downcase.include?(w) }
  end

  @meta_description = 'iOS and Ruby development thoughts by Roland Leth.'
  all_posts.count > 0 ? erb :index, locals: { posts: all_posts, page: 1, total_pages: 1, gap: 2 } : search_not_found
end

Plus 10 lines of CSS, and that was that.

I was (and still am) pondering on using Google's site: search. I feel its bolding of the search term(s) is a better user experience, but the pages aren't updated as fast as I post them, so I'll keep my custom search for now.

<form class="search" action="http://www.google.com/search" method="get">
  <input type="hidden" name="q" value="site:rolandleth.com">
  <input type="text" class="search" name="q" size="15" maxlength="20" placeholder="Search..." accesskey="/"/>
</form>