This code is perfect if you have 2 text objects in your Rails application and you want to compare their differences in one of your HTML views. It’s 99% pure Ruby too, so if you alter the first line, you can use it for other purposes.

Only one thing to note: you must have diff installed. I’m using: diff (GNU diffutils) 2.8.1.

#set up some variables to reference later
temporary_directory = File.join(Rails.root, "tmp")
max_lines = 9999999 #needs to be larger than the most lines you'll consider
diff_header_length = 3

# text_old and text_new should be the values of the string objects to compare
# these are just example strings to show it works
text_old      = "line1\\ndeleted line2\\nline3\\n\\nline4\\nline5"
text_new      = "line1\\ninserted line2\\nline3\\n\\nline4\\nline5"

# since we're using diff on the file system, we'll save the text we want to compare
# and then run diff against the two files
file_old_name = File.join(temporary_directory,"file_old"+rand(1000000).to_s)
file_new_name = File.join(temporary_directory,"file_new"+rand(1000000).to_s)
file_old      = File.new(file_old_name, "w+")
file_new      = File.new(file_new_name, "w+")
file_old.write(text_old+"\\n")
file_new.write(text_new+"\\n")
file_old.close
file_new.close

# diff will give provide a string showing insertions and deletions.  We will
# split this string out by newlines if there are difference, and mark it up
# accordingly with html
lines = %x(diff -­-­­­­­­unified=#{max_lines} #{file_old_name} #{file_new_name})
if lines.empty?
  lines = text_new.split(/\\n/)
else
  lines = lines.split(/\\n/)[diff_header_length..max_lines].
  collect do |i|
    if i.empty?
      ""
    else
      case i[0,1]
      when "+"; then "<ins>"+i[1..i.length-1]+"</ins>"
      when "-"; then "<del>"+i[1..i.length-1]+"</del>"
      else; i[1..i.length-1]
      end
    end
  end
end

#clean up the temporary diff files we created
File.delete(file_new_name)
File.delete(file_old_name)

#return marked up text
lines.join("\\n")

If you fire up RAILS_ROOT/script/console and paste that code in, it will return a nicely marked up string like this:

<del>deleted line2</del>
<ins>inserted line2</ins>
line3

line4
line5

Use CSS to make your ins and del tags render however you like.