2013-03-25 70 views
1

使用Rails。如何最好地重寫country_photoif-else中的鏈接條件過多

# country.rb 
class Country < ActiveRecord::Base 
    has_many :zones 

    def country_photo 
    if !zones.blank? && !zones.first.shops.blank? && !zones.first.shops.first.photos.blank? 
     zones.first.shops.first.photos.first.url(:picture_preview) 
    end 
    end 
end 

# zones.rb 
class Zone < ActiveRecord::Base 
    belongs_to :country 
    has_many :zone_shops 
    has_many :shops, :through => :zone_shops 
end 

# zone_shop.rb 
class ZoneShop < ActiveRecord::Base 
    belongs_to :zone 
    belongs_to :shop 
end 

# shop.rb 
class Shop < ActiveRecord::Base 

end 
+0

當你有那些有多深的關聯,你不能做任何事情。但避免深層關聯的一種方法是在'country'模型中存儲'photo_id',其中'belongs_to:photo'。還有一種方法可以做到沒有if-else的情況,即zone.try(:first).try(:shops).try(:first).try(:photos).try(:first).try(:url ).try(:picture_preview)' – codeit 2013-03-25 16:27:14

回答

1

請注意,!x.blank?x.present?。無論如何,如果你都OK在if在做幽會(他們是很常見的紅寶石),你可以這樣寫:

def country_photo 
    if (zone = zones.first) && 
    (shop = zone.shops.first) && 
    (photo = shop.photos.first) 
    photo.url(:picture_preview) 
    end 
end 

如果你喜歡花哨的抽象,與Ick你可以寫:

def country_photo 
    zones.first.maybe { |zone| zone.shops.first.photos.first.url(:picture_preview) } 
end 
+0

我得安裝Ick吧?不願意爲此安裝一個新的寶石。 – Victor 2013-03-25 16:35:21

+0

@維克多:增加了一個更正統的方法。在任何情況下請注意,這些都是簡單的抽象,你可以自己寫在你的擴展模塊上('Object#maybe'可以在4/5行中實現)。 – tokland 2013-03-25 16:36:49

1

假設你要顯示在視圖中的圖像,我會做這樣的事情:

# show.html.haml 
- if @country.photo 
    image_tag @country.photo.url(:picture_preview) 

# country.rb 
class Country < ActiveRecord::Base 
    def photo 
    zones.first.photo unless zones.blank? 
    end 
end 

# zone.rb 
class Zone < ActiveRecord::Base 
    def photo 
    shops.first.photo unless shops.blank? 
    end 
end 

# shop.rb 
class Shop < ActiveRecord::Base 
    def photo 
    photos.first unless photos.blank? 
    end 
end