bish
bish

Reputation: 3419

Ruby: Trying to "Update_all" but getting "NameError: uninitialized constant"

this is the first time I try to write a ruby migration script (I want to update the value of a col for a specific row).

I have a table called "events" with cols "e_id" and "e_text_en". I want to update the "e_text_en" value of the row with ID 6. In SQL it would be

update events set e_text_en = 'blabla' where e_id = 6;

My ruby approach: (20141013130000_update_broken_event_texts.rb)

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def Events.up
    Events.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

But this gives me the error ´NameError: uninitialized constant´

rake aborted!
NameError: uninitialized constant UpdateBrokenTextsEventInEvent::Events
/var/.../20141013130000_update_broken_event_texts.rb:2:in `<class:UpdateBrokenTextsEventInEvent>'
/var/.../20141013130000_update_broken_event_texts.rb:1:in `<top (required)>'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:718:in `load_migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:714:in `migration'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:708:in `disable_ddl_transaction'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:1012:in `use_transaction?'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:922:in `rescue in block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:919:in `block in migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `each'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:916:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:764:in `up'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/migration.rb:742:in `migrate'
/var/lib/gems/1.9.1/gems/activerecord-4.0.1/lib/active_record/railties/databases.rake:42:in `block (2 levels) in <top (required)>'
Tasks: TOP => db:migrate

While I searched for a solution I found some advises that tables are called in singular, but even when I try Event instead of Events I get the same error.

Can anyone help me to correct my ruby?

Versions used:

$ rails -v
Rails 4.0.1
$ gem -v
1.8.23.2
$ ruby -v
ruby 1.9.3p545 (2014-02-24) [i686-linux] Brightbox

edit: Addional infos Our Schema is created via sql-File. We started to use migrations a short time ago and this is the first update-one. The first two migrations where table-changes. We don't have any ´app/model´ files yet, becuase the other migrations worked without any, e.g.:

class AddDeliveriesToEmailQueue < ActiveRecord::Migration
  def change
    add_column :email_queue, :deliveries, :int, :null => false, :default => 0, :after => :error
  end
end

Upvotes: 0

Views: 569

Answers (3)

Frederick Cheung
Frederick Cheung

Reputation: 84124

Firstly your migration class name must match the file name (rails will load the migration file and then assume it created a class of the corresponding name). Assuming you don't change your file name, it means that you need to have

class UpdateBrokenEventTexts < ActiveRecord::Migration
  ...
end

Since you say that you have no model classes, you'll have to use raw SQL, for example

class UpdateBrokenEventTexts < ActiveRecord::Migration
  def change
    execute "UPDATE events SET e_text_en = 'blablabla'"
  end
end

This is pretty much the same as using ActiveRecord::Base.connection.execute but saves a little on the typing and makes sure Rails understands you're making an irreversible change.

Upvotes: 3

Gacha
Gacha

Reputation: 1037

This is a common problem when you create migration and then deside to rename it. Class name in migration should be the same as the filename. You have migration with class UpdateBrokenTextsEventInEvent and filename 20141013130000_update_broken_event_texts.rb, but the class name should be UpdateBrokenEventTexts.

Upvotes: 2

Surya
Surya

Reputation: 16002

Create Event model:

$ rails g model Event

Assuming that you have a model class Event(inside app/models/event.rb) now, then change these lines:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def Events.up
    Events.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

to:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def self.up
    Event.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

Also, I'd recommend you to move such operations in a rake tasks instead of moving them in a migration file:

namespace :events do
  desc "Update e_text_en field with blablabla"
  task :update_e_text_en => :environment do
    Event.where('e_id', 6).update_all(e_text_en: "blablabla")
  end
end

and then from your terminal:

$ rake events:update_e_text_en

UPDATE: Don't plan to have a model class for now? No worries, you can still update the column but with a SQL query:

class UpdateBrokenTextsEventInEvent < ActiveRecord::Migration
  def self.up
    ActiveRecord::Base.connection.execute("UPDATE events SET e_text_en = 'blablabla'")
  end
end

Please note that these actions are irreversible(since you don't know what was the previous data in the column you're updating) and that's why they shouldn't be in a migration file. You probably be better with a rake task or something for such operations.

Upvotes: 1

Related Questions