Skip to content

Commit

Permalink
Merge pull request #690 from berkmancenter/media_mention
Browse files Browse the repository at this point in the history
Media mention
  • Loading branch information
peter-hank authored Sep 20, 2021
2 parents 77658dc + 7e66e27 commit 2c150ee
Show file tree
Hide file tree
Showing 40 changed files with 486 additions and 94 deletions.
36 changes: 27 additions & 9 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -168,20 +168,20 @@ GEM
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
elasticsearch (7.8.0)
elasticsearch-api (= 7.8.0)
elasticsearch-transport (= 7.8.0)
elasticsearch-api (7.8.0)
elasticsearch (7.14.1)
elasticsearch-api (= 7.14.1)
elasticsearch-transport (= 7.14.1)
elasticsearch-api (7.14.1)
multi_json
elasticsearch-extensions (0.0.31)
ansi
elasticsearch
elasticsearch-model (7.1.0)
elasticsearch-model (7.2.0)
activesupport (> 3)
elasticsearch (> 1)
elasticsearch (~> 7)
hashie
elasticsearch-rails (7.1.0)
elasticsearch-transport (7.8.0)
elasticsearch-rails (7.2.0)
elasticsearch-transport (7.14.1)
faraday (~> 1)
multi_json
erubi (1.10.0)
Expand All @@ -192,8 +192,25 @@ GEM
factory_bot_rails (5.2.0)
factory_bot (~> 5.2.0)
railties (>= 4.2.0)
faraday (1.0.1)
faraday (1.7.2)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
ffi (1.15.3)
flutie (2.2.0)
get_process_mem (0.2.7)
Expand Down Expand Up @@ -416,6 +433,7 @@ GEM
rexml
ruby-prof (1.3.2)
ruby-statistics (2.1.3)
ruby2_keywords (0.0.5)
ruby_parser (3.16.0)
sexp_processor (~> 4.15, >= 4.15.1)
rubyzip (2.3.0)
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
@import 'blog/show';
@import 'counter_notices/show';
@import 'token_urls/index';
@import 'media_mentions/index';

@import 'pages/pages';

Expand Down
37 changes: 37 additions & 0 deletions app/assets/stylesheets/media_mentions/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.media_mentions-search {
.media-mention-result {
.title {
margin-bottom: 5px;
}

.media-mention-result-meta {
label {
margin-top: 5px;
margin-bottom: 0;
}
}
}
}

.media-mention-show {
.main {
padding: 35px;
}

&-metadata {
@include clearfix;
margin-bottom: 10px;

&-item {
margin-bottom: 5px;

.label {
@extend %notices-label;
}

.field {
clear: both;
}
}
}
}
1 change: 1 addition & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def index
@notices ||= Notice.where(id: notice_ids)

@blog_entries = blog_entries
@search_index_path = notices_search_index_path
end

def blog_entries
Expand Down
33 changes: 33 additions & 0 deletions app/controllers/media_mentions/search_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class MediaMentions::SearchController < SearchController
URL_ROOT = 'media_mention'.freeze
SEARCHED_MODEL = MediaMention

private

def set_model_specific_variables
@model_class = MediaMention
@search_index_path = media_mentions_search_index_path
@searchable_fields = MediaMention::SEARCHABLE_FIELDS
@filterable_fields = MediaMention::FILTERABLE_FIELDS
@ordering_options = MediaMention::ORDERING_OPTIONS
@url_root = URL_ROOT
@search_all_placeholder = 'Search all research and media mentions...'
end

def item_searcher
ElasticsearchQuery.new(params, MediaMention).tap do |searcher|
@searchable_fields.each do |searched_field|
searcher.register searched_field
end

@filterable_fields.each do |filtered_field|
searcher.register filtered_field
end

searcher.sort_by = sort_by(params[:sort_by])
end
end

# We don't need to limit access to research papers
def restrict_deep_pagination; end
end
7 changes: 7 additions & 0 deletions app/controllers/media_mentions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class MediaMentionsController < ApplicationController
def show
return resource_not_found("Can't fing research paper with id=#{params[:id]}") unless (@media_mention = MediaMention.find_by(id: params[:id]))

render :show
end
end
10 changes: 10 additions & 0 deletions app/controllers/notices/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ class Notices::SearchController < SearchController

private

def set_model_specific_variables
@model_class = Notice
@search_index_path = notices_search_index_path
@searchable_fields = Notice::SEARCHABLE_FIELDS
@filterable_fields = Notice::FILTERABLE_FIELDS
@ordering_options = Notice::ORDERING_OPTIONS
@url_root = URL_ROOT
@search_all_placeholder = 'Search all notices...'
end

def item_searcher
ElasticsearchQuery.new(params).tap do |searcher|
Notice::SEARCHABLE_FIELDS.each do |searched_field|
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/notices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ def show

update_stats

@searchable_fields = Notice::SEARCHABLE_FIELDS
@filterable_fields = Notice::FILTERABLE_FIELDS
@ordering_options = Notice::ORDERING_OPTIONS
@search_all_placeholder = 'Search all notices...'

respond_to do |format|
format.html { show_render_html }
format.json do
Expand Down
6 changes: 5 additions & 1 deletion app/controllers/search_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
# - URL_ROOT
# - SEARCHED_MODEL
# - item_searcher
# - set_model_specific_variables
# They may also define html_responder.
class SearchController < ApplicationController
before_action :set_model_specific_variables
before_action :prevent_impossible_pagination
before_action :restrict_deep_pagination

Expand Down Expand Up @@ -65,7 +67,7 @@ class << instance
end

def sort_by(sort_by_param)
ResultOrdering.define(sort_by_param).sort_by
ResultOrdering.define(sort_by_param, @model_class).sort_by
end

def wrap_instances
Expand Down Expand Up @@ -142,4 +144,6 @@ def facet_query_meta(results)
memo[facet.to_sym] = params[facet.to_sym] if params[facet.to_sym].present?
end
end

def set_model_specific_variables; end
end
4 changes: 2 additions & 2 deletions app/helpers/notices/search_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def unspecified_identifiers(parameter)
@unspecified_identifiers[parameter]
end

def sort_order_label(sort_by_param)
ResultOrdering.define(sort_by_param).label
def sort_order_label(sort_by_param, model_class)
ResultOrdering.define(sort_by_param, model_class).label
end
end
9 changes: 5 additions & 4 deletions app/models/elasticsearch/date_range_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ class DateRangeFilter

attr_reader :title, :parameter

def initialize(parameter, indexed_attribute = nil, title = '')
def initialize(parameter, indexed_attribute = nil, title = '', ranges = default_ranges)
@parameter = parameter
@title = title
@indexed_attribute = indexed_attribute || parameter
@ranges = ranges
end

def to_partial_path
'notices/search/date_range_filter'
'search/date_range_filter'
end

def as_elasticsearch_filter(param, value)
Expand All @@ -25,7 +26,7 @@ def process_for_query
type: :date_range,
local_parameter: @parameter,
local_indexed_attribute: @indexed_attribute,
local_ranges: ranges
local_ranges: @ranges
}
end

Expand All @@ -40,7 +41,7 @@ def as_elasticsearch_query(*); end

private

def ranges
def default_ranges
now = Time.now.beginning_of_day
[
{ from: now - 1.day, to: now },
Expand Down
13 changes: 4 additions & 9 deletions app/models/elasticsearch/result_ordering.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
class ResultOrdering
attr_reader :param, :sort_by, :label
attr_reader :param, :sort_by, :label, :default

# The param is passed in from the UI; the sort_by is the same information,
# but in the format used by Elasticsearch; the label is a human-readable
# representation. It's up to the caller of #new to get the mappings among
# these right.
def initialize(param, sort_by, label)
def initialize(param, sort_by, label, default = false)
@param = param
@sort_by = sort_by
@label = label
@default = default
end

def self.define(sort_by_param, model_class = Notice)
model_class::ORDERING_OPTIONS.find { |ordering| ordering.param == sort_by_param } ||
self.default_ordering
end

private

def self.default_ordering
ResultOrdering.new('relevancy desc', [:_score, :desc], 'Most Relevant')
model_class::ORDERING_OPTIONS.find { |ordering| ordering.default == true }
end
end
2 changes: 1 addition & 1 deletion app/models/elasticsearch/term_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def initialize(parameter, title = '', indexed_attribute = nil)
end

def to_partial_path
'notices/search/term_filter'
'search/term_filter'
end

# When tests for this fail, update them to use as_elasticsearch_filter,
Expand Down
2 changes: 1 addition & 1 deletion app/models/elasticsearch/term_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def initialize(parameter, field, title = '')
end

def to_partial_path
'notices/search/term_search'
'search/term_search'
end

def query_for(value, operator)
Expand Down
66 changes: 66 additions & 0 deletions app/models/media_mention.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require 'validates_automatically'

class MediaMention < ApplicationRecord
include ValidatesAutomatically
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks

PER_PAGE = 10

MULTI_MATCH_FIELDS = %w(base_search)

SEARCHABLE_FIELDS = [
TermSearch.new(:term, MULTI_MATCH_FIELDS, 'All Fields')
].freeze

now = Time.now.beginning_of_day
DATE_FACET_RANGES = [
{ from: now - 1.year, to: now },
{ from: now - 5.years, to: now },
{ from: now - 10.years, to: now },
{ from: now - 20.years, to: now }
]

FILTERABLE_FIELDS = [
TermFilter.new(:source_facet, 'Source'),
TermFilter.new(:document_type_facet, 'Document Type'),
TermFilter.new(:scale_of_mention_facet, 'Scale of Mention'),
DateRangeFilter.new(:date_facet, :date, 'Date Published', DATE_FACET_RANGES)
].freeze

ORDERING_OPTIONS = [
ResultOrdering.new('relevancy desc', [:_score, :desc], 'Most Relevant'),
ResultOrdering.new('relevancy asc', [:_score, :asc], 'Least Relevant'),
ResultOrdering.new('date desc', [:date, :desc], 'Date Published - newest', true),
ResultOrdering.new('date asc', [:date, :asc], 'Date Published - oldest')
].freeze

HIGHLIGHTS = [].freeze

validates :scale_of_mention, presence: true, inclusion: { in: LumenSetting.get('media_mentions_scale_of_mentions').split(',') }

settings do
mappings dynamic: false do
# fields
indexes :base_search, type: 'text'
indexes :title, copy_to: 'base_search'
indexes :description, copy_to: 'base_search'
indexes :source, copy_to: %w[base_search source_facet]
indexes :document_type, copy_to: %w[base_search document_type_facet]
indexes :date, type: 'date', copy_to: %w[base_search date_facet]
indexes :published, type: 'boolean'
indexes :author, copy_to: 'base_search'
indexes :scale_of_mention, copy_to: %w[base_search scale_of_mention_facet]

# facets
indexes :source_facet, type: 'keyword'
indexes :document_type_facet, type: 'keyword'
indexes :scale_of_mention_facet, type: 'keyword'
indexes :date_facet, type: 'date'
end
end

def self.visible_qualifiers
{ published: true }
end
end
2 changes: 1 addition & 1 deletion app/models/notice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Notice < ApplicationRecord
].freeze

ORDERING_OPTIONS = [
ResultOrdering.new('relevancy desc', [:_score, :desc], 'Most Relevant'),
ResultOrdering.new('relevancy desc', [:_score, :desc], 'Most Relevant', true),
ResultOrdering.new('relevancy asc', [:_score, :asc], 'Least Relevant'),
ResultOrdering.new('date_received desc', [:date_received, :desc], 'Date Received - newest'),
ResultOrdering.new('date_received asc', [:date_received, :asc], 'Date Received - oldest'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= render partial: 'search/date_range_filter', locals: { results: results, date_range_filter: date_range_filter } %>
Loading

0 comments on commit 2c150ee

Please sign in to comment.