2011-08-21 4 views
2

내 응용 프로그램에서 Photo has_and_belong_to_many :land_usesRuby/Rails : 자식 인스턴스에서 작동하는 클래스 메서드를 만듭니다.

Photo 모델에서이 도우미 메서드가 있습니다 :

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

이것은 코드 냄새 (demeter)로 나를 때렸지만, 방법을 알아낼 수 없었습니다. LandUse 모델로 이동하십시오. 내가 뭘하고 싶은 건 :

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

그래서 대신 photo.land_use_list 전화를 photo.land_uses.list 호출 할 수 있습니다.

그러나 특정 사진에 속하는 범위가 지정된 인스턴스에 대해 호출되는 대신 클래스에 대해 호출되기 때문에 작동하지 않습니다.

내가 생각하는 것을 할 수있는 방법이 있습니까? 더 일반적으로 앱에서 이와 같은 문제에 어떻게 접근합니까? LandUse 모델의 목록 코드를 올바른 방법으로 옮기고 있습니까? 아니면 다른 것을 추천 하시겠습니까?

답변

1

첫째, 나는 Demeter Law 그 자체를 위반하지 않는다고 생각합니다. 속성에 대해 하나의 메소드를 호출하여 임시 변수를 만든 다음 임시 변수에 대해 작업하는 메소드가 있습니다.

다른 계급에서이 작업을 완전히 수행하는 경우 Demeter의 법칙을 위반하는 것입니다. 예 :

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과 상호 작용하는 방법이클래스에 대해 알고 있다면, 그 사진에는 토지 용도의 문자열을 반환하는 메소드 만 있습니다.

+0

굉장한 제안, 나는 협회 확장에 대해 전혀 몰랐다. Demeter 문제를 해결해 주셔서 감사합니다. 나는 라인을 따라 생각하고 있었다. 사진은 단지 토지 이용을 알고 있으며, 토지가 어떻게 포맷을 사용하는지에 관해서는 안된다. 그러나 나는 그것이 가지고있는 콘텐츠와의 상호 작용에 관한 귀하의 요지를 보았습니다. 이것은 매우 도움이되었다! – 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

나는 레일 애플 리케이션의 앞에 아닙니다 그러나 나는 LandUse 객체

복귀와
photo.land_uses 

배열 그래서 그냥 같은 그 배열에 아래로지도를 이동해야 믿습니다

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

원래 다른 모델에 있던 모델입니다. 나는 당신이 맞을지도 모른다고 생각합니다. 따라서 PhotoLandUse에 대해 너무 많이 알고 있습니다. 따라서 그것을 옮길 것입니다.

+0

좋아요, 그래서이 방법을 LandUse로 옮겨야합니다 -하지만 문제는 무엇입니까? .each를 클래스 메서드 내에서 호출 할 수는 없으며 self 메서드를 호출하면 사진에서 호출되는 범위 인스턴스에 대한 액세스가 허용되지 않습니다. 그 문제를 해결하는 방법을 알고 있습니까? – Andrew

+0

아마도 구현체를 컨트롤러에두고 private 메소드로 옮겨서'.map (& : name) .join (',')'을 여러 번 입력 할 필요가 없을 것입니다. 좀 더 구체적인 솔루션을 원한다면 ActiveRecord를 확장하고 싶지만 원숭이가 당신의 방법을 패치 할 곳을 찾기 시작해야할지 모르겠다. –

관련 문제