module RenamingUtil # Rename the given record in memory (without saving it!) # by trying various combinations of appending number/s to the # end of its name (provided by the name column). # # WARNING: Other record fields MUST BE valid before calling # this function, as it uses the ActiveRecord.valid? method. # # WARNING: The maximum length validations on the provided name_col # MUST BE at least 10 characters, otherwise this function can # stir some odd behaviour. def rename_record(record, name_col) clazz = record.class prev_name = record[name_col] # Skip already valid records if record.valid? return end # Get the max. length validation, if it exist # IF MAX_LENGTH IS VERY LOW, this code here could # potentially cause trouble. Let's hope max_length is always 10+ max_length = 99999 clazz .validators_on(name_col) .select{ |v| v.class == ActiveModel::Validations::LengthValidator } .each do |v| max = v.options[:maximum] if max.present? && max < max_length max_length = max end end # First, check if name is simply too long if prev_name.length > max_length then record[name_col] = prev_name[0..(max_length - 4)] + "..." if record.valid? return end end # Now, start renaming (we try 100 tries) cntr = 0 while (record.invalid? && cntr < 100) do cntr += 1 suffix = " (#{cntr})" if prev_name.length + suffix.length > max_length record[name_col] = prev_name[0..(max_length - 4 - suffix.length)] + suffix else record[name_col] = prev_name + suffix end end return record.valid? end end