Skip to content

Instantly share code, notes, and snippets.

@benjaminkreen
Last active January 17, 2019 21:33
Show Gist options
  • Save benjaminkreen/31cb107ef607c4847913607a2fc18d78 to your computer and use it in GitHub Desktop.
Save benjaminkreen/31cb107ef607c4847913607a2fc18d78 to your computer and use it in GitHub Desktop.
Discord user import for moodle data
require "csv"
require File.expand_path(File.dirname(__FILE__) + "/base.rb")
# Edit the constants and initialize method for your import data.
# Requires that Custom User Fields be created before running scrit with names matching the keys in REQUIRED_USER_FIELD_NAME_MAP
# Call it like this:
# RAILS_ENV=production CSV_FILE=/path/to/file.csv bundle exec ruby script/import_scripts/moodle_csv.rb
class ImportScripts::MoodleCsv < ImportScripts::Base
CSV_FILE_PATH = ENV['CSV_FILE']
# maps a user field name to a csv column index
REQUIRED_USER_FIELD_NAME_MAP = {
'Section 1' => 10,
'Section 2' => 11,
'Section 3' => 12,
'ORCiD' => 14,
'GUID' => 1,
'Institution' => 8,
'Country' => 7
}
def initialize
super
@imported_csv = load_csv
@user_fields_id_map = Hash[UserField.where(name: REQUIRED_USER_FIELD_NAME_MAP.keys).pluck(:name, :id)]
missing_fields = REQUIRED_USER_FIELD_NAME_MAP.keys - @user_fields_id_map.keys
# requires these custom user fields to already be created in the admin panel
raise "Missing custom user fields: #{missing_fields.join(', ')}, you need to create these first" unless missing_fields.empty?
end
def execute
puts "", "Importing from CSV file..."
import_groups
import_users
puts "", "Done"
end
def load_csv
# Columns: PeopleID, GUID, Username, LastName, FirstName, editorRole, email1, Country, Institute, dateJoined, Section_1, Section_2, Section_3, Discipline, ORCID
CSV.read(CSV_FILE_PATH, headers: true, encoding: 'windows-1250:utf-8') # the csv is in windowsy format
end
def import_groups
puts '', "Importing groups"
# get unique Disiplines for grouping
group_names = @imported_csv.map { |u| u[13] }.uniq.compact.map.with_index.to_a
create_groups(group_names) { |g| Hash[:full_name, g[0], :id, g[1]] }
end
def import_users
puts '', "Importing users"
create_users(@imported_csv) do |u|
{
id: u[0],
username: u[2].to_s.length > 2 ? u[2] : u[6], # use email if no username present
name: [u[4], u[3]].compact.join(' '),
email: clean_email_address(u[6].split(';').first), # a user can have several emails
created_at: u[9] ? Time.strptime(u[9], '%m/%d/%Y') : Time.now,
custom_fields: build_custom_fields(u),
post_create_action: proc do |new_user|
if group = Group.includes(:users).find_by(full_name: u[13])
group.users << new_user unless group.users.include?(new_user)
end
if remaining_emails = u[6].split(';').uniq[1..-1]
remaining_emails.map! { |e| Hash[:email, clean_email_address(e)] }
new_user.user_emails.create(remaining_emails)
end
end
}
end
end
def build_custom_fields(user)
# user is an array of values
REQUIRED_USER_FIELD_NAME_MAP.each_with_object({}) do |(name, idx), obj|
obj["user_field_#{@user_fields_id_map[name]}"] = user[idx]
end
end
def clean_email_address(email)
email.strip.delete(',')
end
end
if __FILE__ == $0
ImportScripts::MoodleCsv.new.perform
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment