Custom user fields and csv import

Hi all,
One more question regarding custom user profile fields and csv imports.
It appears the fields we can populate using the cv imports is limited, but we’d like to populate some custom user fields we’ve created.
In taking a look through this support forum, I “think” it’s possible, but I’m not sure how, or how complicated it will be.
Again, thanks in advance for helping this newbie out. I have lots of smarter people involved who can help implement once I give them the initial info! :slight_smile:

1 Like

The Ning importer imports custom user fields. You can use that as an example.

2 Likes

And by “using that as an example” I presume you mean we could use that as a template for scripting a custom import of our own? It looks like ning imports json, and we’re looking to import from a csv file.
I should probably be more clear - we’re hoping to import several thousand users and send them an invite to our new discourse environment. When we import those users, we’d like to add some custom field data to their user profiles.
Is the ning importer still the best option to accomplish this? Or, alternately, is there a better means to do it?
Thanks again

My idea was that you’d see how the Ning script created and populated custom user fields and modify your script to do the same. You’d not change the part of your script that reads the csv file.

It sounds like you also need to look for a script that reads a CSV to see how to read a CSV in ruby. I think that I had assumed you had that part figured out.

If you have a budget, my contact information is in my profile.

1 Like

Here is a class we used to import custom fields and to assign members to a group(s).

require File.expand_path( "/var/www/discourse/script/import_scripts/base.rb")

class ImportScripts::BD2L < ImportScripts::Base
  
  def initialize
    super

    @htmlentities = HTMLEntities.new    
    @import_config_file = ARGV[0]
    raise ArgumentError.new('Bringing Data to Life import script config file argument is missing. Provide the full path to the config json file.') if @import_config_file.blank?

    
  end
  
  def import_users(import_array)
  
    puts "import_users.started"
    
    if import_array == nil then
      puts "import_users: skipped."
    else
      puts "import_users.import_array: #{import_array}"
    
       
      candidate_users = Array.new
      import_array.each do |import|
      
        puts "import_users.import_array.import: #{import}"
        
        mobile = UserField.find_by_name("Mobile")
        landline = UserField.find_by_name("Landline")
        postcode = UserField.find_by_name("Postcode")
        
        groups = Array.new
        import['groups'].each do |group_name|
          group = Group.find_by(name:group_name)
          if group == nil then
            # ignore
          else
            groups.push(group)
          end
        end
        
        @members = parse_import_json_file(import['path'])
        @members.each do |member|
          # puts "import_users.import_array.import.members.member: #{member}"
          email = member['email']
          if email.length == 0 then
            email = member['name'].gsub(' ','.').downcase + '@domain.com'
            puts email
            member['email'] = email
          end
          if email.length > 0 and member['name'].length > 0 and email != '@domain.com' then
            #puts email
            user = User.find_by_email(email)
            if user == nil then
              username = member['name'].gsub(' ','.').downcase
              member['username'] = username
              #puts "create"
              candidate = {}
              candidate['id'] = member['external-id']
              candidate['username'] = member['username']
              candidate['name'] = member['name']
              candidate['email'] = member['email']
              candidate['mobile'] = member['mobile'] # user custom field
              candidate['landline'] = member['landline'] # user custom field
              candidate['postcode'] = member['postcode'] # user custom field
              candidate['groups'] = groups
              candidate['mobile-user-field'] = mobile # userField
              candidate['landline-user-field'] = landline # userField
              candidate['postcode-user-field'] = postcode # userField

              candidate_users.push(candidate)

            else
              groups.each do |group|
                if group.user_ids.include?(user.id) then
                  # already a memeber
                else
                  group.add user
                end
              end
            end
          end
        end
      end # import_array.each do |import|
     
      if candidate_users.length > 0 then
        puts "calling create_users with candidate_users.length #{candidate_users.length}"
        create_users(candidate_users) do |candidate|
          { id: candidate['id'],
            username: candidate['username'],
            email: candidate['email'],
            name: candidate['name'],
            active: true,
            approved: true,
            post_create_action: proc do |user|
              
              user.save
              
              puts "user.id: #{user.id} user.email #{user.email}"
              
              candidate['groups'].each do |group|
                if group.user_ids.include?(user.id) then
                  # already a member
                else
                  group.add user
                  if user.primary_group == nil then
                    user.primary_group = group
                    user.save
                  end
                end
              end
              
              mobile = candidate['mobile-user-field']
              landline = candidate['landline-user-field']
              postcode = candidate['postcode-user-field']
              
              if candidate['mobile'].length > 0 then
                user_field_name = sprintf("user_field_%d", mobile.id) 
                user_custom_field = UserCustomField.where(user_id:user.id,name:mobile.name).first
                if user_custom_field == nil then
                  user_custom_field = UserCustomField.create!(user_id: user.id, name: user_field_name, value: candidate['mobile'])
                else
                  if user_custom_field.value != candidate['mobile'] then
                    user_custom_field.value = candidate['mobile']
                    user_custom_field.save!
                  end
                end
              end
              
              if candidate['landline'].length > 0 then
                user_field_name = sprintf("user_field_%d", landline.id) 
                user_custom_field = UserCustomField.where(user_id:user.id,name:landline.name).first
                if user_custom_field == nil then
                  user_custom_field = UserCustomField.create!(user_id: user.id, name: user_field_name, value: candidate['landline'])
                else
                  if user_custom_field.value != candidate['landline'] then
                    user_custom_field.value = candidate['landline']
                    user_custom_field.save!
                  end
                end
              end
              
              if candidate['postcode'].length > 0 then
                user_field_name = sprintf("user_field_%d", postcode.id) 
                user_custom_field = UserCustomField.where(user_id:user.id,name:postcode.name).first
                if user_custom_field == nil then
                  user_custom_field = UserCustomField.create!(user_id: user.id, name: user_field_name, value: candidate['postcode'])
                else
                  if user_custom_field.value != candidate['postcode'] then
                    user_custom_field.value = candidate['postcode']
                    user_custom_field.save!
                  end
                end
              end 
            end
          }
        end
      else 
        puts "No processing done for candidates candidate_users.length #{candidate_users.length}"
      end # if candidate_users.length > 0
       
    end # if import_array == nil then
      
    puts "import_users.finished"
    
  end
  
  def parse_import_json_file(path)
    puts "parse_import_json_file('#{path}')"
    text = File.read(path)
    result = JSON.parse(text)
    return result
  end
    
  def execute
    
    @config = parse_import_json_file(@import_config_file)
    import_users(@config['users'])
    
  end
  
end

if ARGV[0] == nil then
  ARGV[0] = "/shared/bd2l/members-configuration.json"
end

ImportScripts::BD2L.new.perform
6 Likes