concord-consortium/rigse

View on GitHub
rails/lib/tasks/fixups.rake

Summary

Maintainability
Test Coverage
require 'rake'
require 'csv'

namespace :app do
  namespace :convert do

    desc 'Fix user fields which are not compliant with ActiveRecord validation checks.'
    task :fix_invalid_user_fields => :environment do
        regex = /(?=\A[^[:cntrl:]\\<>\/&]*\z)(.*[\p{L}\d].*)/u
        count = 0
        puts
        puts "ID,Login,First name,Last name,Email"
        User.find_each do |u|
            if !(u.first_name =~ regex && u.last_name =~ regex)
                line = CSV.generate do |csv|
                    csv << [ u.id, u.login, u.first_name, u.last_name, u.email ]
                end
                puts line
                if(u.first_name !~ regex)
                    u.update(first_name: "unknown")
                end
                if(u.last_name !~ regex)
                    u.update(last_name: "unknown")
                end
                count+=1
            end
        end
        puts
        puts "Updated #{count} users."
        puts
    end

    desc "Convert Existing Clazzes so that multiple Teachers can own a clazz. (many to many change)"
    task :convert_clazzes_to_multi_teacher => :environment do
      MultiteacherClazzes.make_all_multi_teacher
    end

    desc "Erase all learner responses and reset the tables"
    task :erase_all_learner_responses_and_reset_the_tables => :environment do
      puts "Erase all saveable learner responses and reset the tables"
      saveable_models = Dir["app/models/saveable/**/*.rb"].collect { |m| m[/app\/models\/(.+?).rb/, 1] }.collect { |m| m.camelize.constantize }
      saveable_models.each do |model|
        if model.respond_to?(:table_name)
          ActiveRecord::Base.connection.delete("TRUNCATE `#{model.table_name}`")
          puts "deleted: all from #{model}"
        end
      end
      puts
    end

    # seb: 20100513
    desc "Populate the new leaid, state, and zipcode portal district and school attributes with data from the NCES tables"
    task :populate_new_district_and_school_attributes_with_data_from_nces_tables => :environment do
      puts "\nUpdating #{Portal::District.count} Portal::District models with state, leaid, and zipcode data from the Portal::Nces06District models"
      Portal::District.real.find_in_batches(:batch_size => 500) do |portal_districts|
        portal_districts.each do |portal_district|
          nces_district = Portal::Nces06District.where(:id => portal_district.nces_district_id).select("id, LEAID, LZIP, LSTATE").first
          portal_district.state   = nces_district.LSTATE
          portal_district.leaid   = nces_district.LEAID
          portal_district.zipcode = nces_district.LZIP
          portal_district.save!
        end
        print '.'; STDOUT.flush
      end

      puts "\nUpdating #{Portal::School.count} Portal::School models with state, leaid_schoolnum, and zipcode data from the Portal::Nces06School models"
      Portal::School.real.find_in_batches(:batch_size => 500) do |portal_schools|
        portal_schools.each do |portal_school|
          nces_school = Portal::Nces06School.where(:id => portal_school.nces_school_id).select("id, NCESSCH, MZIP, MSTATE").first
          portal_school.state           = nces_school.MSTATE
          portal_school.ncessch         = nces_school.NCESSCH
          portal_school.zipcode         = nces_school.MZIP
          portal_school.save!
        end
        print '.'; STDOUT.flush
      end
      puts
    end
  end

  namespace :report do
    # NSP: 20100826
    desc "report on activities without position attributes"
    task :activity_positon_bug_report, [:file_name] => :environment do |t,args|
      args.with_defaults(:file_name => 'position_bug_activity_report.csv')
      file_name = args.file_name
      suspect_activities = Activity.where("position is null and investigation_id is not null")
      good_activities =  Activity.where("position is not null and investigation_id is not null")
      puts "#{suspect_activities.size} without positions & #{good_activities.size} with good positions"
      bad_hash = suspect_activities.map do |a|
        {
          :id => a.id,
          :inv_id => a.investigation.id,
          :investigation => a.investigation.name,
          :act_size => a.investigation.activities.size,
          :z => "[ #{a.investigation.activities.map{ |iact| iact.id}.join(",")} ]",
          :published => (a.investigation.published? ? "public" : "draft"),
          :offerings => a.investigation.offerings.size,
          :updated => (a.updated_at.strftime("%F"))
        }
      end
      bad_hash = bad_hash.sort_by {|a| [a[:published], a[:inv_id], a[:id] ]}
      File.open(file_name,'w') do |file|
        bad_hash.each do |a|
          line = %/ "#{a[:investigation]}", "#{a[:published]}", "#{a[:act_size]}", "#{a[:updated]}", "#{a[:id]}", "#{a[:z]}"/
          file.puts(line)
        end
      end
      puts "report results should be in #{file_name}"
    end
  end

  namespace :fixup do
    desc "makes sure all Report::Learner attributes are not nil"
    task :remove_report_learner_nils => :environment do
      Report::Learner.find_each(:batch_size => 100) do |rl|
        # we just need to trigger the save hooks
        rl.save
      end
    end

    desc "reset all activity position information"
    task :reset_activity_positions => :environment do
      # We actually want to reset the position attribute on ALL activities
      all_invs = Investigation.all
      puts "fixing up #{all_invs.length} investigations"
      all_invs.sort_by { |inv| inv.id }.each do |inv|
        inv.reload # force the default ordering of activities
        act_order = inv.activities.map{ |a| a.id}.join(",")
        puts "working with #{inv.id} #{inv.name}"
        position = 1
        inv.activities.each do |act|
          if (act.position != position)
            puts "    fix: (#{act.position}) ==> (#{position})"
          end
          act.update!(:position => position)
          position = position + 1
        end
        inv.reload
        new_order = inv.activities.map{ |a| a.id}.join(",")
        raise "Non-matching activity order" unless (new_order == act_order)
        predicted_position = 1
        inv.activities.each do |act|
          raise "Activity has wrong position: #{act.position} != #{predicted_position}" unless (act.position == predicted_position)
          predicted_position = predicted_position + 1
        end
        puts "  reset position information for #{position - 1} activities in #{inv.name}:"
        puts "     PRE: #{act_order}"
        puts "    POST: #{new_order}"
        puts
      end
    end

    desc "delete orphaned teachers, clazzes, students, and learners"
    task :delete_orphaned_items => :environment do
      Portal::Teacher.all.select  {|t| t.user.nil? }.each    {|t| t.delete }
      Portal::Student.all.select  {|s| s.user.nil? }.each    {|s| s.delete }
      Portal::Clazz.all.select    {|c| c.teacher.nil? }.each {|c| c.delete }
      Portal::Learner.all.select  {|l| l.student.nil?}.each  {|l| l.delete }
      Portal::Offering.all.select {|o| o.clazz.nil?}.each    {|o| o.delete }
      Portal::Offering.all.select {|o| o.runnable.nil?}.each {|o| o.delete }
    end

    desc "move vernier_goio vendor interface users to new JNA driver"
    task :use_jna_for_vernier_goio => :environment do
      Fixups.switch_driver('vernier_goio','JNI','JNA')
    end

    desc "remove 'teacher' students (users which both, loose their students"
    task :remove_teachers_test_students => :environment do
      Fixups.remove_teachers_test_students
    end

    desc "move all offerings to default class"
    task :move_offerings_to_default_class => :environment do
      clazz = Portal::Clazz.default_class
      Portal::Offering.all.each do |offering|
        next if offering.clazz_id == clazz.id
        runnable_id = offering.runnable_id
        runnable_type = offering.runnable_type
        found   = Portal::Offering
                      .where(runnable_id: runnable_id,
                             runnable_type: runnable_type)
                      .detect { |o| o.clazz_id == clazz.id }
        unless found
          found = Portal::Offering.create(:runnable_id => runnable_id, :runnable_type => runnable_type, :clazz => clazz, :default_offering => true)
        end
        offering.learners.each do |learner|
          learner.offering = found
          learner.save!
        end
      end
      # We don't need to delete offerings, they are
      # switched out dynamically in the controller
      # Portal::Offering.all.each do |offering|
      #   next if offering.clazz_id == clazz.id
      #   offering.delete
      # end
    end
  end
end