Module: SearchHelper

Defined in:
app/helpers/search_helper.rb

Overview

Markup generators for the search controller

Instance Method Summary (collapse)

Instance Method Details

- (String) document_bibliography_entry(doc)

Get the short, formatted representation of a document

This function returns the short bibliographic entry for a document that will appear in the search results list. The formatting here depends on the current user's settings. By default, we use a jQuery Mobile-formatted partial with an H3 and some P's. The user can set, however, to format the bibliographic entries using their favorite CSL style.

Examples:

Get the entry for a given document

document_bibliography_entry(Document.new(authors: 'W. Johnson',
                                         year: '2000'))
# "Johnson, W. 2000. ..."

Parameters:

  • doc (Document)

    document for which bibliographic entry is desired

Returns:

  • (String)

    bibliographic entry for document



304
305
306
307
308
309
310
# File 'app/helpers/search_helper.rb', line 304

def document_bibliography_entry(doc)
  if user_signed_in? && current_user.csl_style
    return doc.to_csl_entry(current_user.csl_style)
  end

  render partial: 'document', locals: { document: doc }
end

Create a link to the given set of facets

This function converts an array of facets to a link (generated via link_to) to the search page for that filtered query. All parameters other than :fq are simply duplicated (including the search query itself, :q).

Examples:

Get a “remove all facets” link

facet_link("Remove all facets", [])
# => link_to "Remove all facets", search_path

Get a link to a given set of facets

facet_link("Some facets", [...])
# => link_to "Some facets", search_path({ fq: [ ... ] })

Parameters:

  • text (String)

    body of the link

  • facets (Array<Solr::Facet>)

    array of facets, possibly empty

Returns:

  • (String)

    link to search for the given set of facets



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'app/helpers/search_helper.rb', line 174

def facet_link(text, facets)
  new_params = params.dup

  if facets.empty?
    new_params[:fq] = nil
    return link_to text,
                   search_path(new_params),
                   data: { transition: 'none' }
  end

  new_params[:fq] = []
  facets.each { |f| new_params[:fq] << f.query }
  link_to text,
          search_path(new_params),
          data: { transition: 'none' }
end

Return a set of list items for faceted browsing

This function queries both the active facets on the current search and the available facets for authors, journals, and years. It returns a set of <li> elements (not a <ul>), including list dividers.

Examples:

Get all of the links for faceted browsing

facet_link_list(@result)
# "<li>Active Filters</li>...<li>Authors</li><li>"
  "<a href='...'>Johnson</a></li>..."

Parameters:

Returns:

  • (String)

    set of list items for faceted browsing



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'app/helpers/search_helper.rb', line 243

def facet_link_list(result)
  # Bail now if there's no facet data (faceted down to one document)
  return ''.html_safe unless result.facets

  # Convert the active facet queries to facets
  active_facets = []
  if params[:fq]
    params[:fq].each do |query|
      active_facets << result.facets.for_query(query)
    end
    active_facets.compact!
  end

  # Start with the active facets
  ret = ''.html_safe
  unless active_facets.empty?
    ret << (:li,
                       I18n.t('search.index.active_filters'),
                       data: { role: 'list-divider' })
    ret << (:li, data: { icon: 'delete' }) do
      facet_link I18n.t('search.index.remove_all'), []
    end
    active_facets.each do |f|
      ret << (:li, data: { icon: 'delete' }) do
        other_facets = active_facets.reject { |x| x == f }
        facet_link "#{f.field_label}: #{f.label}", other_facets
      end
    end
  end

  # Run the facet-list code for all three facet fields
  ret << list_links_for_facet(result,
                              :authors_facet,
                              I18n.t('search.index.authors_facet'),
                              active_facets)
  ret << list_links_for_facet(result,
                              :journal_facet,
                              I18n.t('search.index.journal_facet'),
                              active_facets)
  ret << list_links_for_facet(result,
                              :year,
                              I18n.t('search.index.year_facet'),
                              active_facets)
  ret
end

Get the list of facet links for one particular field

This function takes the facets from the Document class, checks them against active_facets, and creates a set of list items. It is used by facet_link_list.

Examples:

Get the links for the authors facet

list_links_for_facet(@result, :authors_facet, "Authors", [...])
# "<li><a href='...'>Johnson <span class='ui-li-count'>2</a></li>..."

Parameters:

  • result (Solr::SearchResult)

    the search result

  • field (Symbol)

    field we're faceting on

  • header (String)

    content of list item header

  • active_facets (Array<Solr::Facet>)

    array of active facets

Returns:

  • (String)

    list items for links for the given facet



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'app/helpers/search_helper.rb', line 206

def list_links_for_facet(result, field, header, active_facets)
  return ''.html_safe unless result.facets

  # Get the facets for this field
  facets = (result.facets.sorted_for_field(field) - active_facets).take(5)

  # Bail if there's no facets
  ret = ''.html_safe
  return ret if facets.empty?

  # Build the return value
  ret << (:li, header, data: { role: 'list-divider' })
  facets.each do |f|
    ret << (:li) do
      # Link to whatever the current facets are, plus the new one
      link = facet_link f.label, active_facets + [f]
      count =  :span, f.hits.to_s, class: 'ui-li-count'
      link + count
    end
  end

  ret
end

- (String) num_hits_string(result)

Return a formatted version of the number of hits for the last search

Examples:

Print the number of hits for the search (in HAML)

= num_hits_string(@result)

Parameters:

Returns:

  • (String)

    number of hits for the search



13
14
15
16
17
18
19
# File 'app/helpers/search_helper.rb', line 13

def num_hits_string(result)
  if params[:precise] || params[:q] || params[:fq]
    I18n.t 'search.index.num_hits_found', count: result.num_hits
  else
    I18n.t 'search.index.num_documents_database', count: result.num_hits
  end
end

Make a link to a page for the pagination widget

Examples:

Get a link to the 3rd page of results, with a right-arrow icon

page_link('Page 3!', 2, 'arrow-r', true)

Parameters:

  • text (String)

    text for this link

  • num (Integer)

    the page number (0-based)

  • icon (String) (defaults to: '')

    icon for the button, if desired

  • right (Boolean) (defaults to: false)

    if true, put icon on the right side of the button

Returns:

  • (String)

    the requested link



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'app/helpers/search_helper.rb', line 31

def page_link(text, num, icon = '', right = false)
  new_params = params.dup
  if num == 0
    new_params.delete :page
  else
    new_params[:page] = num
  end

  data = { transition: :none, role: :button }
  data[:icon] = icon unless icon.empty?
  data[:iconpos] = 'right' if right

  link_to text, search_path(new_params), data: data
end

- (String) render_pagination(result)

Render the pagination links

We currently render four buttons, in a 4x1 grid: first, previous, next, and last. Pagination is difficult for an application like this; we don't want infinite scroll, as there are far too many items, but full pagination (like that on Google or Flickr) really doesn't work on mobile devices. So this is a compromise.

Examples:

Put the current pagination links in a paragraph element

<p><%= render_pagination(@result) %></p>

Parameters:

Returns:

  • (String)

    full set of pagination links for the current page



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/helpers/search_helper.rb', line 59

def render_pagination(result)
  num_pages = result.num_hits.to_f / @per_page.to_f
  num_pages = Integer(num_pages.ceil)
  return '' if num_pages == 0

   :div, class: 'ui-grid-c' do
    content = (:div, class: 'ui-block-a') do
      if @page != 0
        page_link(I18n.t('search.index.first_button'),
                  0,
                  'back')
      end
    end
    content << (:div, class: 'ui-block-b') do
      if @page != 0
        page_link(I18n.t('search.index.previous_button'),
                  @page - 1,
                  'arrow-l')
      end
    end

    content << (:div, class: 'ui-block-c') do
      if @page != (num_pages - 1)
        page_link(I18n.t('search.index.next_button'),
                  @page + 1,
                  'arrow-r',
                  true)
      end
    end
    content << (:div, class: 'ui-block-d') do
      if @page != num_pages - 1
        page_link(I18n.t('search.index.last_button'),
                  num_pages - 1,
                  'forward',
                  true)
      end
    end

    content
  end
end

- (Array<String>) sort_methods

Return an array of all sort methods

Examples:

Create links to all the sort methods

<%= sort_methods.each do |s| %>
  <%= link_to ... %>

Returns:

  • (Array<String>)

    all possible sorting strings



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'app/helpers/search_helper.rb', line 108

def sort_methods
  [
    'score desc',
    'authors_sort asc',
    'authors_sort desc',
    'title_sort asc',
    'title_sort desc',
    'journal_sort asc',
    'journal_sort desc',
    'year_sort asc',
    'year_sort desc'
  ]
end

- (String) sort_to_string(sort)

Get the given sort method as a string

This function converts a sort method ('relevance', 'title', 'author', 'journal', 'year') and sort direction ('asc' or 'desc') into a user-friendly string.

Examples:

Get the user-friendly version of 'score desc'

sort_to_string 'score desc'
# => 'Sort: Relevance'

Parameters:

  • sort (String)

    sorting string

Returns:

  • (String)

    user-friendly representation of sort method



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'app/helpers/search_helper.rb', line 134

def sort_to_string(sort)
  parts = sort.split(' ')
  return I18n.t('search.index.sort_unknown') unless parts.count == 2

  method = parts[0]
  dir = I18n.t("search.index.sort_#{parts[1]}")

  method_spec = case method
                when 'score'
                  I18n.t('search.index.sort_score')
                when 'title_sort'
                  "#{Document.human_attribute_name('title')} #{dir}"
                when 'authors_sort'
                  "#{Document.human_attribute_name('authors')} #{dir}"
                when 'journal_sort'
                  "#{Document.human_attribute_name('journal')} #{dir}"
                when 'year_sort'
                  "#{Document.human_attribute_name('year')} #{dir}"
                end

  "#{I18n.t('search.index.sort_prefix')} #{method_spec}"
end