2011-08-21 42 views
2

在我的應用程序,Photo has_and_belong_to_many :land_usesRuby/Rails:創建一個對其子項實例進行操作的類方法?

我在Photo模型這個輔助方法:

def land_use_list 
    land_uses.map(&:name).join(', ') 
end 

這在我看來是一個代碼味道(得墨忒耳),但我一直無法弄清楚如何將其移至LandUse模型。我想要做的是一樣的東西:

class LandUse < ActiveRecord::Base 
    ... 
    def self.list 
    self.map(&:name).join(', ') 
    end 
    ... 
end 

這樣而不是調用photo.land_use_list我可以打電話給photo.land_uses.list

但是,這不起作用,因爲它被稱爲反對類,而不是被稱爲針對屬於特定照片的範圍實例。

有沒有辦法做我在想什麼?而且,更一般地說,您如何在應用程序中處理類似這樣的問題?是否將清單代碼移到LandUse模型的正確方法,還是您會推薦不同的東西?

回答

1

首先,我不認爲這違反了德米特法本身。對於調用屬性上的一個方法創建臨時變量的對象,您有一個方法,然後對該臨時變量執行操作。

如果你完全從不同的課程中完成這將違反德米特法。例如,

class User 
    def names_of_lands_ive_known 
    photos.map(:land_uses).map(:name).join ', ' 
    end 
end 

事實上,它只是很好的信息隱藏。但是,如果你想寫photo.land_uses.names,你可以添加一個擴展到協會去做你想做的事情。

class Photo 
    has_and_belong_to_many :land_uses do 
    def names_as_list_string 
     all.map(:name).join ', ' 
    end 
    end 
end 

有關關聯擴展的更多信息,請查看docs

符合德米特法則的最好方法是做或多或少的你在做什麼,因爲通過在Photo上添加你的方法,這意味着與Photo交互的方法也不需要了解LandUse類,只是該照片有一個方法返回一個土地用途名稱的字符串。

+0

真棒建議,我不知道關聯擴展。也感謝你爲我清理德米特問題。我一直在想,照片只知道他們有土地用途,他們不應該關心土地如何使用自己的格式。但是我看到你的觀點只是與它所具有的內容進行交互。這非常有幫助! – Andrew

0

您可以使用:

class LandUse 
    def self.list_for_photo(id) 
    LandUse.find_by_photo_id(id).join(', ') 
    end 

    def to_s 
    self.name 
    end 
end 

希望它能幫助!

+0

目標是創建一個一致的幫助方法,從LandUse類返回它們的名稱列表,而不是一組土地使用對象。這個建議並不能幫助我做到這一點。我熟悉to_s,它可能會保存一條命令,但是想法是能夠指定land_uses,我想將它們的列表作爲連接字符串而不是實例數組返回。 – Andrew

+0

我編輯所以它更適合您的需求:) – Cydonia7

0

我不是一個Rails應用程序的前面,但我相信

photo.land_uses 

與回報LandUse對象

數組所以你只需要向下移動地圖到陣列,如:

photo.land_uses.map(&:name).join(', ') 

這是你最初的 - 只是在你的其他模型。我想你可能是對的,這意味着Photo知道太多關於LandUse,因此我會將其移出。

+0

好吧,所以我應該將此方法移動到LandUse - 但問題是,如何?我無法在類方法中調用.each,並且調用self方法不允許我訪問從照片調用的作用域實例。你知道如何解決這個問題嗎? – Andrew

+0

我可能將控制器中的實現留在控制器中,並將其移入私有方法中,因此我不必多次輸入'.map(&:name).join(',')'。如果你想要一個更具體的解決方案,那麼也許擴展ActiveRecord,但我不知道從哪裏開始尋找猴子修補你的方法 –

相關問題