2012-11-13 92 views
9

假設我正在抽象代碼,並且循環訪問對象x的列名,檢測列是否爲關聯的最佳方法是什麼?Rails/ActiveRecord:檢測列是否爲關聯

我知道我能做到這一點,但我想知道是否有更好的辦法:

@user = User.first 
    @user.attributes.keys.each do |column| 
    if column[-3..-1] == "_id" && @user.respond_to?(column[0..-4].to_sym) 
     puts "#{column} is an association/relation." 
    else 
     puts "#{column} is not an assocation/relation." 
    end 
    end 
end 

任何內置的Rails的方法或助手來檢測協會?上面的代碼既不漂亮也不傻。謝謝!要做到這一點

回答

15

一種方法是在該類的所有協會反映:

associations = class_goes_here.reflect_on_all_associations 

然後找到剛纔belongs_to的,因爲這些將有_id領域:

associations = associations.select { |a| a.macro == :belongs_to } 

然後你可以通過這樣做找到這些關聯中使用的外鍵:

association_foreign_keys = associations.map(&:foreign_key) 

我不會使用@user.attributes來獲取屬性,然後使用keys來獲取列名。我會用User.column_names來獲取列名。

因此,所有的解釋,你就可以改變你的代碼是這使它更加萬無一失:

associations = User.reflect_on_all_associations 
associations = associations.select { |a| a.macro == :belongs_to } 
association_foreign_keys = associations.map(&:foreign_key) 
User.column_names.each do |column| 
    if association_foreign_keys.include?(column) 
    puts "#{column} is an association/relation." 
    else 
    puts "#{column} is not an assocation/relation." 
    end 
end 
+0

鐵軌1.1.1,你可以立即過濾宏:'協會= User.reflect_on_all_associations(:belongs_to的) '並保存第二行代碼。 – ToniTornado

1

我肯定選擇的解決方案是更好的,但是如果你住在「理想世界」,在那裏每個人都遵循Rails約定,我想你可以依靠this

2.2架構約定的Active Record使用命名慣例在數據庫表中的列 根據這些專欄的目的。

外鍵 - 應根據模式 singularized_table_name_id(例如item_id,order_id)命名這些字段。這些是Active Record在您的模型之間創建關聯 時將查找的 字段。

因此,只要尋找_id後綴在列名的末尾:

Model.column_names.select{|cn| cn.include?("_id")} 
+0

我個人認爲這是一種容易出錯的方法,因爲人們(不幸地)違反了這些約定規則。 –

+0

這就是我提到約定的原因。 –