【问题标题】:How ActiveRecord finds the attributes of a model?ActiveRecord 如何找到模型的属性?
【发布时间】:2013-12-20 10:31:51
【问题描述】:

这是我的问题。

我想知道active record如何访问数据库中的表和列?

【问题讨论】:

标签: ruby-on-rails ruby ruby-on-rails-3


【解决方案1】:

大部分回答您问题的代码都包含在model_schema.rb 文件中。

table_name 是与您的模型对应的数据库表的名称。如文档中所述,除非明确设置,否则它是根据模型名称猜测的。

根据类名猜测表名(强制小写) 继承层次结构直接从 ActiveRecord::Base 下降。所以如果层次结构 看起来像:Reply < Message < ActiveRecord::Base,然后使用 Message 即使在回复时也猜测表名。用于猜测的规则 由 Active Support 中的 Inflector 类处理,它知道几乎所有常见的 英语屈折变化。您可以在config/initializers/inflections.rb 中添加新的变形。

嵌套类的表名以单数形式为前缀 父表名。不考虑封闭模块。 您还可以明确设置自己的表名:

class Mouse < ActiveRecord::Base
  self.table_name = "mice"
end

或者,您可以覆盖 table_name 方法来定义您的 自己的计算。 (可能使用 super 来操作默认值 表名。)示例:

class Post < ActiveRecord::Base
  def self.table_name
    "special_" + super
  end
end

对于列,它有点复杂。您可以从columns 方法开始,该方法从schema.rb 文件中获取列定义并返回它们。

列在应用程序内的schema.rb 文件中明确定义。

【讨论】:

  • 这是对一个可怕问题的绝妙答案
  • 很好的超级答案.. 非常感谢
  • 它不是从 schema.rb 文件中提取的(我有带有自定义 db 列的项目,只是转储 sql)。通常它通过数据库调用使用表的自省(例如,请参阅 activerecord/lib/active_record/connection_adapter/postgresql_adapter.rb 和 def column_definitions 了解 postgresql 是如何做到的。
  • 据我所知,自省仅用于生成 schema.rb(通常在迁移时)。生成后,将使用 schema.rb。实际上,运行应用程序需要schema.rb。如果它只使用自省,则不需要schema.rb
  • 我没有 schema.rb(有 structure.sql,因为 schema 转储程序不喜欢自定义字段,它现在不怎么处理),我的应用程序都可以工作很好 :) 见stackoverflow.com/questions/9884429/…
【解决方案2】:

它由 ORM 层完成,它遵循 rails 约定来映射表和那里的字段,直到您手动配置模型以映射数据库中的表

看看http://guides.rubyonrails.org/active_record_basics.html

【讨论】:

  • 嗨..你能告诉我代码具体写在哪里吗?
  • @poojaagarwal here,我想。
  • 感谢@Mischa 的链接。
【解决方案3】:

ActiveRecord 提供了一个 Base 类,当它被子类化时,会在所述类和现有 DB 表之间建立一个映射。

每个 finder 方法都允许您将参数传递给它,以便在您的数据库上执行某些查询,而无需编写原始 SQL。

如果您想了解更多关于内部工作原理的信息,可以从这里开始: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb

【讨论】:

    【解决方案4】:

    以mysql为例,它有一个db调用information_schema,还有表名tables,columns等等。 Mysql 使用这些表将每个表的信息及其列定义存储在其他 mysql 的数据库中。

    其他 db provicer 可能有类似的东西。

    【讨论】:

      【解决方案5】:

      它使用内省。如果您查看调试日志,第一次访问模型时,您应该会看到一个查询表定义、列等的查询。我最熟悉 postgres,所以我会链接到它,但所有 connection adapters这样做是数据库特定的方式。

      查看您的数据库的activerecord / lib / active_record / connection_adapters 以及column_definitions 函数,它为postgres 生成运行时自省,如下所示。

      (来自https://github.com/rails/rails/blob/60fa355790bd6888ab8758bd4989431256d8ba8e/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

      def column_definitions(table_name) #:nodoc:
                exec_query(<<-end_sql, 'SCHEMA').rows
                    SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                           pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
                      FROM pg_attribute a LEFT JOIN pg_attrdef d
                        ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                     WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
                       AND a.attnum > 0 AND NOT a.attisdropped
                     ORDER BY a.attnum
                end_sql
              end
      

      然后缓存此信息并用于生成动态方法。

      阅读 rails 源代码,虽然它可能非常令人困惑,但很有趣,您可以看到一些 magic 是如何工作的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-11
        • 1970-01-01
        • 2011-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多