Skip to content

Commit

Permalink
Extract SolrDocument references from controllers and models and define
Browse files Browse the repository at this point in the history
the solr document class to use in the blacklight configuration.

- add blacklight_config.solr_document_model configuration (defaults to
  SolrDocument)
- make Bookmarks polymorphic and refactor Bookmarks to use objects
  instead of passing IDs around
  • Loading branch information
cbeer committed Mar 27, 2014
1 parent 7fe5863 commit f18362a
Show file tree
Hide file tree
Showing 21 changed files with 211 additions and 109 deletions.
14 changes: 7 additions & 7 deletions app/controllers/bookmarks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def index
@bookmarks = current_or_guest_user.bookmarks
bookmark_ids = @bookmarks.collect { |b| b.document_id.to_s }

@response, @document_list = get_solr_response_for_field_values(SolrDocument.unique_key, bookmark_ids)
@response, @document_list = get_solr_response_for_document_ids(bookmark_ids)
end

def update
Expand All @@ -41,13 +41,13 @@ def create
if params[:bookmarks]
@bookmarks = params[:bookmarks]
else
@bookmarks = [{ :document_id => params[:id] }]
@bookmarks = [{ document_id: params[:id], document_type: blacklight_config.solr_document_model.to_s }]
end

current_or_guest_user.save! unless current_or_guest_user.persisted?

success = @bookmarks.all? do |bookmark|
current_or_guest_user.bookmarks.create(bookmark) unless current_or_guest_user.existing_bookmark_for(bookmark[:document_id])
current_or_guest_user.bookmarks.create(bookmark) unless current_or_guest_user.bookmarks.where(bookmark).exists?
end

if request.xhr?
Expand All @@ -66,10 +66,10 @@ def create
# Beware, :id is the Solr document_id, not the actual Bookmark id.
# idempotent, as DELETE is supposed to be.
def destroy
bookmark = current_or_guest_user.existing_bookmark_for(params[:id])
success = (!bookmark) || current_or_guest_user.bookmarks.delete(bookmark)
bookmark = current_or_guest_user.bookmarks.where(document_id: params[:id], document_type: blacklight_config.solr_document_model).first

success = bookmark && bookmark.delete && bookmark.destroyed?

unless request.xhr?
if success
flash[:notice] = I18n.t('blacklight.bookmarks.remove.success')
Expand Down
5 changes: 5 additions & 0 deletions app/helpers/blacklight/catalog_helper_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,9 @@ def render_view_type_group_icon view
def default_view_type_group_icon_classes view
"glyphicon-#{view.to_s.parameterize } view-icon-#{view.to_s.parameterize}"
end

def current_bookmarks response = nil
response ||= @response
@current_bookmarks ||= current_or_guest_user.bookmarks_for_documents(response.documents).to_a
end
end
2 changes: 1 addition & 1 deletion app/helpers/blacklight/configuration_helper_behavior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def spell_check_max

# Used in the document list partial (search view) for creating a link to the document show action
def document_show_link_field document=nil
blacklight_config.view_config(document_index_view_type).title_field.to_sym
blacklight_config.view_config(document_index_view_type).title_field.try(:to_sym) || document.id
end

##
Expand Down
17 changes: 13 additions & 4 deletions app/models/bookmark.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# -*- encoding : utf-8 -*-
class Bookmark < ActiveRecord::Base

belongs_to :user
validates_presence_of :user_id, :scope=>:document_id
attr_accessible :id, :document_id, :title if Rails::VERSION::MAJOR < 4
belongs_to :user, polymorphic: true
belongs_to :document, polymorphic: true

validates_presence_of :user_id, :scope=>:document_id
attr_accessible :id, :document_id, :document_type, :title if Rails::VERSION::MAJOR < 4

def document
SolrDocument.new SolrDocument.unique_key => document_id
document_type.new document_type.unique_key => document_id
end

def document_type
(super.constantize if defined?(super)) || default_document_type
end

def default_document_type
SolrDocument
end

end
5 changes: 5 additions & 0 deletions app/models/solr_document.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class SolrDocument

include Blacklight::Solr::Document

end
4 changes: 2 additions & 2 deletions app/views/catalog/_bookmark_control.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# Note these two forms are pretty similar but for different :methods, classes, and labels.
# but it was simpler to leave them seperate instead of DRYing them, got confusing trying that.
# the data-doc-id attribute is used by our JS that converts to a checkbox/label.
-%>
<% unless current_or_guest_user.document_is_bookmarked? document.id %>
-%>
<% if current_bookmarks.find { |x| x.document_id == document.id and x.document_type == document.class }.blank? %>
<%= form_tag( bookmark_path( document ), :method => :put, :class => "bookmark_toggle", "data-doc-id" => document.id, :'data-present' => t('blacklight.search.bookmarks.present'), :'data-absent' => t('blacklight.search.bookmarks.absent'), :'data-inprogress' => t('blacklight.search.bookmarks.inprogress')) do %>
<%= submit_tag(t('blacklight.bookmarks.add.button'), :id => "bookmark_toggle_#{document.id.to_s.parameterize}", :class => "bookmark_add") %>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- encoding : utf-8 -*-
class AddPolymorphicTypeToBookmarks < ActiveRecord::Migration
def change
add_column(:bookmarks, :document_type, :string)

add_index :bookmarks, :user_id
end
end
8 changes: 4 additions & 4 deletions lib/blacklight/catalog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def index

# get single document from the solr index
def show
@response, @document = get_solr_response_for_doc_id
@response, @document = get_solr_response_for_doc_id

respond_to do |format|
format.html {setup_next_and_previous_documents}
Expand Down Expand Up @@ -103,7 +103,7 @@ def opensearch

# citation action
def citation
@response, @documents = get_solr_response_for_field_values(SolrDocument.unique_key,params[:id])
@response, @documents = get_solr_response_for_document_ids(params[:id])
respond_to do |format|
format.html
format.js { render :layout => false }
Expand All @@ -113,7 +113,7 @@ def citation

# Email Action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
def email
@response, @documents = get_solr_response_for_field_values(SolrDocument.unique_key,params[:id])
@response, @documents = get_solr_response_for_document_ids(params[:id])

if request.post? and validate_email_params
email = RecordMailer.email_record(@documents, {:to => params[:to], :message => params[:message]}, url_options)
Expand All @@ -136,7 +136,7 @@ def email

# SMS action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
def sms
@response, @documents = get_solr_response_for_field_values(SolrDocument.unique_key,params[:id])
@response, @documents = get_solr_response_for_document_ids(params[:id])

if request.post? and validate_sms_params
to = "#{params[:to].gsub(/[^\d]/, '')}@#{sms_mappings[params[:carrier]]}"
Expand Down
11 changes: 8 additions & 3 deletions lib/blacklight/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'solr_document'

module Blacklight
##
# Blacklight::Configuration holds the configuration for a Blacklight::Controller, including
Expand All @@ -18,8 +20,6 @@ class Configuration < OpenStructWithHashAccess
class << self
def default_values
@default_values ||= begin
unique_key = ((SolrDocument.unique_key if defined?(SolrDocument)) || 'id')

{
# HTTP method to use when making requests to solr; valid
# values are :get and :post.
Expand All @@ -30,6 +30,7 @@ def default_values
:solr_path => 'select',
# Default values of parameters to send with every search request
:default_solr_params => {},
:solr_document_model => SolrDocument,
# The solr rqeuest handler to use when requesting only a single document
:document_solr_request_handler => 'document',
# THe path to send single document requests to solr
Expand All @@ -50,7 +51,7 @@ def default_values
# General configuration for all views
:index => ViewConfig::Index.new(
# solr field to use to render a document title
:title_field => unique_key,
:title_field => nil,
# solr field to use to render format-specific partials
:display_type_field => 'format',
# partials to render for each document(see #render_document_partials)
Expand Down Expand Up @@ -160,6 +161,10 @@ def default_sort_field

field
end

def default_title_field
solr_document_model.unique_key || 'id'
end

##
# Add any configured facet fields to the default solr parameters hash
Expand Down
15 changes: 15 additions & 0 deletions lib/blacklight/solr/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,14 @@ def to_semantic_values
return @semantic_value_hash
end

def destroyed?
false
end

def new_record?
false
end

# Certain class-level methods needed for the document-specific
# extendability architecture
module ClassMethods
Expand All @@ -160,6 +167,14 @@ module ClassMethods
def unique_key
@unique_key ||= 'id'
end

def primary_key
'id'
end

def base_class
self
end

# Returns array of hashes of registered extensions. Each hash
# has a :module_obj key and a :condition_proc key. Usually this
Expand Down
11 changes: 8 additions & 3 deletions lib/blacklight/solr_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def find(*args)
key = blacklight_config.http_method == :post ? :data : :params
res = blacklight_solr.send_and_receive(path, {key=>solr_params.to_hash, method:blacklight_config.http_method})

solr_response = Blacklight::SolrResponse.new(force_to_utf8(res), solr_params)
solr_response = Blacklight::SolrResponse.new(force_to_utf8(res), solr_params, solr_document_model: blacklight_config.solr_document_model)

Rails.logger.debug("Solr query: #{solr_params.inspect}")
Rails.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
Expand Down Expand Up @@ -169,10 +169,14 @@ def solr_doc_params(id=nil)
def get_solr_response_for_doc_id(id=nil, extra_controller_params={})
solr_params = solr_doc_params(id).merge(extra_controller_params)
solr_response = find(blacklight_config.document_solr_path, solr_params)
raise Blacklight::Exceptions::InvalidSolrID.new if solr_response.docs.empty?
raise Blacklight::Exceptions::InvalidSolrID.new if solr_response.documents.empty?
[solr_response, solr_response.documents.first]
end

def get_solr_response_for_document_ids(ids=[], extra_solr_params = {})
get_solr_response_for_field_values(blacklight_config.solr_document_model.unique_key, ids, extra_solr_params)
end

# given a field name and array of values, get the matching SOLR documents
def get_solr_response_for_field_values(field, values, extra_solr_params = {})
q = if Array(values).empty?
Expand Down Expand Up @@ -323,7 +327,7 @@ def get_opensearch_response(field=nil, extra_controller_params={})
solr_params = solr_opensearch_params().merge(extra_controller_params)
response = find(solr_params)
a = [solr_params[:q]]
a << response.docs.map {|doc| doc[solr_params[:fl]].to_s }
a << response.documents.map {|doc| doc[solr_params[:fl]].to_s }
end


Expand Down Expand Up @@ -372,4 +376,5 @@ def blacklight_solr_config
def should_add_to_solr field_name, field
field.include_in_request || (field.include_in_request.nil? && blacklight_config.add_field_configuration_to_solr_request)
end

end
44 changes: 12 additions & 32 deletions lib/blacklight/solr_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ class Blacklight::SolrResponse < HashWithIndifferentAccess

require 'blacklight/solr_response/pagination_methods'

autoload :Spelling, 'blacklight/solr_response/spelling'
autoload :Facets, 'blacklight/solr_response/facets'
autoload :MoreLikeThis, 'blacklight/solr_response/more_like_this'
require 'blacklight/solr_response/response'
require 'blacklight/solr_response/spelling'
require 'blacklight/solr_response/facets'
require 'blacklight/solr_response/more_like_this'
autoload :GroupResponse, 'blacklight/solr_response/group_response'
autoload :Group, 'blacklight/solr_response/group'

include PaginationMethods
include Spelling
include Facets
include Response
include MoreLikeThis

attr_reader :request_params
def initialize(data, request_params)
attr_accessor :solr_document_model
def initialize(data, request_params, options = {})
super(data)
@request_params = request_params
extend Spelling
extend Facets
extend Response
extend MoreLikeThis
self.solr_document_model = options[:solr_document_model] || SolrDocument
end

def header
Expand All @@ -44,11 +47,7 @@ def docs
end

def documents
docs.collect{|doc| SolrDocument.new(doc, self) }
end

def spelling
self['spelling']
docs.collect{|doc| solr_document_model.new(doc, self) }
end

def grouped
Expand Down Expand Up @@ -76,23 +75,4 @@ def grouped?
self.has_key? "grouped"
end

module Response
def response
self[:response] || {}
end

# short cut to response['numFound']
def total
response[:numFound].to_s.to_i
end

def start
response[:start].to_s.to_i
end

def empty?
total == 0
end

end
end
18 changes: 18 additions & 0 deletions lib/blacklight/solr_response/response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Blacklight::SolrResponse::Response
def response
self[:response] || {}
end

# short cut to response['numFound']
def total
response[:numFound].to_s.to_i
end

def start
response[:start].to_s.to_i
end

def empty?
total == 0
end
end
21 changes: 17 additions & 4 deletions lib/blacklight/user.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# -*- encoding : utf-8 -*-
module Blacklight::User

extend Deprecation
self.deprecation_horizon = 'blacklight 6.0'

# This gives us an is_blacklight_user method that can be included in
# the containing applications models.
Expand All @@ -12,17 +15,27 @@ def self.included(base)
end
end

def bookmarks_for_documents documents = []
if documents.length > 0
bookmarks.where(document_type: documents.first.class.base_class, document_id: documents.map { |x| x.id})
else
[]
end
end

def bookmarked_document_ids
Deprecation.warn self, "The User#bookmarked_document_ids method is deprecated and will be removed in Blacklight 6.0"

self.bookmarks.pluck(:document_id)
end

def document_is_bookmarked?(document_id)
bookmarked_document_ids.include? document_id.to_s
def document_is_bookmarked?(document)
bookmarks_for_documents([document]).any?
end

# returns a Bookmark object if there is one for document_id, else
# nil.
def existing_bookmark_for(document_id)
self.bookmarks.where(:document_id => document_id).first
def existing_bookmark_for(document)
bookmarks_for_documents([document]).first
end
end

0 comments on commit f18362a

Please sign in to comment.