【问题标题】:Adding a method to a Rails ActiveRecord class向 Rails ActiveRecord 类添加方法
【发布时间】:2011-05-28 11:38:42
【问题描述】:

在普通的 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

我可以在 TestClass 实例上调用 foo() 和 bar() 并得到我期望的结果:

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() 会消失,除非我明确让它扩展 my_migration.rb 中的 ActiveRecord。否则,它会删除超类。

如果我这样做,我会在 MyModel.bar() 中的 foo 调用中收到错误。

如果我在 my_migration.rb 中注释掉类(重新)定义,find() 和 bar() 都可以正常工作。

在调试过程中,我添加了puts 语句来查看每个文件和类的执行时间。如果 MyModel 已经定义(我在 my_migration.rb 中这样做),似乎 my_model.rb 甚至不会被加载。

那么:为什么会在 Rails 中发生这种情况,我该如何解决?

【问题讨论】:

  • 你为什么要在迁移中重新打开 MyModel?可以通过重构 bar() 并将其逻辑放入 self.up 方法调用中来实现相同的目标。
  • @mpd:因为现实世界的逻辑是特定于某些类和多态的;它确实值得封装在模型类中。

标签: ruby-on-rails ruby migration


【解决方案1】:

理论 #2:在迁移的顶部

require 'app/models/my_model'

【讨论】:

  • require 'app/models/my_model' 对我不起作用,但是 require_relative '../../app/models/my_model' 对我有用——谢谢!
  • require Rails.root.join("app/models/my_mode") 看起来更干净了。
【解决方案2】:

您需要首先为您的模型引用一个常量,这将加载您的模型类。然后你可以改变那个类。以下是做同样事情的 3 种方法:

我的模型 类 MyModel 定义栏 foo.each{ |f| f.baz } 结尾 结尾 MyModel.module_eval 做 定义栏 foo.each{ |f| f.baz } 结尾 结尾 MyModel.send :include, Module.new { 定义栏 foo.each{ |f| f.baz } 结尾 }

【讨论】:

    【解决方案3】:

    在你的例子中,我认为你错过了

    < ActiveRecord::Base
    

    根据您的第一个定义。

    在您的迁移猴子补丁中,您还需要一个匹配的

    < ActiveRecord::Base
    

    两个类定义必须匹配

    【讨论】:

    • 有一次,我确实将该代码添加到我的猴子补丁中。那时我发现来自 my_model.rb 的 foo 关联也没有被创建......因为 my_model.rb 根本没有被加载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 2017-01-19
    相关资源
    最近更新 更多