1

I am using Rails 3.1.1 and Ruby 1.9.2. I am moving a database from a Ruby 1.8.7 environment to a Ruby 1.9 environment and would like to execute the following migration:

# coding: utf-8
class CleanseVerses < ActiveRecord::Migration
  def up
    Poem.all.each do |vs|

      cleansed_text = String.new
      cleansed_text = vs.text

      cleansed_text.gsub!('—',  '—')
      cleansed_text.gsub!(' - ',  ' — ')
      cleansed_text.gsub!('’',  '’')
      cleansed_text.gsub!('“',  '“')
      cleansed_text.gsub!('â€', '”')
      cleansed_text.gsub!('prince', 'king')

      vs.text = cleansed_text

      vs.save

    end
  end

  def down
  end
end

The problem is that the database doesn't seem to reflect any of the changes. Even the simple 'prince' to 'king' conversion isn't working.

I do have attr_accessible on the Poem.text field.

Am I missing something fundamental on strings?

UPDATE:

It seems that I am missing something fundamental on the nature of strings.

When I change the following two lines:

cleansed_text = String.new
cleansed_text = vs.text

to

cleansed_text = String.new(vs.text)

then everything works perfectly.

Andy
  • 1,801
  • 3
  • 22
  • 33
  • 2
    My guess is that the records are failing to save for some reason. Try changing `vs.save` to `vs.save!` so an exception will be raised if the record isn't saved. – Emily Nov 18 '11 at 21:43
  • I have tried it with save! and it wasn't raising any exceptions. – Andy Nov 18 '11 at 21:50
  • re: Update. A surprising result. I'd love to hear from someone more knowledgeable why that would occur. You're sure nothing else changed? The `String.new` shouldn't be necessary at all. If `vs.text` isn't already a string (or you're not sure), doing an explicit cast by calling `vs.text.to_s` is probably a better approach. – Alec Wenzowski Nov 19 '11 at 03:05
  • I'm fairly sure nothing else changed. It seems very mysterious to me too but I feel as though I've bumped into this exact issue in the past. – Andy Nov 22 '11 at 22:24

1 Answers1

1

Consider

# coding: utf-8
vs = '—  - ’ “ †prince'
vs.gsub!('—', '—')
  .gsub!(' - ',  ' — ')
  .gsub!('’',  '’')
  .gsub!('“',  '“')
  .gsub!('â€', '”')
  .gsub!('prince', 'king')
puts vs

which prints — — ’ “ ” king

The bang on the end of gsub! indicates that it operates in place. Note that #gsub! is not the same as #gsub which does not modify in place.

You can perform this operation directly on vs.text since it's already a string and skip the whole cleansed_text thing entirely.

All that said, the only two reasons I can think of that your example isn't working are

  1. Your changes are not being persisted because they are failing to save, and
  2. Your Poem class doesn't have a method text that represents a column text in your poems table via ActiveRecord.

While I understand that your changes are not currently being persisted, it is generally considered to be a good idea to make your migrations reversible in the down method when at all possible.

If you or anyone on your team uses a Windows text editor, make sure your migration doesn't have a byte order mark in it, just in case.


Since you mention 1.8, do read about how things have changed in 1.9.

And since this looks like an encoding conversion, if you know the old encoding why don't you use String#encode?

Community
  • 1
  • 1
Alec Wenzowski
  • 3,878
  • 3
  • 25
  • 40
  • I updated my question but it appears that the way I was initially doing it was not actually changing the text in the 'text' column. – Andy Nov 18 '11 at 23:25