如何在具有名为“属性”的列的数据库上使用 ActiveRecord? (危险属性错误)

Posted

技术标签:

【中文标题】如何在具有名为“属性”的列的数据库上使用 ActiveRecord? (危险属性错误)【英文标题】:How can I use ActiveRecord on a database that has a column named 'attribute'? (DangerousAttributeError) 【发布时间】:2011-03-25 05:48:16 【问题描述】:

我正在访问一个我无法更改的数据库,它定义了一个名为attribute 的列。每当我尝试访问 attribute 时,都会收到此异常:

属性?由 ActiveRecord(ActiveRecord::DangerousAttributeError) 定义

我的代码:

class User < ActiveRecord::Base
      def self.authenticate(username,password)
        where(:username => username, :value => password).first
      end
end

我在 ruby​​ on rails 邮件列表中找到了解决问题的计划,但对我不起作用

  class << self
    def instance_method_already_implemented?(method_name)
      return true if method_name == 'attribute'
      super
    end
  end

我不确定这是否重要,但这里是我的环境的详细信息:

ruby 1.9.2p0(2010-08-18 修订 29036)[x86_64-darwin10.4.0] 导轨 3.0.1 activerecord (3.0.1) activeresource (3.0.1)

更新(已解决):

A计划:

select("username, value").where(:username => username, :value => password).first

【问题讨论】:

attribute?attribute的例外吗?注意问号在哪里。 关于attribute?的异常。名为attribute的列 【参考方案1】:

ActiveRecord 查询支​​持:select 参数,它允许您将希望返回给您​​的字段定义为字符串。

通常人们使用类似的东西:

:select => 'field1, field2'

如果您知道数据库服务器的原始查询语言,那么您可以在选择字符串中使用它。使用 SQL 选择字段时的选项之一是使用 as 修饰符:

select field1 as the_first_field, field2 as the_second_field

并且数据库将使用新字段名称而不是旧字段名称返回字段。如果您的数据库支持,这是一种管理以与 Rails 冲突的方式命名的遗留字段的简单方法。

请参阅 Ruby on Rails 指南中“Five ActiveRecord Tips”和“Selecting Specific Fields”中的“学习爱 ActiveRecord 的 :select 参数”。

这是我的一个 Rails 应用程序使用 rails console 访问我的 Postgres 数据库的示例:

ruby-1.9.2-p180 :007 > dn = DomainName.first
 => #<DomainName id: 1, domain_name: "ip72-208-155-230.ph.ph.cox.net", created_at: "2010-04-20 05:53:22", updated_at: "2010-04-20 05:53:22"> 
ruby-1.9.2-p180 :008 > dn = DomainName.first(:select => 'id, domain_name as dn')
 => #<DomainName id: 1> 
ruby-1.9.2-p180 :009 > dn['id']
 => 1 
ruby-1.9.2-p180 :010 > dn['dn']
 => "ip72-208-155-230.ph.ph.cox.net"

【讨论】:

谢谢。我知道这个计划,我以前使用原始查询语言。但有时不安全。 这不是使用原始 SQL,而是使用 select 语句,它只是查询的一部分。如果您没有正确处理参数,where 子句可能是不安全的。 但是 ActiveRecord 仍然会尝试为attribute 列创建所有方法。 如果在as 修饰符中将其重命名为其他内容,它将不会在来自数据库的响应中看到属性列。我已经多次使用这种策略来处理字段名称与保留字和方法发生冲突的遗留表。【参考方案2】:

对于列x,ActiveRecord 创建xx=x? 方法。因此,将您的修复更新为:

class << self
    def instance_method_already_implemented?(method_name)
        return true if method_name == 'attribute?'
        super
    end
end

【讨论】:

更改并收到错误attribute_before_type_cast is defined by ActiveRecord 如果将return true if method_name == 'attribute_before_type_cast' 添加到instance_method_already_implemented? 的列表中会怎样? 请看我的更新,解决了但很多return true if method_name ==【参考方案3】:

也许您可以使用 alias_attribute,从而使用不同名称的方法。

【讨论】:

以上是关于如何在具有名为“属性”的列的数据库上使用 ActiveRecord? (危险属性错误)的主要内容,如果未能解决你的问题,请参考以下文章

如何在pyspark中连接具有相同名称的列的值

ms 访问,需要获取具有不同列的所有行

Cassandra/Datastax:如何在 java 中获取具有列表数据类型的列的值

如何过滤具有列表的列的数据框包含值[重复]

如何获取数据集中具有空值的列的总数? [复制]

如何将 Avro 文件加载到具有“时间戳”类型的列的 BigQuery 表中