Skip to content

Commit

Permalink
+ Add support for uploading of CSV datafiles.
Browse files Browse the repository at this point in the history
  • Loading branch information
manxingxing committed Jul 25, 2013
1 parent e095a04 commit cda243b
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 7 deletions.
8 changes: 5 additions & 3 deletions app/controllers/datasets_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class DatasetsController < ApplicationController
allow all, :if => :dataset_is_free_for_public
end

actions :new, :create, :create_with_workbook do
actions :new, :create, :create_with_datafile do
allow logged_in
end
end
Expand All @@ -48,7 +48,7 @@ def create # create dataset with only a title
end
end

def create_with_workbook
def create_with_datafile
unless params[:datafile]
flash[:error] = "No data file given for upload"
redirect_to :back and return
Expand All @@ -60,7 +60,9 @@ def create_with_workbook
redirect_to :back and return
end

@dataset = Dataset.new(datafile.general_metadata_hash)
attributes = datafile.general_metadata_hash
attributes.merge!(title: params[:title].squish.capitalize) if params[:title]
@dataset = Dataset.new(attributes)
if @dataset.save
@dataset.add_datafile(datafile)
@dataset.load_projects_and_authors_from_spreadsheet
Expand Down
116 changes: 116 additions & 0 deletions app/models/csv_data.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
class CsvData
include ActiveModel::Validations
validate :check_csvfile

# define 'strip' converter
CSV::Converters[:strip] = lambda {|f| f.try(:strip) }
CSV::HeaderConverters[:strip] = lambda {|f| f.try(:strip) }

OPTS = {
headers: true,
return_headers: false,
skip_blanks: true,
converters: :strip,
header_converters: :strip
}

def initialize(datafile)
@dataset = datafile.dataset
@path = datafile.path
end

def general_metadata_hash
{}
end

def authors_list
{
found_users: [],
unfound_users: []
}
end

def projects_list
{}
end

def headers
return @headers if defined? @headers
CSV.open @path, OPTS do |csv|
@headers = csv.first.headers
end
return @headers
end

def import_data
save_datacolumns
import_sheetcells
end

private

def check_csvfile
errors.add :base, 'Failed to find data in your file' and return unless headers.present?
errors.add :base, 'It seems one or more columns have not a header' and return if headers.any? {|h| h.blank? }
errors.add :file, 'column headers must be uniq' unless headers.uniq_by(&:downcase).length == headers.length
end

def save_datacolumns
@datacolumns = headers.map.with_index do |h, i|
datagroup = assign_datagroup_to_column(h)
Datacolumn.create! do |dc|
dc.columnheader = h
dc.definition = h
dc.columnnr = i + 1
dc.dataset_id = @dataset.id
dc.datatype_approved = false
dc.datagroup_approved = false
dc.finished = false
dc.datagroup_id = datagroup.id
end
end
end

def import_sheetcells
id_for_header = header_id_lookup_table
counter = 0
sheetcells_in_queue = []

CSV.foreach @path, OPTS do |row|
row.to_hash.each do |k, v|
next if v.blank?
sheetcells_in_queue << [ id_for_header[k], v, $INPUT_LINE_NUMBER,
Datatypehelper::UNKNOWN.id, Sheetcellstatus::UNPROCESSED ]

counter += 1
if counter == 1000
save_data_into_database(sheetcells_in_queue)
counter = 0
sheetcells_in_queue.clear
end
end
end
save_data_into_database(sheetcells_in_queue)
end

def assign_datagroup_to_column(columnheader)
datagroup = Datagroup.where(["title iLike ?", columnheader]).first
return datagroup if datagroup
return Datagroup.create!(title: columnheader)
end

def header_id_lookup_table
hash = {}
columns = defined?(@datacolumns) ? @datacolumns : @dataset.datacolumns
columns.each do |dc|
hash[dc.columnheader] = dc.id
end
return hash
end

def save_data_into_database(sheetcells)
columns = [:datacolumn_id, :import_value, :row_number, :datatype_id, :status_id]
Sheetcell.import columns, sheetcells, :validate => false
end

end
1 change: 1 addition & 0 deletions app/models/datafile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def spreadsheet
return @spreadsheet if defined? @spreadsheet
@spreadsheet = case File.extname(path)
when '.xls' then Dataworkbook.new(self)
when '.csv' then CsvData.new(self)
else nil
end
end
Expand Down
6 changes: 5 additions & 1 deletion app/views/datasets/edit_files.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
= link_to_if(index > 0, "delete", dataset_datafile_path(@dataset, datafile), :method => :delete, :confirm => "Are you sure to delete this workbook ?") do
protected

%h3 Upload Excel workbook
%h3 Upload Datafile

%p
%b Note:
Only Excel-2003 and CSV files are supported.

= form_for :datafile,
:url => update_workbook_dataset_path(@dataset),
Expand Down
12 changes: 11 additions & 1 deletion app/views/datasets/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#{link_to "here", help_url}.


= form_for Datafile.new, :url => {:controller => :datasets, :action => :create_with_workbook}, :html => {:multipart => true} do |f|
= form_for Datafile.new, :url => {:controller => :datasets, :action => :create_with_datafile}, :html => {:multipart => true} do |f|
%h4
Excel workbook
= f.error_messages
Expand All @@ -38,3 +38,13 @@
%br
= f.submit "Submit"

.row
.dataset-create-option.span-6
%h3 Option C: Create dataset with CSV file
= form_for Datafile.new, url: create_with_workbook_datasets_path, html: {multipart: true} do |f|
%dl
%dt Title
%dd= text_field_tag 'title'
= f.file_field :file
%br
= f.submit 'Submit'
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
match 'search' => 'pages#search'

resources :datasets, :except => [:index] do
post :create_with_workbook, :on => :collection
post :create_with_datafile, :on => :collection
resources :datafiles, :only => [:destroy] do
get :download, :on => :member
end
Expand Down
2 changes: 1 addition & 1 deletion test/functional/datasets_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class DatasetsControllerTest < ActionController::TestCase

# create a new dataset using this problematic workbook
@request.env['HTTP_REFERER'] = new_dataset_path
post :create_with_workbook, :datafile => {:file => uploaded_file}
post :create_with_datafile, :datafile => {:file => uploaded_file}
assert_redirected_to new_dataset_path
assert_equal 'File column headers in the raw data sheet must be unique', flash[:error]

Expand Down

0 comments on commit cda243b

Please sign in to comment.