ActiveRecord如何查找模型的属性?

时间:2013-12-20 10:31:51

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

这是我的问题。

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

5 个答案:

答案 0 :(得分:3)

回答您问题的大部分代码都包含在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文件中明确定义。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

每个finder方法都允许您将参数传递给它,以便在不编写原始SQL的情况下对数据库执行某些查询。

如果您正在寻找有关内部运作的更多信息,这里是一个很好的起点: https://github.com/rails/rails/blob/master/activerecord/lib/active_record/base.rb

答案 3 :(得分:0)

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

其他数据库提供者可能有类似的东西。

答案 4 :(得分:0)

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

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

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

column_definitions

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

阅读rails源,虽然它非常混乱,但很有趣,你可以看到一些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 是如何工作的。