【问题标题】:How does Rails guess the table name from model?Rails 如何从模型中猜测表名?
【发布时间】:2013-09-22 21:23:31
【问题描述】:

我把我的 Rails 数据库弄乱了,当时有点迷茫。 当我意识到我的一个表名不像其他表名那样以 ' 结尾时,一切都开始了。 (我真的不知道为什么,因为我所有的其他表都以's'为前缀) 所以我尝试重命名它并进行了迁移:

rename_table :funnel_data, :funnel_datas

有关信息,对应的模型称为FunnelData

class FunnelData < ActiveRecord::Base
   ...
end

所以迁移似乎完成了它的工作,并且没有错误地运行。

但是现在,在控制台中,我得到了以下信息:

2.0.0-p247 :014 > FunnelData
 => FunnelData(Table doesn't exist)

我检查了我的数据库,并且表 funnel_datas 确实存在!

所以它引出了我的问题:Rails 应该如何知道表的“新”名称?我该如何解决我的情况? 谢谢。


更新:好的,现在我知道“数据”是“数据”的复数形式,我回滚了我的迁移,并试图让我的方式,但现在我得到了一个奇怪的行为.

首先,让我们引入另一个类:

class FunnelStage < ActiveRecord::Base
    has_many :funnel_data
    (...)
end

我的控制台说:

2.0.0-p247 :046 > f = FunnelStage.first
  FunnelStage Load (0.3ms)  SELECT `funnel_stages`.* FROM `funnel_stages` ORDER BY `funnel_stages`.`id` ASC LIMIT 1
 => #<FunnelStage id: 1, name: "Inquiries", order: 100, created_at: "2013-09-14 23:08:55", updated_at: "2013-09-14 23:08:55">
2.0.0-p247 :047 > f.funnel_dat
f.funnel_data        f.funnel_data=       f.funnel_datum_ids   f.funnel_datum_ids=
2.0.0-p247 :047 > f.funnel_data
NameError: uninitialized constant FunnelStage::FunnelDatum
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:125:in `compute_type'
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/reflection.rb:178:in `klass'
        (...)
        from bin/rails:4:in `<main>'
2.0.0-p247 :048 > f.funnel_datum_ids
NameError: uninitialized constant FunnelStage::FunnelDatum
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/inheritance.rb:125:in `compute_type'
        from /usr/local/rvm/gems/ruby-2.0.0-p247@rails4test/gems/activerecord-4.0.0/lib/active_record/reflection.rb:178:in `klass'
        (...)
        from bin/rails:4:in `<main>'

那么现在,Rails 说的是拉丁语? (数据/数据...)

编辑和回答:好的,我自己想通了。 Rails 难以理解该关联,因为它试图将“funnel_data”单数化为一个全新的“funnel_datum”名称(顺便说一句,这将是正确的)

所以我不得不写:

class FunnelStage < ActiveRecord::Base
    has_many :funnel_data, class_name: "FunnelData"
    (...)
end

让它工作。

非常感谢所有帮助我理解这一点的人......

【问题讨论】:

  • 约定优于配置,但要注意 data 已经是复数了.. no s
  • 喂,该死的!那么在 Rails 中编码有语法(我的意思是正字法)规则吗?嗯,这就解释了。可惜不是英语母语的人。非常感谢,这回答了我的问题!
  • 您当然不希望代码库中出现拼写错误,即使您不是英语母语人士 :) 您可以找到有关此的更多信息(称为:​​inflections)here。另请注意,您可以在 config/initializers/inflections.rb 中定义自己的变形。
  • 我更新了我的问题,因为现在,Rails 正在寻找“基准”...
  • datum 是单数,data 是复数。

标签: ruby-on-rails


【解决方案1】:

那是因为“数据”是一个不可数的词,rails 知道:

> "data".pluralize
"data"

所以,你的表应该命名为“funnel_data”。

【讨论】:

    【解决方案2】:

    在rails类名复数是表名,所以漏斗数据复数是漏斗数据所以不需要改变表名。

    【讨论】:

      【解决方案3】:
      "user".pluralize
      => "users"
      

      但是:

      "data".pluralize
      => "data"
      

      如果你想使用funnel_datas 表名:

      class FunnelData < ActiveRecord::Base
        set_table_name "funnel_datas"
      end
      

      【讨论】:

      • 感谢您的提示。但是,如果可能的话,我会尽量适应标准方式
      【解决方案4】:

      要解决您的问题,只需在您的模型定义下方添加:self.table_name = "funnel_datas"


      ActiveRecord 在幕后使用#tableize 方法。来自指南:

      方法tableize#underscore 后跟#pluralize

      根据经验,tableize 返回与简单案例的给定模型相对应的表名。 Active Record 中的实际实现并不是直接表化,因为它还解调了类名并检查了一些可能影响返回字符串的选项。

      Pluralize,默认情况下使用常见的英语变形来获得单词的复数形式,但 "data" 是复数形式。所以:

      > "FunnelData".underscore #=> "funnel_data"
      > "funnel_data".pluralize #=> "funnel_data"
      

      因此,您的模型默认查找 "funnel_data" 表。

      【讨论】:

      • 好的,现在我了解了机制(直到现在这对我来说似乎很神奇)。谢谢:)
      • 我认为鉴于@Orabîg 的后续行动,更好的解决方案是将模型重命名为 FunnelDatum 而不是覆盖表名。
      猜你喜欢
      • 2011-01-01
      • 2012-05-27
      • 2020-12-20
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多