Ruby on rails 使用ActiveRecord获取列名称

Ruby on rails 使用ActiveRecord获取列名称,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,有没有办法通过ActiveRecord获得实际的列名称 当我调用find_by_sql或select_all with a join时,如果有同名的列,则会覆盖第一列: select locations.*, s3_images.* from locations left join s3_images on s3_images.imageable_id = locations.id and s3_images.imageable_type = 'Location' limit 1 在上面的示例

有没有办法通过ActiveRecord获得实际的列名称

当我调用find_by_sql或select_all with a join时,如果有同名的列,则会覆盖第一列:

select locations.*, s3_images.* from locations left join s3_images on s3_images.imageable_id = locations.id and s3_images.imageable_type = 'Location' limit 1
在上面的示例中,我得到以下结果:

#<Location id: 22, name: ... 
>
我需要获取上面行的字段名。 这篇文章接近我想要的,但看起来过时了(fetch_字段似乎不再存在)

ActiveRecord连接方法创建多个对象。我正在尝试实现与“includes”返回相同的结果,但使用左连接


我试图返回大量结果(有时是整个表),这就是为什么Include不适合我的需要。

Active Record提供了一个
#column_names
方法,该方法返回一个列名数组


用法示例:
User.column\u name

这正是active record的inspect方法的工作方式:它只列出模型表中的列。但这些属性仍然存在

record.blah
将返回blah属性,即使它来自另一个表。你也可以使用

record.attributes
获取包含所有属性的哈希


但是,如果有多个名称相同的列(例如,两个表都有一个id列),则active record只会将内容合并在一起,而忽略表名。您必须为列名添加别名以使其唯一。

好的,我一直想做一些更高效的事情

请注意,对于非常少的结果,包括工作刚刚好。当您有很多列想要加入时,下面的代码工作得更好

为了使代码更容易理解,我首先制定了一个简单的版本并对其进行了扩展

第一种方法:

# takes a main array of ActiveRecord::Base objects
# converts it into a hash with the key being that object's id method call
# loop through the second array (arr)
# and call lamb (a lambda { |hash, itm| ) for each item in it. Gets called on the main
# hash and each itm in the second array
# i.e: You have Users who have multiple Pets
# You can call merge(User.all, Pet.all, lambda { |hash, pet| hash[pet.owner_id].pets << pet }
def merge(mainarray, arr, lamb)
    hash = {}
    mainarray.each do |i|
      hash[i.id] = i.dup
    end

    arr.each do |i|
      lamb.call(i, hash)
    end

    return hash.values
  end
我这样称呼它:

 lambmerge = lambda do |lhash, rhash, lid, rid| 
                         lhash[lid].keywords << rhash[rid] 
                end
    Location.merge_through!(Location.all, Keyword.all, LocationsKeyword.all, lambmerge)
以下是我如何使用代码:

def merge_multi_test()

    merge_multi!(Location.all,
                 [
                     # each one location has many s3_images (one to many)
                     { :value => S3Image.all,
                       :proc => lambda do |img, hash|
                          if (img.imageable_type == 'Location')
                            hash[img.imageable_id].s3_images << img
                          end
                       end
                     },

                     # each location has many LocationsKeywords. Keywords is the right table and LocationsKeyword is the middletable.
                     # (many to many) 
                     { :value => Keyword.all,
                       :middletable => LocationsKeyword.all,
                       :proc => lambda do |lhash, rhash, lid, rid|
                         lhash[lid].keywords << rhash[rid]
                       end
                     }
                 ])
  end
def merge_multi_test()
合并多个!(全部,
[
#每个位置都有许多s3_图像(一对多)
{:value=>S3Image.all,
:proc=>lambda do | img,散列|
如果(img.imageable_type=='Location')
哈希[img.imageable\u id].s3\u images关键字.all,
:middletable=>LocationsKeyword.all,
:proc=>lambda do | lhash,rhash,lid,rid|
lhash[lid].关键词两个选项

Model.column_names

范例 名为Rabbit的模特在facebook上有“姓名”、“年龄”等栏目

Rabbit.column_names
Rabbit.columns.map(&:name)
返回

["id", "name", "age", "on_facebook", "created_at", "updated_at"] 

您可以使用:model.columns.map(&:name)获取ActiveRecord模型的所有列,但我不确定这是否是您想要的。当我进行联接时,我不知道哪些值属于哪些模型。这就是我想要列的名称的原因。谢谢您的回答。我尝试了别名,但在AR中没有得到任何不同。它始终是相同的混合结果。AR希望有任何特定的别名吗?每个列名称都有eds是唯一的,例如,选择table1.*、table2.id a s t2_id、table2.name as t2_name等。AR对此不会做任何巧妙的处理,但它会停止所有冲突这意味着我必须为每个重复列别名…非常繁琐:-(对于将来来到这里的任何人来说,此方法都是不推荐的,谢谢分享,@pahnin;如果您(或其他任何人)可以推荐其他方法,那就太好了。Column_names()仍然适用于ActiveRecord类,它刚刚被移到了另一个模块中。
ModelName.columns.map(&:name)
截至2015年6月仍能正常工作。
Model.column_names
Model.columns.map(&:name)
Rabbit.column_names
Rabbit.columns.map(&:name)
["id", "name", "age", "on_facebook", "created_at", "updated_at"]