Добавление метода в класс Rails ActiveRecord - PullRequest
3 голосов
/ 20 декабря 2010

В обычном Ruby это работает просто отлично:

class TestSuper
  def foo
    puts "In TestSuper.foo"
  end
end

class TestClass < TestSuper
  def foo
    super
    puts "In TestClass.bar"
  end
end

class TestClass
  def bar
    puts "In TestClass.bar, second definition"
    puts "Calling foo:"
    foo
  end
end

t = TestClass.new
t.foo
t.bar

Я могу вызвать foo () и bar () для экземпляра TestClass и получить именно то, что ожидаю:

In TestSuper.foo
In TestClass.bar
In TestClass.bar, second definition
Calling foo:
In TestSuper.foo
In TestClass.bar

Однако, когда я пытаюсь что-то очень похожее в миграции на Rails, я получаю ошибки:

#### my_model.rb ####
puts "In my_model.rb"
class MyModel
  has_many :foo
end

#### my_migration.rb ####
puts "In my_migration.rb"
class MyModel
  def bar
    foo.each{ |f| f.baz }
  end
end

class MyMigration < ActiveRecord::Migration
  def self.up
    MyModel.find(1).bar        
  end

  def self.down
    # Not applicable
  end
end

Первая проблема заключается в том, что MyModel.find () исчезает, если у меня нет явного расширения ActiveRecord в my_migration.rb. В противном случае он отбрасывает суперкласс.

Если я это сделаю, я получу ошибку при вызове foo в MyModel.bar ().

Если я закомментирую определение класса (re) в my_migration.rb, find () и bar () оба будут работать нормально.

Во время отладки я добавил операторы puts, чтобы увидеть, когда выполняются каждый файл и класс. Похоже, что my_model.rb даже не загружается, если MyModel уже определен (что я делаю в my_migration.rb).

Итак: почему это происходит в Rails, и как я могу обойти это?

Ответы [ 3 ]

4 голосов
/ 21 декабря 2010

теория # 2: на вершине вашей миграции

require 'app/models/my_model'
2 голосов
/ 21 декабря 2010

Сначала необходимо указать константу для вашей модели, которая загрузит класс вашей модели.Тогда вы можете изменить этот класс.Ниже приведены 3 способа сделать то же самое:

MyModel
class MyModel
  def bar
    foo.each{ |f| f.baz }
  end
end
MyModel.module_eval do
  def bar
    foo.each{ |f| f.baz }
  end
end
MyModel.send :include, Module.new {
  def bar
    foo.each{ |f| f.baz }
  end
}
1 голос
/ 20 декабря 2010

в вашем примере я думаю, что вы пропали без вести

< ActiveRecord::Base

из вашего первого определения.

в вашем патче миграции обезьяны вам также нужен соответствующий

< ActiveRecord::Base

два определения классов должны совпадать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...