Skip to content

Commit

Permalink
Merge pull request #43 from mfenner/doi_limit
Browse files Browse the repository at this point in the history
Refactored SavedDOI into Cart model.
  • Loading branch information
Martin Fenner committed Sep 20, 2014
2 parents fe3846d + 8bc36f3 commit 4bdcebc
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 201 deletions.
16 changes: 8 additions & 8 deletions Cheffile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ SITE
windows (1.34.2)
chef_handler (>= 0.0.0)
xfs (1.1.0)
yum (3.2.4)
yum-epel (0.4.0)
yum (3.3.2)
yum-epel (0.5.1)
yum (~> 3.0)
yum-mysql-community (0.1.10)
yum (>= 3.0)

GIT
remote: [email protected]:articlemetrics/alm_report-cookbook.git
ref: master
sha: f672fc11e2fd81a304d0e68fa776bb8bdc8afcd1
sha: e3843f2c9d81a90fc4ed9d2060ad46dd82fc3150
specs:
alm_report (0.5.6)
alm_report (0.5.8)
apt (>= 0.0.0)
capistrano (~> 0.6.0)
database (>= 0.0.0)
Expand All @@ -75,9 +75,9 @@ GIT
GIT
remote: [email protected]:articlemetrics/capistrano-cookbook.git
ref: master
sha: 43d031f6041ca8a034bd89bde5167a51459d1f0e
sha: d17dff7d3fef0359f11d3c69ee66013ad59f555d
specs:
capistrano (0.6.4)
capistrano (0.6.5)
ruby (~> 0.3.0)

GIT
Expand All @@ -102,9 +102,9 @@ GIT
GIT
remote: [email protected]:articlemetrics/ruby-cookbook.git
ref: master
sha: 099726c8bdcdb61376a9e15aead239346b26061f
sha: bf75f7445ec401696e10c8f4e346f86e9c2604a2
specs:
ruby (0.3.2)
ruby (0.3.5)
apt (~> 2.5.3)

DEPENDENCIES
Expand Down
106 changes: 21 additions & 85 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,62 +1,3 @@

# Exception class thrown when there is an attempt to save a new DOI in the session,
# but the article limit has been reached.
class DoiLimitReachedError < StandardError
end


# Wrapper around the session data which enforces the limit on the number of articles
# per report. Controller code should read and write through this interface instead
# of the session directly.
class SavedDois

attr_reader :saved


def initialize(session_data)
@saved = session_data
if @saved.nil?
@saved = {}
end
end


def [](x)
return @saved[x]
end


def []=(x, val)
if @saved.length >= APP_CONFIG["article_limit"]
raise DoiLimitReachedError, "Reached limit of #{APP_CONFIG["article_limit"]} DOIs"
else
@saved[x] = val
end
end


def delete(val)
@saved.delete(val)
end


def clone
@saved.clone
end


def length
@saved.length
end


def clear
@saved = {}
end

end


class ApplicationController < ActionController::Base

protect_from_forgery
Expand All @@ -75,64 +16,59 @@ class ApplicationController < ActionController::Base
# rescue_from StandardError, :with => :internal_error
end


# See comment in routes.rb and https://github.com/rails/rails/issues/671
# for why this is necessary.
def routing_error
raise ActionController::RoutingError.new(params[:path])
end


def page_not_found
@display_nav = false
@title = "Page Not Found"
render :template => "static_pages/page_not_found", :status => 404
end


def internal_error
@display_nav = false
@title = "Internal Error"
render :template => "static_pages/internal_error", :status => 500
end


# Sets @saved_dois based on the contents of the session, and saves it back to the
# Sets @cart based on the contents of the session, and saves it back to the
# session after an action is run.
def save_session_dois
@saved_dois = SavedDois.new(session[:dois])
@cart = Cart.new(session[:dois])

yield # Run the action

session[:dois] = @saved_dois.saved
session[:dois] = @cart.dois
end


# Sets fields used by the UI for results paging of articles.
# A precondition of this method is that @total_found is set appropriately.
def set_paging_vars(current_page, results_per_page=APP_CONFIG["results_per_page"])
current_page = current_page.nil? ? "1" : current_page
@start_result = (current_page.to_i - 1) * results_per_page + 1
@end_result = @start_result + results_per_page - 1
@end_result = [@end_result, @total_found].min
end
protected :set_paging_vars

# The navigation UI element (1 Select Articles and etc) will not be displayed on the static pages
# That is the only change for the static pages so having a whole separate layout seemed like an overkill
# This might change in the future
def display_nav
@display_nav = true
end

def articleLimitReached?
# prevent the user from moving forward if the article limit has been reached
if (session[:dois].length >= APP_CONFIG["article_limit"])
flash[:error] = "The maximum report size is #{APP_CONFIG["article_limit"]} articles. Go to <a href=\"/preview-list\">Preview List</a> and remove articles before adding more to your selection."
return true
else
return false
end
# prevent the user from moving forward if the article limit has been reached
def article_limit_reached?
return false if @cart.size < APP_CONFIG["article_limit"]

flash[:error] = "The maximum report size is #{APP_CONFIG["article_limit"]} " \
"articles. Go to <a href=\"/preview-list\">Preview List</a> " \
"and remove articles before adding more to your selection."
true
end

protected

# Sets fields used by the UI for results paging of articles.
# A precondition of this method is that @total_found is set appropriately.
def set_paging_vars(current_page, results_per_page=APP_CONFIG["results_per_page"])
current_page = current_page.nil? ? "1" : current_page
@start_result = (current_page.to_i - 1) * results_per_page + 1
@end_result = @start_result + results_per_page - 1
@end_result = [@end_result, @total_found].min
end
end
98 changes: 41 additions & 57 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,74 +53,62 @@ def add_articles
# convert the journal key to journal name
@filter_journal_names = []
if !params["filterJournals"].nil?
if (!APP_CONFIG["journals"].nil? && APP_CONFIG["journals"].size > 0)
if APP_CONFIG["journals"].present?
params["filterJournals"].each do | journal_key |
journal_name = APP_CONFIG["journals"][journal_key]
if !journal_name.nil?
@filter_journal_names << journal_name
end
@filter_journal_names << journal_name if journal_name.present?
end
end
end

end

# get the dois that have been selected
dois = session[:dois]

# make sure that the articles that have been checked previously are checked when we render the page
if (!dois.nil? && !dois.empty?)
@docs.each do | doc |
if (dois.has_key?(doc["id"]))
doc[:doc_checked] = true
end
end
# make sure that the articles that have been checked previously are checked
# when we render the page
if @cart.dois.present?
@docs.each { |doc| doc[:doc_checked] = true \
if (@cart.dois.has_key?(doc["id"])) }
end

set_paging_vars(params[:current_page])
end

# Parses date sent in the ajax call to update_session. This is of the form
# "10.1371/journal.pone.0052192|12345678"; that is, a DOI and a timestamp separated by
# a '|' character. Returns (doi, timestamp).
def parse_article_key(key)
fields = key.split("|")
return fields[0], fields[1].to_i
end
private :parse_article_key

# Update session via ajax call
# params[:article_ids] is of the form "10.1371/journal.pone.0052192|12345678";
def update_session
initial_count = @saved_dois.length
status = "success"
if params[:mode] == "SAVE"
if initial_count >= APP_CONFIG["article_limit"]
status = "limit"
else
params[:article_ids][0..(APP_CONFIG["article_limit"] - initial_count - 1)].each do |doc_key|
doi, pub_date = parse_article_key(doc_key)
@saved_dois[doi] = pub_date
end
end
elsif params[:mode] == "REMOVE"
params[:article_ids].each do |doc_key|
doi, _ = parse_article_key(doc_key)
@saved_dois.delete(doi)
end
else
raise "Unexpected mode " + params[:mode]
initial_count = @cart.size

# don't update session when article_limit reached
return render json: { status: "limit", delta: 0 } \
unless initial_count < APP_CONFIG["article_limit"]

# generate hash in format doi => timestamp, observe article_limit
article_ids = parse_article_keys(params[:article_ids], initial_count)

case params[:mode]
when "SAVE" then @cart.merge!(article_ids)
when "REMOVE" then @cart.except!(article_ids.keys)
end

payload = {:status => status, :delta => @saved_dois.length - initial_count}
respond_to do |format|
format.json { render :json => payload}
render json: { status: "success", delta: @cart.size - initial_count }
end

# Parse array of keys in the form "10.1371/journal.pone.0052192|12345678",
# i.e. a doi and timestamp separated by a '|' character. Returns a hash.
# Hash is empty if params[:article_ids] is nil or limit reached
def parse_article_keys(keys, count = 0)
limit = APP_CONFIG["article_limit"] - count
return {} unless limit > 0

article_ids = Array(keys)[0...limit].reduce({}) do |hash, id|
fields = id.split("|")
hash.merge(fields.first => fields.last.to_i)
end
end

# Simple AJAX action that returns the count of articles stored in the session.
def get_article_count
respond_to do |format|
format.json {render :json => @saved_dois.length}
end
render json: @cart.size
end

# Queries solr for the results used by select_all_search_results.
Expand Down Expand Up @@ -156,7 +144,7 @@ def get_all_results
# *all* of the articles from the search, not just those on the current page.
# (Subject to the article limit.)
def select_all_search_results
initial_count = @saved_dois.length
initial_count = @cart.size

# This is a little weird... if the user has no more capacity before the
# article limit, return an error status, but if at least one article can
Expand All @@ -177,31 +165,27 @@ def select_all_search_results
return
end
docs.each do |doc|
begin
@saved_dois[doc["id"]] = doc["publication_date"].strftime("%s").to_i
rescue DoiLimitReachedError
break
end
@cart[doc["id"]] = doc["publication_date"].strftime("%s").to_i
end
end

payload = {:status => status, :delta => @saved_dois.length - initial_count}
payload = {:status => status, :delta => @cart.size - initial_count}
respond_to do |format|
format.json { render :json => payload}
end
end

# Action that clears any DOIs in the session and redirects to home.
def start_over
@saved_dois.clear
@cart.clear
redirect_to :action => :index
end

def preview_list
@tab = :preview_list
@title = "Preview List"
dois = @saved_dois.clone
@total_found = dois.length
@total_found = @cart.size
dois = @cart.clone
set_paging_vars(params[:current_page])

# Convert to array, sorted in descending order by timestamp, then throw away the timestamps.
Expand Down
Loading

0 comments on commit 4bdcebc

Please sign in to comment.