活动记录在别名primary_key时返回空值"id"



我想要别名DB字段,但将primary_key别名为"id"将使其值空白:

class XXX < ActiveRecord::Base
  self.table_name = 'XXX'
  self.primary_key = 'xxx_id'
  def self.get()
    self.select(
        primary_key + ' AS id',
        'xxx_itmno AS product_number',
        'xxx_qty AS qty'
    )
  end
输出:

[{
  id: null,
  product_number: 123,
  qty: 2
}]

问题1。解决这个问题最简单的方法是什么?

问题2。为什么会发生这种情况?


PS # 1:

如果我别名为其他东西,这个问题就会消失。

primary_key + 'AS id_',输出:

[{
  id_: 42,
  product_number: 123,
  qty: 2
}]


PS # 2:

我发现包括PK也可以工作:

self.select(
    primary_key,
    primary_key + ' AS id', ...
输出:

[{
  xxx_id: 42,
  id: 42,
  product_number: 123,
  qty: 2
}]

但是,我必须对删除PK进行后处理。

为什么会发生这种情况?

当ActiveRecord:: attributemmethods::Read读取属性值时,id是一个特例:

def read_attribute(attr_name, &block)
  ...
  name = self.class.primary_key if name == "id".freeze
  _read_attribute(name, &block)
end

当您调用id方法时,ActiveRecord将获得主键xxx_id的值,该值仅在select语句中包含xxx_id时可用。

解决这个问题最简单的方法是什么?

尝试覆盖ActiveRecord id逻辑可能是危险的,因为Rails代码和其他gem很可能依赖于它以这种方式工作。

如果你只是需要返回值,而不一定需要使用ActiveRecord对象,你可以将select语句包装在select_all:

class XXX < ActiveRecord::Base
  ...
  def self.get
    select(
      primary_key + ' AS id',
      'xxx_itmno AS product_number',
      'xxx_qty AS qty'
    )
  end
  def self.get_values
    connection.select_all(get)
  end

这将返回:

[{
  "id" => 42,
  "product_number" => 123,
  "qty" => 2
}]

如果你需要它们是ActiveRecord对象,你可能需要加载没有别名的列,然后使用map之类的东西把它们变成你想要的格式。

最新更新