2009-05-21 2 views
2

비즈니스 로직은 다음과 같습니다. 사용자는 조인 테이블을 통해 보트에 있으며,이 모델을 티켓이라고 부릅니다. 그러나 사용자 인스턴스가 보트에있는 다른 사용자를 확인하려고 할 때 해당 사용자에게 보트의 모든 사용자 또는 보트의 특정 사용자를 볼 수 있는지 묻는 조건이 있습니다. 사용자가 모든 사람을 볼 수 있다면 정상적인 거래가 가능합니다. some_user.boats.first.users은 해당 보트 티켓을 가진 모든 사용자를 반환합니다. 그러나 일부 사용자의 경우 보트에있는 유일한 사람들 (사람들이 염려하는 한)은 사람들입니다. 식당을 예로 들어 봅시다. 따라서 사용자의 티켓이 acts_as_taggable 스타일 시스템을 사용하여 '다이닝 룸'으로 '태그 지정'된 경우 some_user.boats.first.users에서 반환 된 유일한 사용자는 '다이닝 룸'이라는 티켓이있는 사용자 여야합니다.싱글 톤 클래스를 사용하여 ActiveRecord 연결을 동적으로 덮어 쓰기/추가하기

레코드 용으로, 나는 getgo에서 정신 나간 것을 디자인하려고하지 않습니다.이 임의 그룹화를 (주로) 존재하는 시스템에 넣으려고합니다. 생성 할 때, SQL을 생성까지 모든 방법을 얻을 수

singleton = class << a_user_instance ; self ; end 
singleton.class_eval(<<-code 
    has_many :tickets, :include => :tags, :conditions => ['tags.id in (?)', [#{tag_ids.to_s(:db)}]] 
code 
) 

:하지만,

class User 
    has_many :tickets 
    has_many :boats, :through => :tickets 
end 

class Ticket 
    belongs_to :user 
    belongs_to :boat 
end 

class Boat 
    has_many :tickets 
    has_many :users, :through => :tickets 
end 

처음에는 내가 조건부 같은 가상 클래스를 수정할 수 있다고 생각 : 는 그래서 우리는있어 그것은 SQL이 끝나는 생성

LEFT OUTER JOIN "tags" ON ("tags"."id" = "taggings"."tag_id") WHERE ("tickets"._id = 1069416589 AND (tags.id in (5001,4502)))

나는 액티브 코드 주위에 파고 시도했지만, 난 아무데도 찾을 w이 없습니다 위의 SQL에서 밑줄로 'id'접두어를 붙입니다. ActiveRecord 클래스가로드 될 때 연관이로드된다는 것을 알고 있으며, 싱글 톤 클래스와 동일한 것으로 가정합니다. shrug.

는 또한 같은 alias_method_chain 사용 :

singleton = class << a_user_instance ; self ; end 
singleton.class_eval(<<-code 
    def tickets_with_tag_filtering 
    tags = Tag.find(etc, etc) 
    tickets_without_tag_filtering.scoped(:include => :tags, :conditions => {:'tags.id' => tags}) 
    end 
    alias_method_chain :tickets, :tag_filtering 
code 
) 

를하지만 그 방법은 원하는 티켓을 생산하면서 그 티켓은 클래스가 아닌 가상 클래스의 조건을 사용에 어떤 조인. some_user.boats.first.users은 모든 사용자를 반환합니다.

특히이 방법으로 잘못된 트리를 짖고 있다면 모든 유형의 주석이 인정 될 것입니다. 감사!

답변

2

그래서 밑줄 문제에 대한 야생적인 추측은 Rails가 평가시 컨텍스트를 기반으로 한 배치 코드를 생성한다는 것입니다. 과 같이, 싱글 톤 클래스에 엉망이 최대 수 인 : 당신은 에 거기에 도착하여 싱글 톤 클래스에 클래스 이름 속성을 정의하고 그 문제가 해결되는지 볼 수

"#{owner.table_name}.#{association.class.name}_id = #{association.id}" 

.

전체적으로 나는 이것을 권장하지 않습니다. 그것은 추적하기에 고뇌하고 효과적으로 확장하기 불가능한 행동을 만듭니다. 코드베이스에 지뢰를 만들어 당신이나 나중에 사랑하는 사람을 해칠 것입니다.

대신, named_scope 선언을 사용하는 것이 좋습니다 : 다시 가서 몇 가지 코드를 편집 할 수 있지만,이 방법이 훨씬 더 유연

class User 
    has_many :taggings, :through => :tickets 

    named_scope :visible_to, lambda { |looking_user| 
     { :include => [ :tickets, :taggings ], 
     :conditions => [ "tickets.boat_id in (?) and taggings.ticket_id = tickets.id and taggings.tag_id in (?)", looking_user.boat_ids, looking_user.tag_ids ] 
     } 
    } 
end 

가 사용할 수 있습니다

Boat.last.users.visible_to(current_user) 

찾기가 제한되고 그 제한의 목적이 무엇인지 분명합니다. 조건은 런타임에 동적으로 계산되므로 클라이언트가 당신을 때리는 다음 이상한 수정을 처리 할 수 ​​있습니다.

class User 
    named_scope :visible_to, lambda { |looking_user| 
     if looking_user.superhuman? 
     {} 
     else 
     { :include => [ :tickets, :taggings ], 
      :conditions => [ "tickets.boat_id in (?) and taggings.ticket_id = tickets.id and taggings.tag_id in (?)", looking_user.boat_ids, looking_user.tag_ids ] 
     } 
     end 
    } 
end 

빈 해시를 반환하면 효과적으로 범위의 효과를 무효로 할 수 있습니다 사용자들 중 일부는 엑스레이 비전과 투시력이 있다고.

+0

당신은 절대적으로 옳습니다. 저는 이것에 대해 매우 비슷한 것을 구현하고, 기존 코드를 편집하며, 가슴 전체를 무한한 힘으로 피하지 않을 것입니다. 또한 싱글 톤 클래스의 밑줄 문제를 추적했습니다. ActiveRecord 2.3 reflection.rb의 241 행입니다. 그 라인 인 경우 : 는 'active_record.class_name.foreign_key' 대신 'active_record.name.foreign_key' 모든 것이 잘 작동합니다. 안녕하세요, 귀하의 모든 도움과 조언에 감사드립니다. 정말 감사. – narsk

0

보트에있는 모든 사용자를 붙잡고 태그를 포함시켜야하는 이유는 무엇입니까?

그런 다음 빠른 필터를 실행하여 &을 포함하면 묻는 사용자와 동일한 태그를 가진 사용자 만 반환됩니다.

+0

이것이 제가'alias_method_chain'을 시도한 접근법입니다. 그리고 그것을 명확하게하기 위해 예제 코드를 편집했습니다. 내가 할 수없는 이유는 모든 사용자가 보트의 모든 사람을 항상보고 싶어한다는 기존 코드의 혼란이 있다는 것입니다. 그리고 나는 그것을 업스트림에 잡으려고 노력하고 있으며 잠자는 개가 거짓말을하도록하고 또한 가지고 있습니다. 다른 모든 협회들은 '일하는 것'이다. – narsk

0

어떤 레일 버전을 사용하고 있습니까? 밑줄 문제가 수정되었는지 확인하기 위해 업그레이드를 시도 했습니까? 그것은 "tag_id"또는 뭔가 '로 넣을 외래 키를 찾을 수없는 것 같습니다.

내 루비 -fu 제한되어 있으므로 런타임에 올바른 메서드 옵션을 동적으로 포함하는 방법을 잘 모르겠습니다.

그냥 명확히하는 데 도움이되므로이 두 장소에 대해 걱정해야합니다. 사용자가 볼 수있는 사용자를 필터링하여 동일한 태그가있는 사용자 만 볼 수 있도록하려고합니다. 귀하의 구조는 다음과 같습니다

사용자 < -> 티켓 < -> 보트 < -> 티켓 < -> 사용자

... 맞죠?

그래서 두 세트의 티켓을 current_user 태그가있는 티켓 세트로 필터링해야합니다.

아마도 current_user.viewable_users() 메소드가 필요하고이를 통해 모든 것을 필터링 할 수 있을까요? 기존 기능을 보존해야하는지 잘 모르겠습니다.

블레치, 내가 너를 돕는 것 같지 않아. 죄송합니다.

+0

activerecord 2.1을 사용하고 있지만 2.3.2에서도 발생합니다. 시간을내어 주셔서 감사합니다. – narsk

0

당신의 접근 방식이 문제입니다. 기존의 호출 사이트를 리팩터링 할 필요가없는 곳에서 뭔가를 해킹하는 것이 현명하다고 생각합니다.하지만 시간이 지나면 버그와 복잡성의 원인으로 다시 돌아올 것입니다.

거짓말을하는 잠자는 개가 내 경험상 당신을 무는 데 다시와 있습니다. 전형적으로 당신의 협회가 "마술"이라는 것을 모르는 미래의 개발자의 형태로, 그것을 단지 양동이로 가정합니다. 테스트 케이스를 작성해야하는 이유가 없을 수도 있습니다. 테스트 케이스를 작성하면 프로덕션 환경에있을 때만 알 수 있고 클라이언트는 불만입니다. 지금 저축 할 때가 정말로 가치가 있습니까?

Austinfrombostin이 길을 가리키고 있습니다. 다른 의미론? 다른 이름. 규칙 1 번은 항상 가능한 한 명확하게 말하는 코드를 작성합니다. 다른 것은 광기의 길입니다.